Toidicode.com

Toidicode.com

BASIC TO ADVANCE

Bài 17: Controller trong Laravel 8

Như các bạn đã thấy thì ở các bài trước mình thường viết code logic vào trong call back function của route. Lý do mình viết code vào trong đó là cho mọi người dễ hình dung logic vì nó được đặt trong 1 file luôn. Nhưng trên thực tế ứng dụng của mọi người sẽ có rất nhiều route, lúc này nếu như code logic mà đặt trong route luôn thì file này sẽ rất lớn và code lúc này sẽ trở nên rối hơn.

Trong Laravel, Controller sẽ là nơi chứa các logic code thay thế cho route. Lúc này bạn có thể gom nhóm một loạt các logic có chung một nghiệp vụ vào một class cho dễ quản lý.

VD: Controller UserController sẽ chứa các logic liên quan đến user như hiển thị, tạo mới, update, xóa,...

Mặc định, Controller trong Laravel được đặt trong thư mục app/Http/Controllers.

1. Tạo controller trong Laravel.

Trong Laravel tất cả các controller đều phải kế thừa class Controller(App\Http\Controllers\Controller). Nếu không kế thừa class Controller này thì bạn sẽ không sử dụng được các tính năng kèm theo của Laravel như middleware, authorize,... bằng việc gọi phương thức.

Để tạo mới một controller trong Laravel các bạn sử dụng artisan command hoặc có thể tạo bằng tay. Đối artisan commadn các bạn sử dụng câu lệnh:

php artisan make:controller ControllerName

Trong đó: ControllerName là tên của controller các bạn muốn tạo.

VD: Mình sẽ tạo mới một controller là ContactController.

php artisan make:controller ContactController

Lúc này Laravel sẽ generate cho các bạn một file ContactController.php nằm trong thư mục app/Http/Controllers có nội dung như sau (lưu ý: nội dung có thể thay đổi tùy vào version):

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ContactController extends Controller
{
    //
}

Trong trường hợp bạn muốn tạo controller trong một thư mục con nằm trong app/Http/Controllers thì các bạn chỉ cần điền ControllerName là path chứa thư mục con đó kèm controller name.

VD: Tạo mới controller ContactController trong thư mục app/Http/Controllers/Pages.

php artisan make:controller Pages/ContactController

Lúc này ở route các bạn muốn assign logic cho controller các bạn truyền tham số thứ 2 là một mảng với tham số đầu tiên là class path của controller, tham số thứ 2 là method thực thi.

VD: Mình sẽ thêm method show vào trong ContactController vừa tạo ở trên để hiển thị view đồng thời assign vào route với path /contact.

- app/Http/Controllers/ContactController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ContactController extends Controller
{
    public function show()
    {
        return view('contact.form');
    }
}

- routes/web.php

use App\Http\Controllers\ContactController;
use Illuminate\Support\Facades\Route;

Route::get('/contact', [ContactController::class, 'show']);

2. Single Action Controller.

Trong một vài trường hợp nếu bạn chỉ muốn một controller class thực thi một hành động duy nhất, thì các bạn cũng có thể thêm một phương thức như phần trên rồi assign chúng vào route. Hoặc có thể viết chúng trong phương thức __invoke rồi trong route các bạn sẽ không cần phải truyền thêm phương thức.

VD: Single action Controller.

- app/Http/Controllers/ProvisionServer.php

