Laravel Controller trung tâm điều khiển hệ thống
NỘI DUNG BÀI VIẾT
Tại sao phải có Controller trong Laravel
Trong phần Laravel Route định tuyến yêu cầu đến giao diện chúng ta đã xử lý từ một yêu cầu tải trang đến khi hiển thị một trang web mà không cần sự có mặt của Controller, vậy Controller có cần thiết? Câu trả lời ở đây là Controller rất cần thiết để quản lý code tốt hơn, nếu không có Controller chúng ta sẽ phải viết toàn bộ phần code xử lý logic ở trong file route (routes/web.php), như vậy nếu một hệ thống website có hàng trăm route kèm theo hàng triệu dòng code xử lý logic, file route sẽ không thể quản lý được.

Controller với viết tắt là chữ C trong mô hình MVC, nó thực hiện điều hướng giữa Model và View sau khi nhận request từ trình duyệt web. ## Tạo một Laravel Controller
Để tạo mới một Controller chúng ta sử dụng câu lệnh:
php artisan make:controller MyController
Code language: CSS (css)
Bạn có thể thay MyController thành tên Controller với tên gợi nhớ, sau khi thực hiện, nó sẽ tạo ra một file MyController.php trong thư mục app/Http/Controllers. Khi một yêu cầu gửi đến hệ thống Laravel sẽ tìm trong route và route sẽ gọi đến một hàm trong một Controller theo cú pháp như sau:
Route::get('base URI','controller@method');
Code language: PHP (php)
Chúng ta sẽ thực hành vào một ví dụ để hiểu kỹ hơn: yêu cầu khi truy nhập đến http://laravel.dev/tin-tuc/bai-viet-laravel-moi-1234 sẽ đưa đến trang tin “Bài viết Laravel mới” có id là 1234. Chúng ta sẽ sử dụng luôn MainController trong bài viết Laravel Middleware, nếu project của bạn chưa có Controller này có thể tạo lại cho quen.
php artisan make:controller MainController
Code language: CSS (css)
Thêm route vào routes/web.php cho yêu cầu http://laravel.dev/tin-tuc/bai-viet-laravel-moi-1234:
Route::get('/tin-tuc/{news_id_string}', 'MainController@showNews');
Code language: JavaScript (javascript)
news_id_string chính là một tham số bắt buộc cho route, xem lại Laravel Route để nắm rõ hơn. Như vậy, yêu cầu http://laravel.dev/tin-tuc/bai-viet-laravel-moi-1234 được gửi đi nó sẽ gọi đến hàm showNews của MainController. Thực hiện thêm hàm showNews cho MainController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class MainController extends Controller
{
public function checkRole(){
echo "<br>2. MainController@checkRole";
echo "<br>Main Controller: checkRole function";
echo "<br>Thực hiện sau khi qua bộ lọc Middleware và trước khi gửi HTTP response";
}
public function showNews($news_id_string){
$news_id_arr = explode('-', $news_id_string);
$news_id = end($news_id_arr);
// Thực hiện lấy thông tin về bài viết $news_id, bài viết đưa ra ví dụ ở mức đơn giản
$news_title = 'Bài viết Laravel mới với ID là ' . $news_id;
// Các xử lý khác
return view('fontend.news-detail')->with(['news_id' => $news_id, 'news_title' => $news_title]);
}
}
Code language: HTML, XML (xml)
Trong hàm showNews khi return sẽ gọi đến view fontend.news-detail, để tạo view này trước hết chúng ta tạo thư mục fontend nằm trong resources/views, thư mục này nhằm mục đích chứa các views liên quan đến hệ thống fontend của website (bạn có thể đặt tên khác), trong thư mục fontend này tạo một file news-detail.blade.php (tại sao phải đặt tên với mở rộng là blade.php chúng ta sẽ tìm hiểu trong những bài tiếp theo) với nội dung như sau:
<html>
<head>
<title>{{ $news_title }}</title>
<link href = "https://fonts.googleapis.com/css?family=Arial:100" rel = "stylesheet" type = "text/css">
<style>
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
width: 100%;
display: table;
font-weight: 100;
font-family: 'Arial';
}
.container {
text-align: center;
display: table-cell;
vertical-align: middle;
}
.content {
text-align: center;
display: inline-block;
}
.title {
font-size: 96px;
}
</style>
</head>
<body>
<div class = "container">
<div class = "content">
<h1>{{ $news_title }}</h1>
<p>
ID bài viết: {{ $news_id }}
<br> Tiêu đề: {{ $news_title }}
<br> Nội dung: Chưa có nội dung gì cả
</p>
</div>
</div>
</body>
</html>
Code language: HTML, XML (xml)
Chúng ta thấy MainController truyền các giá trị news_title và news_id sang view news-detail, để in được giá trị chúng ta đưa biến vào {{ $value }}. Ok, giờ mở trình duyệt và xem http://laravel.dev/tin-tuc/bai-viet-laravel-moi-1234 sẽ ra kết quả như thế nào?

