Ra mắt hai series mới cực hot Trí tuệ nhân tạo A đến ZPython công cụ không thể thiếu khi nghiên cứu Data science, Machine learning.

Laravel Controller trung tâm điều khiển hệ thống

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.

Mô hình MVC

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

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');

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

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');

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]);
    }
}

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>

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?

Ví dụ về Controller trong Laravel

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');

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');
    }
}

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.

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);
    }
}

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);
    }
}

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);
    }
}

Tiếp theo chúng ta thêm route vào routes/web.php:

Route::get('/controller-middleware', [
   'middleware' => 'First',
   'uses'       => 'TestController@testControllerMiddleware'
]);

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.

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';
    }
}

À 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,
];

Ok, xem kết quả http://laravel.dev/controller-middleware xem ra ngô ra khoai thế nào?

Ví dụ về Controller Middleware trong Laravel

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.

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');

Câu lệnh tạo Resource Controller

php artisan make:controller PhotoController --resource

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)
    {
        //
    }
}

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'
]]);

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);

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');

Tạo một controller mới tên là TestImplicitController

php artisan make:controller TestImplicitController

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';
   }
}

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ÁC BÀI VIẾT KHÁC

FirebirD

Đam mê Toán học, Lập trình. Sở thích chia sẻ kiến thức, Phim hài, Bóng đá, Cà phê sáng với bạn bè.

Laravel Middleware cơ chế bộ lọc trung gian

HTTP Request trong Laravel

3 Bình luận trong "Laravel Controller trung tâm điều khiển hệ thống"

  1. Minh

    3 years ago

    Phản hồi

    Hi adm, Phần tên class cũng SecondMiddleware và ThirdMiddleware đang để là FirstMiddleware ạ!

  2. Yayaya

    2 years ago

    Phản hồi

    Phần này cũng như ở bài middware trước, trong laravel 8 thay đoạn "Route::get('/tin-tuc/{news_id_string}', 'MainController@showNews');" thành "Route::get('/tin-tuc/{string_id}',[MainController::class,'showNews']);";

  3. bb

    1 year ago

    Phản hồi

    ad có thời gian thì cập nhật lại phần return controller nhé :))) tkanks ad!!!

Thêm bình luận