class ProvisionServer extends Controller
{
    /**
     * Provision a new web server.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function __invoke()
    {
        // ...
    }
}

- routes/web.php

use App\Http\Controllers\ProvisionServer;
use Illuminate\Support\Facades\Route;

Route::get('/contact', ProvisionServer::class);

Đối với trường hợp các bạn muốn tạo một controller như trên, các bạn có thể truyền thêm option --invokable khi chạy make:controller artisan command.

VD: Tạo single action controller ProvisionServer

php artisan make:controller ProvisionServer --invokable

3. Middleware trong Controller.

Ở bài middleware mình mới chỉ hướng dẫn mọi người cách assign middleware vào trong route thôi. Và trong Laravel các bạn có thể assign middleware vào trong controller với method middleware.

VD: Mình sẽ assigne middleware auth vào trong controller UserController.

class UserController extends Controller
{
    /**
     * Instantiate a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }
}

Nếu bạn muốn chỉ định middleware hoạt động cho một vài method nào đó trong controller các bạn có thể đặt middleware trong method đó. Hoặc sử dụng phương thức only.

VD: middleware cho hành động edit trong UserController.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth')->only('edit');
    }

    public function edit()
    {
        //
    }
}

Hoặc

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    public function edit()
    {
        $this->middleware('auth');
    }
}

Nếu bạn muốn middleware hoạt động với tất cả action trong controller và bỏ qua một vài action nào đó, các bạn có thể sử dụng phương thức except.

VD: assign middleware auth cho controller UserController và bỏ qua action indexshow.

$this->middleware('auth')->except(['index', 'show']);

// hoặc

$this->middleware('auth')->except('index', 'show');

4. Resource Controller.

Resource controller trong Laravel là một dạng controller cung cấp sẵn các action index, create, store, show, edit, update, destroy để thực thi các hành động CRUD data.

Để tạo resource controller trong Laravel các bạn sử dụng command:

php artisan make:controller ControllerName --resource

Trong đó: ControllerName là tên của controller các bạn muốn tạo.

VD: Mình sẽ tạo một resource controller là PhotoController.

php artisan make:controller PhotoController --resource

Lúc này Laravel sẽ sinh ra cho chúng ta file app/Http/Controllers/PhotoController.php có nội dung như sau:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PhotoController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

Lúc này để assign route cho resource controller các bạn sử dụng phương thức resource.

VD: routes/web.php

use App\Http\Controllers\PhotoController;
use Illuminate\Support\Facades\Route;

Route::resource('photos', PhotoController::class);

Để xem danh sách các route các bạn sử dụng command:

php artisan route:list

Kết quả:

Route list trong laravel

Như các bạn cũng đã thấy các action tương ứng với các route, route name,... Mình khỏi phải giải thích nhiều :D

Trong trường hợp bạn muốn sử dụng thêm route model binding trong route (xem hướng dẫn) trong resource controller các bạn có thể sử dụng command

php artisan make:controller ControllerName --resource --model=ModelName

Trong đó ModelName là model mà bạn muốn auto binding.

Trong một số trường hợp, bạn không muốn sử dụng tất cả các action trong controller thì ở route các bạn sử dụng phương thức except để xác định các action không muốn sử dụng.

VD: Loại bỏ action indexshow trong controller PhotoController.

Route::resource('photos', PhotoController::class)->except([
    'index', 'show'
]);

Hoặc các bạn có thể sử dụng phương thức only để xác định các action được phép sử dụng.

VD: Chỉ sử dụng action indexshow trong controller PhotoController.

Route::resource('photos', PhotoController::class)->only([
    'index', 'show'
]);

Trong một số trường hợp, bạn muốn thay đổi route name cho một action nào đó trong resource controller các bạn có thể sử dụng phương thức names.

VD: Thay đổi route name cho action create thành photo.build.

Route::resource('photos', PhotoController::class)->names([
    'create' => 'photos.build'
]);

Bạn cũng có thể thay đổi route parameters cho resource controller, bằng cách sử dụng phương thức parameters.

VD: Thay đổi parameter photo thành photo_id.

Route::resource('photos', PhotoController::class)->parameters([
    'users' => 'photos_id'
]);

5. API Resource Routes.

Trong trường hợp ứng dụng của bạn chỉ cần cung cấp các action như một API Resfull. Thì bạn có thể sử dụng API Resource route. Lúc này các route sẽ bỏ qua các action create, edit.

VD: Chuyển PhotoController trên về API resource route.

use App\Http\Controllers\PhotoController;

Route::apiResource('photos', PhotoController::class);

Bạn có thể chạy route:list để xem kết quả:

Route list trong Laravel

6. Lời kết.

Về controller trong Laravel, chúng ta tạm dừng ở đây thôi nhé. Bài sau mình sẽ giới thiệu với mọi người về URL generation trong Laravel 8.

Đăng ký nhận tin.

Chúng tôi chỉ gửi tối đa 2 lần trên 1 tháng. Tuyên bố không spam mail!

Vũ Thanh Tài

About author
The best way to learn is to share
Xem tất cả bài đăng

9 Comments

cho em hỏi cái

nguoilahoidap

3 năm trước

cái pages/Controller .. trong route phải làm sao nó biết vào pages tìm Controller vậy ạ hay tự động nó vào pages tìm luôn ạ

nguoilahoidap

3 năm trước

cái pages/Controller .. trong route phải làm sao nó biết vào pages tìm Controller vậy ạ hay tự động nó vào pages tìm luôn ạ

nguoilahoidap

3 năm trước

Chào nguoilahoidap,

Bạn sử dụng use để định danh namspace của Controller đó à.

Vũ Thanh Tài

3 năm trước

anh cho em hỏi khi tạo controller --resource thì những method index, store, update được đặt tên ở đâu mà khi mình chạy route:list nó lại có sẵn cột name vậy

stranger

3 năm trước

Chào stranger,

Khi sử dụng route resource thì Laravel sẽ tự động maping route name với các phương thức index, create, store,...

Chi tiết bạn có thể xem ở đây 

Vũ Thanh Tài

3 năm trước

Em chào anh ạ, anh cho em hỏi:
như ví dụ đầu tiên em có gọi controller thì trình duyệt báo lỗi: "Target class [ContactController] does not exist" dù em đã kiểm tra rất kỹ file ContactController.php(app\http\controllers)
em đang chạy trên môi trường laragon, cổng 8080 và ssl 443 ạ!
mong anh xem và phản hồi sớm giúp em, em xin chân thành cảm ơn ạ!

Chính

3 năm trước

dòng báo lỗi là :"catch (ReflectionException $e) {

throw new BindingResolutionException("Target class [$concrete] does not exist.", 0, $e);

}"tương tự với middleware cũng lỗi y hệt ạ!

Chính

3 năm trước

Chào Chính,

Sorry bạn vì reply trễ. Bạn đã fix được lỗi này chưa ạ?

Vũ Thanh Tài

3 năm trước

Bình luận

Captcha