Route param
Trong các bài học trước, chúng ta đã tìm hiểu về query params. Tuy nhiên, như các bạn đều biết, đôi lúc tham số của chúng ta được định hẳn thành một route, tức là thay vì /posts?id=123, chúng ta sẽ có URL dạng /posts/123. Và Laravel, không có gì khác lạ, cung cấp cho chúng ta giải pháp cho vấn đề này. Cụ thể, nếu param là một route query, chúng ta có hàm dưới đây:
1 2 3 4 |
Route::get('/posts', function() { $id = request('id'); return view('post', ['id' => id]); }); |
Đối với route param, vì đó là một route hẳn hoi, nên chúng ta không thể dùng hướng bên trên để giải quyết, và $id cũng không được “tách chiết” từ request được, vì chúng ta không param map. Thay vào đó, $id nằm trực tiếp trong closure định nghĩa response. Tức là:
1 2 3 |
Route::get('/posts/{id}', function($id) { return view('post', $id); }); |
Controllers
Giả sử, chúng ta có những định nghĩa route sau đây:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// Posts Route::get('/posts/', function() { return view('posts'); }); Route::get('/posts/{id}', function($id) { return view('post', $id); }); Route::post('/post', function() { // Vì post request sẽ liên quan đến kiến thức ở các bài sau, // hiện tại, tôi chỉ đơn giản là cho redirect về '/posts'. return redirect('/posts'); }); // Categories Route::get('/categories/', function() { return view('categories'); }); Route::get('/categories/{id}', function($id) { return view('category', $id); }); // Authors Route::get('/authors/', function() { return view('authors'); }); Route::get('/authors/{id}', function($id) { return view('author', $id); }); |
Việc phải xử lí tất cả trong web.php tuy có lợi ích là “tất cả trứng đều nằm chung giỏ”, tuy nhiên, nếu số lượng routes tăng lên nhiều thì lợi bất cập hại, dễ khiến bạn nổi điên. Và sau một đêm mất ngủ, khi bật máy tính, bạn sẽ tức quá hóa rồ hệt như trong bức ảnh bên dưới:
Thay vì uống thuốc giảm đau, bạn có thể sử dụng Controller để chia nhỏ vấn đề ra để dễ bề thao tác. Nhưng chia như thế nào là hợp lí? Câu trả lời được nhiều người đồng tình nhất là bạn gom chung các routes giống nhau về cùng một Controller. Trong ví dụ của chúng ta, tôi sẽ có đúng 3 Controller là PostController, CategoryController và AuthorController. Dù chúng ta có thể tự tạo các file controller.php bằng tay, nhưng để dễ dàng và chính xác hơn, mọi người đều dùng command có sẵn. Và với ví dụ đã cho, tôi chạy 3 commands tương ứng với 3 controllers:
1 2 3 |
php artisan make:controller PostController php artisan make:controller CategoryController php artisan make:controller AuthorController |
Khi tạo các controllers với commands trên, chúng sẽ được nằm tại app/Http/Controllers. Bây giờ, chúng ta mở PostController:
1 2 3 4 5 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class PostController extends Controller { } |
Bây giờ, tôi định nghĩa thêm hai functions trong PostController như bên dưới. Thực chất, chúng chỉ là wrapper cho hai closures của ‘/posts’ routes:
1 2 3 4 5 6 7 8 9 10 11 |
class PostController extends Controller { public function index() { return view('posts'); } public function show($id){ return view('post', ['id' => $id]); } public function store() { return redirect('/posts'); } } |
Như vậy, chúng ta đã đưa nội dung của hai closures vào PostController. Bước cuối cùng, ta chỉ việc reference PostController@index và PostController@show vào web.php:
1 2 3 4 |
// routes/web.php Route::get('/posts', 'PostController@index'); Route::get('/posts/{id}', 'PostController@show'); Route::post('/posts', 'PostController@store'); |
Lưu ý, các tham số thứ hai của chúng ta hiện tại là String chứ không còn là closure nữa. Và như vậy là xong. Sau này, khi bạn muốn thay đổi nội dung về ‘/posts’ routes, bạn chỉ cần thay đổi nội bộ tập tin PostController mà thôi. Vừa dễ tìm lại vừa dễ chỉnh sửa hơn là tập trung lại một nơi tại web.php. Cuối cùng, nhiệm vụ của các bạn là làm tương tự với CategoryController và AuthorController. Chúc các bạn thành công và hãy đừng xóa project. Các bài viết sau sẽ tiếp nối với những gì đã được trình bày trong bài này.