Bạn thử thay đổi id tin tức xem thế nào, ví dụ http://laravel.dev/tin-tuc/bai-moi-6688. Trong Controller bạn có thể thực hiện các code về logic như các thuật toán xử lý giao dịch, lấy thông tin từ database, cập nhật dữ liệu lên database… sau đó truyền dữ liệu sang view. ## Tìm hiểu Controller Middleware
Một Laravel Middleware có thể gán vào route như sau:
Route::get('profile', 'UserController@show')->middleware('auth');
Code language: PHP (php)
Tuy nhiên sẽ thuận tiện hơn nếu gán các middleware vào hàm khởi tạo __contruct của Controller:
class UserController extends Controller
{
/**
* Instantiate a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log')->only('index');
$this->middleware('subscribed')->except('store');
}
}
Code language: PHP (php)
Chúng ta đi vào một ví dụ cụ thể để hiểu hơn về Controller Middleware: Tạo ra 3 Middleware là FirstMiddleware, SecondMiddleware, ThirdMiddleware với:
- FirstMiddleware gán thông qua route.
- SecondeMiddleware và ThirdMiddleware gán thông qua contructor của Controller (Controller Middleware).
c:\xampp\htdocs\laravel-test>php artisan make:middleware FirstMiddleware
Middleware created successfully.
c:\xampp\htdocs\laravel-test>php artisan make:middleware SecondMiddleware
Middleware created successfully.
c:\xampp\htdocs\laravel-test>php artisan make:middleware ThirdMiddleware
Middleware created successfully.
Code language: CSS (css)
Nội dung các Middleware như sau: app/Http/Middleware/FirstMiddleware.php
<?php
namespace App\Http\Middleware;
use Closure;
class FirstMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
echo '<br> Middleware số 1';
return $next($request);
}
}
Code language: HTML, XML (xml)
app/Http/Middleware/SecondMiddleware.php
<?php
namespace App\Http\Middleware;
use Closure;
class FirstMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
echo '<br> Middleware số 2';
return $next($request);
}
}
Code language: HTML, XML (xml)
app/Http/Middleware/ThirdMiddleware.php
<?php
namespace App\Http\Middleware;
use Closure;
class FirstMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
echo '<br> Middleware số 3';
return $next($request);
}
}
Code language: HTML, XML (xml)
Tiếp theo chúng ta thêm route vào routes/web.php:
Route::get('/controller-middleware', [
'middleware' => 'First',
'uses' => 'TestController@testControllerMiddleware'
]);
Code language: PHP (php)
TestController chưa có, chúng ta sẽ tạo controller này:
c:\xampp\htdocs\laravel-test>php artisan make:controller TestController
Controller created successfully.
Code language: CSS (css)
Thêm hàm testControllerMiddleware vào controller này:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TestController extends Controller
{
public function __construct(){
$this->middleware('Second');
$this->middleware('Third');
}
public function testControllerMiddleware(){
echo '<br>Hàm testControllerMiddleware trong controller';
}
}
Code language: HTML, XML (xml)
À quên, chúng ta chưa đăng ký Middleware, đưa vào app/Http/Kernel.php:
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'role' => \App\Http\Middleware\RoleMiddleware::class,
'First' => \App\Http\Middleware\FirstMiddleware::class,
'Second' => \App\Http\Middleware\SecondMiddleware::class,
'Third' => \App\Http\Middleware\ThirdMiddleware::class,
];
Code language: PHP (php)
Ok, xem kết quả http://laravel.dev/controller-middleware xem ra ngô ra khoai thế nào?

Với kết quả này chúng ta thấy, không gán SecondMiddleware và ThirdMiddleware trong route nhưng khi thực hiện đường dẫn, nó chạy qua FirstMiddleware trước do gán trong route và tiếp đó là SecondMiddleware và ThirdMiddleware được khai báo trong contructor của TestController, tức là bất kỳ phương thức nào nằm trong Controller này cũng sẽ chạy qua bộ lọc SecondMiddleware và ThirdMiddleware. ## Restful Resource Controllers
Resource Controller có liên quan đến một khái niệm CRUD, có thể bạn đã nghe qua nhưng chưa rõ CRUD là gì? CRUD viết tắt của Create, Read, Update, Delete là một thuật ngữ lập trình nói đến 4 phương thức quen thuộc khi làm việc với kho dữ liệu.
Laravel giúp cho việc này trở lên đơn giản bằng cách tạo ra một controller và tự động cung cấp tất cả các phương thức CRUD. Ngoài ra, resource controller giúp cho đăng ký một route duy nhất cho tất cả các phương thức khác nhau.
Code language: PHP (php)Route::get($uri, $callback); Route::post($uri, $callback); Route::put($uri, $callback); Route::patch($uri, $callback); Route::delete($uri, $callback); Route::options($uri, $callback);
Thay vào đó chúng ta chỉ đơn giản viết một route như sau:
Route::resource('/photos', 'PhotoController');
Code language: PHP (php)
Câu lệnh tạo Resource Controller
php artisan make:controller PhotoController --resource
Code language: CSS (css)
Khi đó nếu mở PhotoController.php trong app/Http/Controllers chúng ta sẽ thấy nội dung như sau:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PhotoController extends Controller
{
public function index()
{
//
}
public function create()
{
//
}
public function store(Request $request)
{
//
}
public function show($id)
{
//
}
public function edit($id)
{
//
}
public function update(Request $request, $id)
{
//
}
public function destroy($id)
{
//
}
}
Code language: HTML, XML (xml)
Resource Controller sẽ tự động đưa vào một số hàm như index, create, store, show, edit, update, destroy, như vậy ứng với mỗi đường dẫn URI khác nhau, Resource Controller sẽ điều hướng vào các hàm khác nhau theo bảng sau:
Verb | URI | Action | Route Name |
---|---|---|---|
GET | /photos | index | photos.index |
GET | /photos/create | create | photos.create |
POST | /photos | store | photos.store |
GET | /photos/{photo} | show | photos.show |
GET | /photos/{photo}/edit | edit | photos.edit |
PUT/PATCH | /photos/{photo} | update | photos.update |
DELETE | /photos/{photo} | destroy | photos.destroy |
Như vậy, chúng ta chỉ cần thực hiện chức năng nào với một ảnh thì tìm đến hàm tương ứng trong bảng trên và thêm vào code xử lý logic là xong, như vậy sẽ tiết kiệm được nhiều thời gian cũng như quản lý code tốt hơn. Khi khai báo Resource Controller có thể có nhiều route bạn không dùng đến, Laravel cho phép hạn chế các route:
Route::resource('photo', 'PhotoController', ['only' => [
'index', 'show'
]]);
Route::resource('photo', 'PhotoController', ['except' => [
'create', 'store', 'update', 'destroy'
]]);
Code language: PHP (php)
Implicit Controllers (đã bỏ đi từ Laravel 5.2)
Implicit Controller cho phép bạn định nghĩa một route để quản lý mọi hoạt động trong controller, cú pháp của Implicit Controller như sau:
Route::controller('base URI', ControllerName);
Code language: PHP (php)
Các phương thức trong ControllerName phải bắt đầu bằng cú pháp get hoặc post, nếu bắt đầu bằng get phương thức đó sẽ quản lý các GET request, nếu bắt đầu bằng post sẽ quản lý POST request. Chúng ta sẽ bắt đầu với ví dụ sau đây: Tạo một route mới trong routes/web.php:
Route::controller('/implicit-controller', 'TestImplicitController');
Code language: PHP (php)
Tạo một controller mới tên là TestImplicitController
php artisan make:controller TestImplicitController
Code language: CSS (css)
Thêm nội dung vào controller vừa tạo app\Http\Controllers\TestImplicitController.php:
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
class TestImplicitController extends Controller {
/**
* Đáp ứng yêu cầu GET với URI /implicit-controller
*/
public function getIndex(){
echo 'Xử lý GET request cho đường dẫn http://laravel.dev/implicit-controller';
}
/**
* Đáp ứng yêu cầu GET với URI /implicit-controller/show/68
*/
public function getShow($id){
echo 'Xử lý GET request cho đường dẫn http://laravel.dev/implicit-controller/show/' . $id;
}
/**
* Đáp ứng yêu cầu GET cho URI /implicit-controller/user-dashboard
*/
public function getUserDashboard(){
echo 'Xử lý GET request cho đường dẫn http://laravel.dev/implicit-controller/user-dashboard';
}
/**
* Đáp ứng yêu cầu POST cho URI /implicit-controller/user-profile
*/
public function postUserProfile(){
echo 'Xử lý POST request cho đường dẫn http://laravel.dev/implicit-controller/user-profile';
}
}
Code language: HTML, XML (xml)
OK, bây giờ chúng ta sẽ thử các đường dẫn http://laravel.dev/implicit-controller/user-dashboard http://laravel.dev/implicit-controller/show/68
Cảm ơn các bạn đã đọc.
Các bạn có thể tham khảo các bài viết hay về Laravel tại đây.
Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.
Nguồn tham khảo: allaravel
Leave a Reply