false, 'count' => 0, 'error' => null]; try { $pdo = getPdoConnection(); $pdo->exec("CREATE TABLE IF NOT EXISTS `articles` ( `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `title` VARCHAR(255) NOT NULL, `slug` VARCHAR(255) NOT NULL UNIQUE, `category` VARCHAR(100) NOT NULL DEFAULT 'Laravel', `summary` VARCHAR(500) NOT NULL, `content` TEXT NOT NULL, `author` VARCHAR(120) NOT NULL DEFAULT 'Admin', `views` INT UNSIGNED NOT NULL DEFAULT 0, `published_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP, `created_at` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"); $count = (int) $pdo->query("SELECT COUNT(*) FROM `articles`")->fetchColumn(); if ($count === 0) { $pdo->exec("INSERT IGNORE INTO `articles` (`id`, `title`, `slug`, `category`, `summary`, `content`, `author`, `views`, `published_at`) VALUES (1, 'Làm chủ Laravel Routing nâng cao và Route Group', 'lam-chu-laravel-routing-nang-cao', 'Routing', 'Tìm hiểu cách khai báo tham số động, biểu thức chính quy Regex, Named Routes và gom nhóm prefix admin.', 'Laravel cung cấp hệ thống định tuyến (Routing) vô cùng linh hoạt và mạnh mẽ. Bạn có thể bắt tham số bắt buộc như /articles/page/{page}, tham số tùy chọn kèm ràng buộc Regex where(''slug'', ''[a-z0-9-]+''), đặt tên định danh bằng ->name() và gom nhóm các route quản trị với Route::prefix(''admin'').', 'Hoàng Vũ', 320, '2026-01-10 08:30:00'), (2, 'Xây dựng RESTful Resource Controller chuẩn mực trong Laravel', 'xay-dung-restful-resource-controller-laravel', 'Controller', 'Khám phá 7 phương thức chuẩn của Resource Controller: index, create, store, show, edit, update và destroy.', 'Chỉ với một dòng lệnh Route::resource(''articles'', ArticleController::class), Laravel tự động ánh xạ 7 chuẩn RESTful HTTP Verbs (GET, POST, PUT/PATCH, DELETE) tương ứng với 7 action trong ArticleController, giúp mã nguồn rõ ràng và tuân thủ chuẩn công nghiệp.', 'Minh Tuấn', 285, '2026-01-12 09:15:00'), (3, 'Tổ chức giao diện kế thừa với Blade Layout, Partials và Stack', 'to-chuc-giao-dien-voi-blade-layout-stack', 'Blade View', 'Sử dụng @extends, @section, @yield, @include và @stack/@push để xây dựng kiến trúc giao diện mô-đun hóa.', 'Blade Template Engine cho phép tách biệt khung giao diện chính (layouts/app.blade.php) và các thành phần con (partials/nav, partials/footer). Đặc biệt, cơ chế @stack(''styles'') và @stack(''scripts'') giúp các trang con đẩy CSS/JS riêng biệt vào đúng vị trí mong muốn.', 'Thu Hà', 410, '2026-01-15 14:20:00'), (4, 'Tái sử dụng UI hiệu quả bằng Anonymous & Class-based Blade Components', 'tai-su-dung-ui-bang-blade-components', 'Components', 'Tạo các thẻ giao diện tùy chỉnh , , gọn nhẹ, dễ bảo trì.', 'Thay vì lặp lại hàng chục dòng HTML Bootstrap cho mỗi ô nhập liệu hay thông báo, Blade Component (, , ) giúp đóng gói giao diện, truyền dữ liệu qua thuộc tính (props) và tự động hiển thị trạng thái lỗi validation.', 'Hoàng Vũ', 195, '2026-01-18 10:45:00'), (5, 'Bảo mật Form với CSRF, Method Spoofing và Route Model Binding', 'bao-mat-form-csrf-method-spoofing-model-binding', 'Security & Eloquent', 'Kết hợp @csrf, @method(''PUT''/''DELETE''), Validation và Implicit Route Model Binding trong thực tế.', 'Trong Laravel, mọi biểu mẫu POST/PUT/DELETE đều được bảo vệ khỏi tấn công giả mạo truy vấn qua @csrf. Bên cạnh đó, Implicit Route Model Binding tự động truy vấn bản ghi Article theo ID hoặc Slug và trả về lỗi 404 nếu không tìm thấy.', 'Hải Đăng', 540, '2026-01-20 16:00:00')"); $count = 5; } $dbStatus['connected'] = true; $dbStatus['count'] = $count; } catch (Throwable $e) { $dbStatus['error'] = $e->getMessage(); } $exercises = [ [ 'num' => '01', 'folder' => 'Bai01', 'title' => 'Routing nâng cao, Regex, Named Routes & Route Group', 'desc' => 'Khai báo tham số động {page}, tham số tùy chọn {slug?} kèm Regex where(), Named Routes và gom nhóm prefix admin. Tích hợp trình mô phỏng kiểm tra khớp URL Route trực tiếp.', 'badge' => 'Routing', 'color' => 'primary', 'icon' => 'bi-signpost-split', 'laravel_files' => ['routes/web.php'], ], [ 'num' => '02', 'folder' => 'Bai02', 'title' => 'ArticleController RESTful (7 Actions) & Route::resource', 'desc' => 'Triển khai đầy đủ 7 action chuẩn RESTful (index, create, store, show, edit, update, destroy), bảng ánh xạ HTTP Verb / URI / Route Name và danh sách bài viết thực tế.', 'badge' => 'RESTful Controller + SQL', 'color' => 'success', 'icon' => 'bi-diagram-3', 'laravel_files' => ['app/Http/Controllers/ArticleController.php', 'routes/web.php', 'Bai02/articles.sql'], ], [ 'num' => '03', 'folder' => 'Bai03', 'title' => 'Blade Layout chung, Partials & @stack / @push', 'desc' => 'Thiết kế Master Layout layouts/app.blade.php, tách biệt partials.nav, partials.footer và quản lý tài nguyên động với @stack(\'scripts\') / @push(\'scripts\').', 'badge' => 'Blade Layout', 'color' => 'info', 'icon' => 'bi-layout-text-window-reverse', 'laravel_files' => ['resources/views/layouts/app.blade.php', 'resources/views/partials/nav.blade.php', 'resources/views/partials/footer.blade.php'], ], [ 'num' => '04', 'folder' => 'Bai04', 'title' => 'Blade Components tái sử dụng: & ', 'desc' => 'Xây dựng Class & View Component (type, message, dismissible) và (name, label, type, value, placeholder, @error) để tái sử dụng trong biểu mẫu.', 'badge' => 'Blade Components', 'color' => 'warning', 'icon' => 'bi-boxes', 'laravel_files' => ['app/View/Components/Alert.php', 'app/View/Components/Input.php', 'resources/views/components/alert.blade.php', 'resources/views/components/input.blade.php'], ], [ 'num' => '05', 'folder' => 'Bai05', 'title' => 'Form Tạo/Sửa Bài viết với @csrf, @method(\'PUT\') & Validation', 'desc' => 'Thực nghiệm trực tiếp tạo mới (POST) và chỉnh sửa (PUT) bài viết vào bảng articles trên MySQL, kiểm tra lỗi Validation và hiển thị lỗi inline với @error.', 'badge' => 'Form + Validation + SQL', 'color' => 'danger', 'icon' => 'bi-ui-checks-grid', 'laravel_files' => ['resources/views/articles/create.blade.php', 'resources/views/articles/edit.blade.php', 'Bai05/articles.sql'], ], [ 'num' => '06', 'folder' => 'Bai06', 'title' => 'Implicit Route Model Binding (Theo ID & Theo Slug)', 'desc' => 'Thử nghiệm tự động ánh xạ bản ghi Eloquent Model Article qua /articles/{article} và /articles/slug/{article:slug}, tự động trả về HTTP 404 nếu không tồn tại.', 'badge' => 'Model Binding + SQL', 'color' => 'primary', 'icon' => 'bi-link-45deg', 'laravel_files' => ['app/Models/Article.php', 'routes/web.php', 'resources/views/articles/show.blade.php', 'Bai06/articles.sql'], ], [ 'num' => '07', 'folder' => 'Bai07', 'title' => 'Form Xóa an toàn với Method Spoofing (@method(\'DELETE\'))', 'desc' => 'Kết hợp @csrf, @method(\'DELETE\') và hộp thoại xác nhận JS confirm() để xóa bài viết an toàn khỏi CSDL MySQL, kèm chức năng khôi phục nhanh dữ liệu mẫu.', 'badge' => 'Security Delete + SQL', 'color' => 'secondary', 'icon' => 'bi-shield-lock', 'laravel_files' => ['resources/views/articles/index.blade.php', 'app/Http/Controllers/ArticleController.php', 'Bai07/articles.sql'], ], [ 'num' => '08', 'folder' => 'Bai08', 'title' => 'Component & Chèn CSS tùy chỉnh qua @stack(\'styles\')', 'desc' => 'Đóng gói Component đa biến thể (variant, size, icon, type) và đẩy CSS hiệu ứng riêng biệt từ view con lên thẻ bằng @push(\'styles\').', 'badge' => 'Button & Styles Stack', 'color' => 'success', 'icon' => 'bi-palette2', 'laravel_files' => ['app/View/Components/Button.php', 'resources/views/components/button.blade.php', 'resources/views/layouts/app.blade.php'], ], [ 'num' => '09', 'folder' => 'Bai09', 'title' => 'Tối ưu hóa Named Routes & Breadcrumb động theo từng trang', 'desc' => 'Sử dụng helper route() xuyên suốt các Blade View thay cho URL cứng và tự động sinh thanh điều hướng Breadcrumb động theo ngữ cảnh từng action.', 'badge' => 'Named Routes & Breadcrumb', 'color' => 'info', 'icon' => 'bi-compass', 'laravel_files' => ['resources/views/partials/breadcrumb.blade.php', 'resources/views/articles/index.blade.php', 'resources/views/articles/show.blade.php'], ], ]; ?> Chương 4 - Lab 07: Laravel Routing nâng cao, Controller RESTful, Blade & Form
CHƯƠNG 4 • LAB 07

