Tuyệt vời, bạn đã có hệ thống CRUD Page hoàn chỉnh. Bây giờ mình sẽ hướng dẫn phân quyền chi tiết ch
@extends('layouts.admin')
@section('content')
<div class="container mt-4">
<form action="{{ route('admin.pages.store') }}" method="POST">
@csrf
<div class="mb-3">
<label class="form-label">Tiêu đề</label>
<input type="text" name="title" class="form-control" value="{{ old('title') }}" required>
</div>
<div class="mb-3">
<label class="form-label">Slug</label>
<input type="text" name="slug" class="form-control" value="{{ old('slug') }}" required>
</div>
<hr>
<div class="mb-3">
<label for="image" class="form-label">Ảnh</label>
<div class="input-group">
<input id="image_url" class="form-control" type="text" name="image" value="{{ old('image', $page->image ?? '') }}">
<button type="button" class="btn btn-secondary" onclick="openLfm('image_url', 'image_preview')">Chọn ảnh</button>
</div>
<img id="image-preview" src="{{ old('image', $page->image ?? '') }}" style="max-height: 150px; margin-top: 10px">
</div>
<div class="mb-3">
<label for="content_vi" class="form-label">Nội dung (Tiếng Việt)</label>
<textarea name="content_vi" class="form-control editor" rows="10">{{ old('content_vi', $page->content_vi ?? '') }}</textarea>
</div>
<div class="mb-3">
<label for="content_en" class="form-label">Nội dung (English)</label>
<textarea name="content_en" class="form-control editor" rows="10">{{ old('content_en', $page->content_en ?? '') }}</textarea>
</div>
<div>
<button type="submit" class="btn btn-primary">Tạo trang</button>
<a href="{{ route('admin.pages.index') }}" class="btn btn-light">Quay lại</a>
</div>
</form>
</div>
@endsection
@section('scripts')
<script src="https://cdn.ckeditor.com/ckeditor5/39.0.1/classic/ckeditor.js"></script>
<script>
const editors = {};
function insertImageToEditor(editorName, imageUrl) {
const editor = editors[editorName];
if (editor) {
editor.model.change(writer => {
const imageElement = writer.createElement('imageBlock', {
src: imageUrl
});
editor.model.insertContent(imageElement, editor.model.document.selection);
});
}
}
function openLfmForEditor(editorName) {
window.open('/laravel-filemanager?type=Images', 'fm', 'width=800,height=600');
window.SetUrl = function(items) {
const url = Array.isArray(items) ? items[0].url : items.url;
insertImageToEditor(editorName, url);
};
}
document.querySelectorAll('.editor').forEach((textarea, index) => {
const name = textarea.getAttribute('name') || 'editor_' + index;
ClassicEditor.create(textarea, {
toolbar: {
items: [
'heading', '|'
, 'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|'
, 'undo', 'redo'
]
}
}).then(editor => {
editors[name] = editor;
// Tạo nút chèn ảnh
const insertBtn = document.createElement('button');
insertBtn.type = 'button';
insertBtn.className = 'btn btn-sm btn-secondary mt-2';
insertBtn.innerText = 'Chèn ảnh từ thư viện';
insertBtn.addEventListener('click', () => {
openLfmForEditor(name);
});
// Gắn nút sau editor
textarea.parentNode.appendChild(insertBtn);
}).catch(error => {
console.error(error);
});
// Thêm nút chèn ảnh ngay sau textarea
const button = document.createElement('button');
button.type = 'button';
button.innerText = 'Chèn ảnh từ thư viện';
button.className = 'btn btn-sm btn-secondary mt-2';
button.onclick = () => openLfmForEditor(name);
textarea.parentNode.insertBefore(button, textarea.nextSibling);
});
</script>
<script src="{{ asset('js/lfm.js') }}"></script>
@endsection
✅ 1. Cập nhật middleware và đăng ký permission check
✅ 2. Cập nhật Route
✅ 3. Cập nhật giao diện Blade (ẩn nút theo quyền)
Ví dụ trong resources/views/admin/pages/index.blade.php:
resources/views/admin/pages/index.blade.php:✅ 4. Gợi ý: Thêm Policy (nếu muốn granular hơn)
✅ 5. Đảm bảo bạn có quyền trong DB
PreviousĐể phân quyền CRUD cho các trang (pages) trong Laravel sử dụng package spatie/laravel-permissionNextTuyệt, để xây dựng giao diện quản lý người dùng và phân quyền với spatie/laravel-permission
Last updated