Cách fix lỗi 'Target class does not exist' trong Laravel 8
Bài đăng này đã không được cập nhật trong 2 năm
Laravel 8 vừa mới được phát hành với một loạt các thay đổi cũng như chức năng. Một trong những thay đổi đó là việc loại bỏ route namespace mặc định.
Mặc dù thay đổi này có tính tương thích ngược, nghĩa là những dự án cũ đã sử dụng Laravel 7.x có thể dễ dàng chuyển sang Laravel 8.x mà không cần thay đổi bất cứ điểu gì, tuy nhiên các dự án mới được áp dụng Laravel 8 ngay từ đầu lại phải quan tâm đến điều này
Rất nhiều developers phải đối mặt với vấn đề trong việc tạo một Project laravel 8, họ cố gắng load routes
và gặp phải một vài Exception
điển hình như
Target class [PostController] does not exist.
Vấn đề này không phải là lỗi do code, tuy nhiên 99,9% các hướng dẫn về Laravel hiện tại đều không phù hợp trong trường hợp này bởi vì hầu hết chúng đều dựa vào namespace
mặc định để đưa ra.
Thay đổi
Cho đến Laravel 7 thì RouteServiceProvider.php
đều có phần mã sau
$protected $namespace = 'App\Http\Controllers';
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
Đoạn code trên nói cho Laravel rằng khi load routes
được định nghĩa trong file routes/web.php
thì sẽ mặc định sử dụng web
middleware và namespace là App\Http\Controllers
. Cụ thể hơn, nghĩa là mỗi lần bạn khai báo một route mới trong file routes/web.php
sử dụng cú pháp như bên dưới, Laravel sẽ tìm kiếm các controller trong folder App\Http\Controllers
:
Route::get('posts', 'PostController@index');
Larvel sẽ sử dụng controller App\Http\Controllers\PostController.php
Tuy nhiên khi đến với Laravel 8, khi bạn khai báo routes sử dụng cú pháp như vậ Laravel sẽ không tìm kiếm controller trong thư mục App\Http\Controllers
nữa. Vấn đề chính là ở đây
Làm sao để fix
Vâng như ở trên thì chúng ta đã biết với Laravel 8, sẽ không có default namespace chính vì vậy Laravel sẽ không biết tìm controller của bạn ở đâu. Có ba cách để bạn nói với Laravel biết điều này:
- Thêm namespace mặc định cũng tương tự như Laravel 7 đã là trước đó.
- Sử dụng đưỡng dẫn đến controller kèm cả namespace khi khai báo một route mới.
- Sử dụng cú pháp action (recommended)
Thêm namespace thủ công
Việc này cực kì đơn giản. Chỉ cần đến file RouteServiceProvider.php
và bạn sẽ nhìn thấy đoạn code dưới đây:
public function boot()
{
$this->configureRateLimiting();
$this->routes(function () {
Route::middleware('web')
->group(base_path('routes/web.php'));
Route::prefix('api')
->middleware('api')
->group(base_path('routes/api.php'));
});
}
Tất cả những gì bạn phải làm là thêm 3 dòng code như dưới đây và Laravel sẽ có thêm default namespace tương tự như Laravel 7:
protected $namespace = 'App\Http\Controllers';
public function boot()
{
$this->configureRateLimiting();
$this->routes(function () {
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
});
}
Chúng ta vừa làm gì? Chúng ta khai báo biến $namespace
và sử dụng nó làm namespace mặc định cho cả web và api routes.
Nếu bạn chạy ứng dụng một lần nữa, mọi thứ sẽ hoạt động lại bình thường.
Khai báo route sử dụng namespace đầy đủ
Nếu sử dụng phương pháp này bạn sẽ phải áp dụng chco tất cả các routes của bạn, nhưng ý tưởng của nó rất đơn giản: thêm vào đằng trước tên controller của bạn bằng namespace của chính nó. Xem ví dũ dưới đây là bạn sẽ hiểu ngay thôi
Route::get('posts', 'App\Http\Controllers\PostController@index');
Lại tiếp tục thử chạy lại app của mình nhé.
Sử dụng cú pháp action
Đây là một giải pháp được khuyên dùng vì sẽ được các IDE hỗ trợ tốt hơn vì nó có thể xem được chính xác là class nào đã được sử dụng. Thay vì sử dụng cú pháp khai báo bằng string như thông thường chúng ta có thể sử dụng có pháp action này bằng cách chỉ định class và method để sử dụng trong một array
Khi sử dụng cú pháp string
Route::get('posts', 'PostController@index');
Thay vì đó sử dụng cú pháp action
Route::get('posts', [PostController::class, 'index']);
Lưu ý chúng ta phải gọi đến PostController::class
thay vì sử dụng string 'PostController'
như vậy nó sẽ trả về 'App\Http\Controllers\PostController'
. Giá trị thứ hai được truyền vào array chính là tên của phương thức chúng ta sẽ sử dụng trong controller.
Một lần nữa hãy thử chạy lại ứng dụng của bạn và mọi thứ sẽ họat động tốt.
Kết luận
Với một vài cách như trên hi vọng rằng project của bạn sẽ không phải gặp lỗi namespace nữa và hoạt động tốt.
Tài liệu tham khảo:
https://medium.com/@litvinjuan/how-to-fix-target-class-does-not-exist-in-laravel-8-f9e28b79f8b4
All rights reserved