Laravel: Routing nâng cao, Controller RESTful, Blade & Form

Tổ chức song song 2 lớp: Cấu trúc dự án Laravel 10 chuẩn & 9 Bài thực nghiệm trực quan chạy trực tiếp trên trình duyệt

Về Trang chủ Document MySQL (`.articles`): bài viết sẵn sàng Chế độ Demo (Chưa kết nối MySQL)

Danh sách 9 Bài tập Thực hành (Lớp 2)

Nhấn vào từng bài để chạy thử nghiệm trực tiếp & xem mã nguồn Laravel
Bài

Tệp Laravel liên quan:
Mở Bài tập
Cấu trúc chuẩn dự án Laravel tại gốc `Lab07_Laravel_Routing_Blade/` (Lớp 1)
Laravel 10 Standard Structure
Lab07_Laravel_Routing_Blade/
├── app/
│   ├── Http/Controllers/
│   │   └── ArticleController.php       # 7 RESTful actions + Validation
│   ├── Models/
│   │   └── Article.php                 # Eloquent Model Article
│   └── View/Components/
│       ├── Alert.php                   # Component <x-alert>
│       ├── Button.php                  # Component <x-button>
│       └── Input.php                   # Component <x-input>
├── database/
│   ├── migrations/
│   │   └── 2026_01_01_000001_create_articles_table.php
│   └── seeders/
│       └── ArticleSeeder.php
├── resources/views/
│   ├── layouts/app.blade.php           # Master Layout + @stack
│   ├── partials/
│   │   ├── nav.blade.php
│   │   ├── footer.blade.php
│   │   └── breadcrumb.blade.php
│   ├── components/
│   │   ├── alert.blade.php
│   │   ├── input.blade.php
│   │   └── button.blade.php
│   └── articles/
│       ├── index.blade.php
│       ├── create.blade.php
│       ├── edit.blade.php
│       └── show.blade.php
├── routes/
│   └── web.php                         # Advanced Routes & Route::resource
├── Bai01/ ... Bai09/                   # 9 Bài thực nghiệm trực quan
├── composer.json
├── .env.example
├── artisan
└── lab07_database.sql
Điểm nổi bật của kiến trúc 2 lớp trong Lab 07:
  • Lớp 1 (Mã nguồn Laravel chuẩn): Đầy đủ `routes/web.php`, `ArticleController.php`, Model `Article.php`, Migration, Seeder, Blade Layout, Partials, Components và 4 trang CRUD `articles/*.blade.php`.
  • Lớp 2 (Bài tập thực nghiệm `Bai01` → `Bai09`): Chạy trực tiếp trên XAMPP/Laragon hoặc PHP Built-in Server không cần cài `vendor/`, kết nối trực tiếp tới bảng `articles` trong MySQL qua `db_config.php`.
  • Tích hợp SQL độc lập: Các bài có thao tác dữ liệu (`Bai02`, `Bai05`, `Bai06`, `Bai07`) đều có sẵn tệp `articles.sql` và cơ chế tự động khởi tạo bảng + nạp dữ liệu mẫu.