Middleware
Author: | ADMIN |
---|
Middleware cung cấp một cơ chế lọc các yêu cầu HTTP vào ứng dụng của bạn. Ví dụ, Laravel bao gồm một middleware kiểm tra người dùng của bạn có xác thực hay chưa. Nếu người dùng không xác thực, middleware sẽ chuyển hướng người dùng đến trang đăng nhập. Tuy nhiên, nếu người dùng đã xác thực, middleware sẽ cho phép yêu cầu tiếp tục vào ứng dụng.
Dưới đây là các bước để định nghĩa middleware trong Laravel:
1. Tạo Middleware
Để tạo middleware, bạn có thể sử dụng lệnh Artisan sau:
php artisan make:middleware CheckAge
Lệnh này sẽ tạo ra một lớp middleware mới tại app/Http/Middleware/CheckAge.php
. Trong lớp middleware này, bạn chỉ cần định nghĩa phương thức handle
.
2. Định nghĩa Middleware
Trong lớp middleware, bạn có thể viết logic để kiểm tra hoặc xử lý yêu cầu. Ví dụ, dưới đây là cách middleware kiểm tra độ tuổi của người dùng:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class CheckAge
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if ($request->age <= 200) {
return redirect('home');
}
return $next($request);
}
}
Trong ví dụ này, nếu độ tuổi của người dùng nhỏ hơn hoặc bằng 200, middleware sẽ chuyển hướng họ về trang chủ. Nếu không, yêu cầu sẽ tiếp tục được xử lý.
3. Đăng ký Middleware
Sau khi tạo middleware, bạn cần đăng ký nó trong ứng dụng. Có hai cách để đăng ký middleware: toàn cục và nhóm.
3.1. Middleware Global
Để đăng ký middleware toàn cục, bạn thêm nó vào thuộc tính $middleware
trong app/Http/Kernel.php
:
protected $middleware = [
// Other middleware
\App\Http\Middleware\CheckAge::class,
];
3.2. Middleware Groups
Để đăng ký middleware nhóm, bạn thêm nó vào thuộc tính $middlewareGroups
trong app/Http/Kernel.php
. Ví dụ, bạn có thể thêm middleware vào nhóm web
:
protected $middlewareGroups = [
'web' => [
// Other middleware
\App\Http\Middleware\CheckAge::class,
],
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
3.3. Middleware Định Tuyến
Bạn có thể gán middleware cho các tuyến cụ thể bằng cách sử dụng phương thức middleware
trong file routes/web.php
hoặc routes/api.php
:
Route::get('admin/profile', function () {
// Only authenticated users may enter...
})->middleware('auth', 'check.age');
4. Middleware Tham Số
Middleware cũng có thể chấp nhận tham số. Ví dụ, bạn có thể tạo middleware để kiểm tra vai trò của người dùng:
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
// Redirect...
}
return $next($request);
}
Sau đó, bạn có thể gán middleware này cho một tuyến với tham số:
Route::put('post/{id}', function ($id) {
// Update the post...
})->middleware('role:editor');
# Middleware and Responses
Middleware có thể thực hiện các tác vụ trước hoặc sau khi chuyển tiếp yêu cầu vào sâu hơn trong ứng dụng. Ví dụ, middleware sau đây sẽ thực hiện một số tác vụ trước khi yêu cầu được xử lý bởi ứng dụng:
Ví dụ Middleware
Dưới đây là một ví dụ về middleware thực hiện một số tác vụ trước khi xử lý yêu cầu:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class BeforeMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
// Thực hiện một số tác vụ trước khi yêu cầu được xử lý
// Ví dụ: kiểm tra điều kiện hoặc ghi log
if ($request->user() && $request->user()->isBlocked()) {
return response('Your account is blocked.', 403);
}
// Chuyển tiếp yêu cầu vào sâu hơn trong ứng dụng
return $next($request);
}
}
Thực hiện tác vụ sau khi xử lý yêu cầu
Middleware cũng có thể thực hiện các tác vụ sau khi yêu cầu đã được xử lý. Để làm điều này, bạn chỉ cần thêm logic sau khi gọi hàm $next($request)
:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class AfterMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
// Xử lý yêu cầu
$response = $next($request);
// Thực hiện một số tác vụ sau khi yêu cầu đã được xử lý
// Ví dụ: thêm header vào phản hồi
$response->header('X-Header-One', 'Header Value');
return $response;
}
}
Trong ví dụ trên, middleware sẽ thêm một header vào phản hồi sau khi yêu cầu đã được xử lý bởi ứng dụng.
# Sorting Middleware
Trong Laravel, bạn có thể chỉ định thứ tự thực hiện của các middleware. Việc sắp xếp này có thể hữu ích khi bạn cần một middleware phải được thực thi trước hoặc sau một middleware khác. Laravel cung cấp một cách dễ dàng để sắp xếp thứ tự của các middleware thông qua thuộc tính $middlewarePriority
trong lớp App\Http\Kernel
.
Định nghĩa Thứ Tự Middleware
Để sắp xếp thứ tự thực hiện của middleware, bạn chỉ cần thêm thuộc tính $middlewarePriority
vào lớp App\Http\Kernel
và liệt kê các middleware theo thứ tự bạn muốn chúng được thực thi:
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
// Danh sách các middleware toàn cục
];
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
// Danh sách các middleware nhóm 'web'
],
'api' => [
// Danh sách các middleware nhóm 'api'
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
// Danh sách các route middleware
];
/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\App\Http\Middleware\FirstMiddleware::class,
\App\Http\Middleware\SecondMiddleware::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\AnotherMiddleware::class,
// Thêm các middleware khác theo thứ tự bạn muốn
];
}
Trong ví dụ trên, FirstMiddleware
sẽ được thực thi trước SecondMiddleware
, và AnotherMiddleware
sẽ được thực thi sau StartSession
và ShareErrorsFromSession
.
Ví Dụ Về Middleware
Dưới đây là ví dụ về hai middleware mà bạn muốn sắp xếp thứ tự thực hiện:
FirstMiddleware
:
<?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) { // Logic của FirstMiddleware return $next($request); } }
SecondMiddleware
:
<?php namespace App\Http\Middleware; use Closure; class SecondMiddleware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { // Logic của SecondMiddleware return $next($request); } }
Kết Hợp Với Route
Sau khi định nghĩa thứ tự của middleware, bạn có thể gán chúng cho các tuyến hoặc nhóm tuyến trong tệp routes/web.php
hoặc routes/api.php
:
// routes/web.php
Route::middleware(['first', 'second'])->group(function () {
Route::get('/', 'HomeController@index');
});
// Hoặc sử dụng trực tiếp trong các tuyến:
Route::get('/example', 'ExampleController@index')->middleware('first', 'second');
# Terminable Middleware
Trong Laravel, middleware có thể được chia thành hai loại chính: middleware thực thi trong quá trình xử lý yêu cầu và middleware thực thi sau khi phản hồi đã được gửi đến client. Middleware thuộc loại thứ hai được gọi là "terminable middleware".
Terminable middleware cho phép bạn thực hiện các công việc sau khi phản hồi đã được gửi về phía client, chẳng hạn như ghi log hoặc thực hiện các tác vụ tốn thời gian mà bạn không muốn làm chậm thời gian phản hồi của ứng dụng.
Tạo Middleware Terminable
Để tạo một terminable middleware, bạn cần tạo một middleware như bình thường và thêm phương thức terminate
vào lớp middleware đó. Phương thức terminate
sẽ được tự động gọi sau khi phản hồi đã được gửi về phía client.
- Tạo Middleware bằng Artisan:
php artisan make:middleware LogAfterRequest
- Định nghĩa Middleware với phương thức
terminate
:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class LogAfterRequest { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle(Request $request, Closure $next) { // Thực hiện các công việc trước khi xử lý yêu cầu return $next($request); } /** * Handle tasks after the response has been sent to the client. * * @param \Illuminate\Http\Request $request * @param \Symfony\Component\HttpFoundation\Response $response * @return void */ public function terminate(Request $request, Response $response) { // Thực hiện các công việc sau khi phản hồi đã được gửi đến client \Log::info('Request has been completed.'); } }
Đăng Ký Middleware
Bạn cần đăng ký middleware trong tệp app/Http/Kernel.php
để Laravel có thể nhận diện và sử dụng middleware đó:
- Thêm middleware vào thuộc tính
$middleware
hoặc$routeMiddleware
của lớpKernel
:
// app/Http/Kernel.php protected $middleware = [ // Các middleware khác \App\Http\Middleware\LogAfterRequest::class, ];
- Nếu bạn muốn middleware này chỉ áp dụng cho một số tuyến cụ thể, bạn có thể thêm vào thuộc tính
$routeMiddleware
:
// app/Http/Kernel.php protected $routeMiddleware = [ // Các route middleware khác 'log.after' => \App\Http\Middleware\LogAfterRequest::class, ];
- Sử dụng middleware trong tuyến của bạn:
// routes/web.php Route::get('/example', 'ExampleController@index')->middleware('log.after');
Kết Hợp với Các Tác Vụ Sau Phản Hồi
Bạn có thể sử dụng terminable middleware để thực hiện các tác vụ sau khi phản hồi đã được gửi đến client, chẳng hạn như:
- Ghi log các yêu cầu và phản hồi
- Gửi email
- Thực hiện các tác vụ bảo trì
- Đặt lại các kết nối hoặc phiên làm việc
Ví dụ, bạn có thể sử dụng phương thức terminate
để ghi lại log các thông tin về yêu cầu và phản hồi:
public function terminate(Request $request, Response $response)
{
\Log::info('Request URL: ' . $request->fullUrl());
\Log::info('Response Status: ' . $response->status());
}
Database: Seeding
Author: | ADMIN |
---|
Seeding trong Laravel là một cách để tự động thêm dữ liệu mẫu vào cơ sở dữ liệu của bạn. Điều này hữu ích khi bạn cần tạo ra dữ liệu thử nghiệm hoặc khởi tạo dữ liệu mặc định cho ứng dụng.
Tạo Seeder
Bạn có thể tạo một seeder mới bằng cách sử dụng lệnh Artisan:
php artisan make:seeder UsersTableSeeder
Lệnh này sẽ tạo một file seeder mới trong thư mục database/seeders
.
Định Nghĩa Seeder
Khi bạn mở file seeder, nó sẽ trông giống như sau:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// Đoạn mã để chèn dữ liệu mẫu vào bảng users
}
}
Bạn có thể sử dụng phương thức DB::table
hoặc các phương thức của Eloquent để chèn dữ liệu vào bảng:
public function run()
{
DB::table('users')->insert([
'name' => Str::random(10),
'email' => Str::random(10).'@gmail.com',
'password' => bcrypt('password'),
]);
}
Hoặc sử dụng model Eloquent:
public function run()
{
\App\Models\User::create([
'name' => 'John Doe',
'email' => 'johndoe@example.com',
'password' => bcrypt('password'),
]);
}
Gọi Seeder
Sau khi định nghĩa seeder, bạn cần gọi nó trong lớp DatabaseSeeder
để nó được chạy khi bạn chạy lệnh seed:
// database/seeders/DatabaseSeeder.php
public function run()
{
$this->call(UsersTableSeeder::class);
}
Chạy Seeder
Bạn có thể chạy tất cả các seeder bằng lệnh Artisan:
php artisan db:seed
Hoặc chạy một seeder cụ thể:
php artisan db:seed --class=UsersTableSeeder
Tái Tạo Cơ Sở Dữ Liệu
Nếu bạn muốn làm mới cơ sở dữ liệu và chạy lại các seeder, bạn có thể sử dụng lệnh migrate:fresh
:
php artisan migrate:fresh --seed
Lệnh này sẽ xóa tất cả các bảng trong cơ sở dữ liệu của bạn và chạy lại tất cả các migration và seeder.
Tùy chọn --seeder có thể được sử dụng để chỉ định một seeder cụ thể để chạy:
php artisan migrate:fresh --seed --seeder=UserSeeder
Sử Dụng Factory trong Seeder
Laravel có thể tích hợp factory với seeder để tạo ra dữ liệu mẫu phong phú hơn. Ví dụ, bạn có thể sử dụng factory để tạo nhiều người dùng một cách dễ dàng:
public function run()
{
\App\Models\User::factory(10)->create();
}
Forcing Seeders to Run in Production
Khi làm việc với Laravel, bạn có thể muốn chạy seeder (tạo dữ liệu mẫu) ngay cả khi ứng dụng đang ở môi trường production. Điều này thường bị ngăn chặn để tránh nguy cơ làm hỏng dữ liệu thực tế. Tuy nhiên, đôi khi bạn vẫn cần phải chạy seeder trong môi trường production, và Laravel cung cấp cách để làm điều này một cách an toàn.
php artisan db:seed --force
Cờ --force
sẽ bỏ qua cảnh báo và cho phép seeder chạy ngay cả khi ứng dụng đang ở môi trường production.
Ví dụ Thực Tế
Giả sử bạn có một seeder gọi là DatabaseSeeder
và bạn muốn chạy nó trong môi trường production. Bạn chỉ cần chạy lệnh sau từ dòng lệnh:
php artisan db:seed --class=DatabaseSeeder --force
Lệnh trên sẽ thực hiện seeding dữ liệu từ DatabaseSeeder
vào cơ sở dữ liệu hiện tại, ngay cả khi ứng dụng đang ở môi trường production.
Chạy Seeder Cụ Thể
Nếu bạn chỉ muốn chạy một seeder cụ thể trong môi trường production, bạn có thể chỉ định seeder đó với cờ --class
cùng với --force
. Ví dụ:
php artisan db:seed --class=UsersTableSeeder --force
Điều này sẽ chỉ chạy seeder UsersTableSeeder
.
Sử Dụng Migrate với Seeder
Nếu bạn muốn chạy migration kèm theo seeder trong môi trường production, bạn có thể sử dụng lệnh migrate:fresh
hoặc migrate
cùng với cờ --seed
và --force
:
php artisan migrate:fresh --seed --force
// or
php artisan migrate --seed --force
Cả hai lệnh trên sẽ chạy migration để tạo lại hoặc cập nhật các bảng trong cơ sở dữ liệu và sau đó chạy seeder.