01/10/2018, 15:41

Bài 6: Laravel – Controllers

Basic Controllers Trong framework MVC, ký tự ‘C’ là viết tắt Controller. Nó hoạt động như một điều phối luồng giữa Views và Models. Tạo một Controller Mở command prompt hoặc terminal tùy vào bạn đang xài window hay linux, bằng việc sử dụng Artisan CLI(Command Line ...

Basic Controllers

Trong framework MVC, ký tự ‘C’ là viết tắt Controller. Nó hoạt động như một điều phối luồng giữa Views và Models.

Tạo một Controller

Mở command prompt hoặc terminal tùy vào bạn đang xài window hay linux, bằng việc sử dụng Artisan CLI(Command Line Interface) để tạo controller.

php artisan make:controller <controller-name>

Thay thế <controller-name> với tên controller bạn muốn đặt.

Nếu bạn muốn thêm đối số để khi tạo ra file controller đồng thời cũng tạo một số phương thức CRUD thì bạn có thể thêm đối số –resource sau tên controller như sau:

php artisan make:controller <controller-name> –resource    

Lưu ý: phiên bản cũ thì dùng –plain để tạo constructor (đã remove ở version dùng tutorial này)

File controller được tạo sẽ nằm ở app/Http/Controllers. Bạn sẽ thấy code cơ bản đã được tạo sẳn cho bạn và bạn có thể thêm code của bạn vào.

Controller đã tạo có thể được gọi từ file định tuyến routes/web.php với cú pháp sau:

Syntax

Route::get(‘base URI’,’controller@method’);

Example

Step 1: tạo controller UserController.

php artisan make:controller UserController –-resource

Step 2: sau khi thành công bạn sẽ thấy output sau:

bai6_create_user_controller

Step 3: bạn có thể thấy controller đã tạo ở app/Http/Controller/UserController.php với một số code cơ bản đã được ghi cho bạn, và bạn có thể thêm code của bạn dựa vào nhu cầu của bạn.

Controller Middleware

Chúng ta đã thấy middleware ở bài trước đó và nó có thể được sử dụng với controller.

Middleware cũng có thể được phân công tới định tuyến(route) của controller hoặc bên trong constructor của controller. Bạn có thể sử dụng phương thức middleware để phân công middleware tới controller. Đăng ký middleware cũng có thể bị giới hạn tới các phương thức nhất định của controller.

Phân công Middleware tới Route

Route::get(‘profile’, [

   ‘middleware’ => ‘auth’,

   ‘uses’ => ‘UserController@showProfile’

]);

Ở đây chúng ta đang phân công middleware “auth” tới UserController trong định tuyến profile (profile route).

Phân công Middleware bên trong Constructor của Controller

class UserController extends Controller {

   public function __construct(){

      $this->middleware(‘auth’);

   }

}

Ở đây chúng ta đang phân công middleware ‘auth’ sử dụng phương thức middleware trong constructor của controller.

Example

Step 1: thêm các dòng sau tới file routes/web.php và lưu nó lại.

Route::get(‘/usercontroller/path’,[

   ‘middleware’ => ‘First’,

   ‘uses’ => ‘UserController@showPath’

]);

Tốt nhất là để nó ở cuối file.

Step 2 : tạo một middleware gọi là FirstMiddleware bằng cách thực hiện lệnh sau:

php artisan make:middleware FirstMiddleware

Step 3 : thêm các dòng code trong phương thức handle trong file middleware vừa mới tạo ở app/Http/Middleware.

class FirstMiddleware {

   public function handle($request, Closure $next) {

      echo ‘<br>First Middleware’;

      return $next($request);

   }

}

Step 4: tạo một middleware gọi là SecondMiddleware.

php artisan make:middleware SecondMiddleware

Step 5: và thêm dòng code sau trong phương thức handle trong file SecondMiddleware.php.

class SecondMiddleware {

   public function handle($request, Closure $next){

      echo ‘<br>Second Middleware’;

      return $next($request);

   }

}

Step 6: tạo controller gọi là UserController, nếu các bạn đã tạo thử từ ví dụ đầu tiên để tracking bài viết thì tới bước này bạn không cần phải tạo nữa, tức là bạn đã tạo ở ví dụ giới thiệu controller ở trên rồi. (step 1).

Step 7: Copy dòng code sau tới app/Http/UserController.php.

class UserController extends Controller {

   public function __construct(){

      $this->middleware(‘Second’);

   }

   public function showPath(Request $request){

      $uri = $request->path();

      echo ‘<br>URI: ‘.$uri;

      $url = $request->url();

      echo ‘<br>’;

      echo ‘URL: ‘.$url;

      $method = $request->method();

      echo ‘<br>’;

      echo ‘Method: ‘.$method;

   }

}

Step 8: chạy lệnh sau nếu bạn chưa chạy nó

php artisan serve

Lệnh này cho php chạy bên trong web server, tức là bạn gõ http://localhost:8000 nó sẽ thực thi laravel của bạn.

Step 9: chạy url sau trên browser

http://localhost:8000/usercontroller/path

Step 10: và kết quả ra là:

bai6_controller_middleware_ex

Lưu ý : nếu các bạn chạy ra lổi thì hãy đọc bài Laravel – Middleware sẽ hiểu nguyên do. Ở đây không phải đánh đố các bạn, mà tôi muốn chắc là các bạn đang luyện tập nó một cách nghiêm túc. Hoặc các bạn hãy comment bên dưới bài học, mình sẽ giải đáp cho các bạn.

Rồi chúng ta qua mục mới .

Restful Resource Controllers

Thường thì khi tạo một ứng dụng chúng ta cần thực hiện CRUD (Create, Read, Update, Delete). Laravel tạo công việc này dể dàng cho chúng ta. Chỉ cần tạo controller và Laravel sẽ tự động cung cấp tất cả các phương thức cho CRUD. Bạn cũng có thể đăng ký 1 route duy nhất cho tất cả các phương thức tại routes/web.php (xem step 3 ví dụ dưới đây).

Example

Step 1 : tạo một controller gọi là MyController với câu lệnh sau :

php artisan make:controller MyController –resource

Như tôi đã đề cập ở trên là khi tạo controller ta thêm đối số –resource thì controller khi mới tạo ra nó sẽ có đủ các phương thức CRUD cho các bạn.

Lưu ý: với phiên bản cũ thì không cần đối số để tạo controller CRUD.

Step 2: thêm code sau vào app/Http/Controllers/MyController.php.

Nếu tạo controller thành công bạn mở ra và sẽ thấy các function tạo sẳn, hãy vào thêm code như sau:

class MyController extends Controller {

   public function index(){

      echo ‘index’;

   }

   public function create(){

      echo ‘create’;

   }

   public function store(Request $request){

      echo ‘store’;

   }

   public function show($id){

      echo ‘show’;

   }

   public function edit($id){

      echo ‘edit’;

   }

   public function update(Request $request, $id){

      echo ‘update’;

   }

   public function destroy($id){

      echo ‘destroy’;

   }

}

Chỉ là echo ra để biết nó chạy vô đâu mà thôi.

Step 3: định tuyến cho controller mới

Route::resource(‘my’,’MyController’);

Step 4: chúng ta  đăng ký cho tất cả các phương thức của MyController bằng cách đăng ký một controller với ‘resource’. Bảng dưới đây mô tả các action xử lý bởi resource controller.

Method Path Action Route Name
GET /my index my.index
GET /my/create create my.create
POST /my store my.store
GET /my/{my} show my.show
GET /my/{my}/edit edit my.edit
PUT/PATCH /my/{my} update my.update
DELETE /my/{my} destroy my.destroy

Lưu ý: Các bạn truyền theo phương thức nào với path tương ứng thì sẽ chạy vào phương thức được liệt kê như bảng : GET => /my và POST => /my chạy vô 2 phương thức khác nhau nha các bạn.

Step 5: vì phương thức POST là dạng truyền đặc biệt, có thể bạn dùng form hoặc dùng CURL do vậy để đơn giản cho luyện tập bài học này, chúng ta thử chạy url get để test.

Rồi bây giờ bạn thực hiện lần lượt các URL sau để xem kết quả.

URL Description Output Image
http://localhost:8000/my Executes index method of MyController.php index
http://localhost:8000/my/create Executes create method of MyController.php create
http://localhost:8000/my/1 Executes show method of MyController.php show
http://localhost:8000/my/1/edit Executes edit method of MyController.php edit

Constructor Injection

Vấn đề này liên quan đến các khái niệm về Dependency Injection. Chúng ta sẽ học chuyên sâu hơn với tutorial Dependency Injection.

Trong khuôn khổ Laravel thì tôi xin diễn giải cách đơn giản nhất để các bạn dể hiểu. Bởi vì hầu hết tất cả framework tiên tiến sau này điều viết theo lối pattern Dependency Injection để khởi tạo đối tượng.

Hiểu như thế này: Thay vì bạn khởi tạo đối tượng là new Object rồi sử dụng nó bên trong class bạn cần, tôi ví dụ là trong class User bạn cần khởi tạo đối tượng Database để tạo lấy dữ liệu hoặc làm các cái bạn cần. Nhưng vấn đề xãy ra là bạn khó mà unit test nó, bởi khi test class user bạn lại phải test cả database, tức là bạn cũng phải implement các class mà thèn user phụ thuộc vào. Hơn nữa, nếu mà tôi thay đổi database class thì bạn lại phải chạy hết các nơi có khởi tạo đối tượng Database mà thay đổi theo.

Phương pháp dependency injection sẽ giúp bạn. Thay vì bạn gọi nó thì hãy để nó tự gọi bạn.

Nghĩa là đối tượng được cấp phát từ bên ngoài và nó sẽ tiêm vào (injection) nơi bạn cần sử dụng.

Có nhiều cách để tiêm vào, trong mục này là sẽ tiêm vào con đường Constructor. Tức là vừa tạo đối tượng class của bạn thì đối tượng tiêm vào cũng được tạo theo.

Dependency Injection  là giúp giảm sự phụ thuộc các đối tượng với nhau, class nào thì làm nhiệm vụ của class đó mà thôi.

Example

Step 1: tạo controller với tên gọi là ImplicitController

php artisan make:controller ImplicitController

Step 2: trong file định tuyến chúng ta thêm code sau:

class MyClass{

   public $foo = ‘bar’;

}

Route::get(‘/myclass’,’ImplicitController@index’);

Step 3: trong ImplicitController.php thêm code sau:

class ImplicitController extends Controller {

   private $myclass;

      public function __construct(MyClass $myclass){

      $this->myclass = $myclass;

   }

   public function index(){

      dd($this->myclass);

   }

}

Step 4: chạy url sau http://localhost:8000/myclass

Step 5: kết quả:

bai6_constructor_injection

Lưu ý: hàm dd là hàm mà laravel viết lại để dump đối tượng ra, bạn không thích thì dùng bất kỳ hàm khác để debug như var_dump, print_r, dump

Diễn giải:

File định tuyến chạy đầu tiên nên nó đã có được class MyClass ta định nghĩa, và trong constructor của class ImplicitController chúng ta đã injection cái MyClass vào, thế là ta có thể sử dụng MyClass rồi, nếu bạn có sữa đổi MyClass thì bạn ra chổ tạo đối tượng nó mà đổi, đâu có ảnh hưởng ăn nhậu gì tới ImplicitController đúng không, hehe thì ra Dependency Injection sử dụng đơn giản và hiệu quả như vậy.

Nếu các bạn vẩn còn chưa rõ DI thì chúng ta sẽ nghiên cứu kỹ ở tutorial khác, chỉ hiểu là chúng ta gửi đối tượng vào class khác khi muốn sử dụng mà không phải tạo instance of bên trong class.

Nhắc lại giữa controller và action phân biệt nhau bởi @ ‘ImplicitController@Index’

Method Injection

Nếu bạn đã biết và hiểu Constructor Injection thì phần này cũng đơn giản, tức là thay vì bạn đưa đối tượng vào constructor, rồi trong class Implicit bạn có thể sử dụng đối tượng này bất kỳ nơi nào, thì nếu bạn không muốn, bạn chỉ muốn đối tượng đó sử dụng cho một hàm nhất định mà thôi.

Vậy thì chúng ta sẽ đưa đối tượng, tiêm nó vào phương thức cần thiết.

EX

Hãy thay đổi ImplicitController như sau:

class ImplicitController extends Controller {

   public function index(MyClass $myclass){ 

     dd($myclass);

   }

}

Bạn đã remove __constructor và thay vào đó khởi tạo đối tượng MyClass trong phương thức index.

Chạy lại http://localhost:8000/myclass sẽ cho cùng kết quả.

0