Advanced learning
Laravel Advanced learning
☕ Scheduler
1,Configuration Scheduler
Open the app/Console/Kernel.php
file, you will see the schedule
method, this is where the tasks are defined:
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*/
protected function schedule(Schedule $schedule): void
{
// Execute the report:daily command at 8 am every day
//$schedule->command('report:daily')->dailyAt('08:00');
$schedule->command('report:daily')->everyMinute();
}
/**
* Register the commands for the application.
*/
protected function commands(): void
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
2,SendDailyReport
php artisan make:command SendDailyReport
<?php
namespace App\Console\Commands;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
class SendDailyReport extends Command
{
// Command Signature
protected $signature = 'report:daily';
// Command Description
protected $description = 'Send daily report email to all users';
public function __construct()
{
parent::__construct();
}
public function handle()
{
$this->info('Starting to send daily report emails');
// Retrieve all users
$users = User::all();
$this->info('Number of users found: ' . $users->count());
if ($users->isEmpty()) {
$this->error('No users found.');
return;
}
foreach ($users as $user) {
try
{
Mail::raw('Here is your daily report content', function ($message) use ($user) {
$message->to($user->email)
->from(config('services.mail.mail_gmail'), config('services.mail.mail_name'))
->subject('Daily Report');
});
$this->info('Email successfully sent to: ' . $user->email);
}
catch (\Exception $e)
{
$this->error('Failed to send email to ' . $user->email . ': ' . $e->getMessage());
}
}
$this->info('Daily report emails sent successfully.');
}
}
3,ENV Setting
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ex_sh
DB_USERNAME=root
DB_PASSWORD=
MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=11db8c1f10c50d
MAIL_PASSWORD=667fe814a795e7
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=HooBusiness@example.com
MAIL_FROM_NAME=Hoo
4,php artisan migrate
Create User
5,start up Scheduler
php artisan schedule:run
Automatically execute php artisan report:daily
In Windows environment, you can use Task Scheduler to set up scheduled tasks.
Setting steps:
-
Open Task Scheduler: Press
Win + R
keys, entertaskschd.msc
and press Enter. -
Create a basic task:
-
Click "Create Basic Task" on the right.
-
Enter a task name, such as "Laravel Report Daily".
-
-
Set Trigger:
-
On the Trigger page, select "Daily" or other desired frequency.
-
Specify the start time, such as
08:00
.
-
-
Set Action:
-
On the Action page, select "Start Program".
-
Program or Script Path Enter your PHP executable file path, such as
D:\php-8.3.10\php.exe
. -
Enter in the Add Parameters section
artisan report:daily
, for example:
D:\Code\Laravel P\example-app2\artisan report:daily
-
-
Save and Finish
☕ Event & Listener
Scenario: Send a welcome email after user registration
When a new user registers, we trigger an event UserRegistered
, and then the listener SendWelcomeEmail
will capture the event and send a welcome email.
1. Installation
php artisan make:event UserRegistered
php artisan make:listener SendWelcomeEmail --event=UserRegistered
2. Define event and listener logic
Open app/Events/UserRegistered.php
and edit the following:
namespace App\Events;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class UserRegistered
{
use Dispatchable, SerializesModels;
public $user;
public function __construct(User $user)
{
$this->user = $user;
}
}
3. Write the logic of sending emails in the listener file
Open the app/Listeners/SendWelcomeEmail.php
file and add the following code:
namespace App\Listeners;
use App\Events\UserRegistered;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Mail;
class SendWelcomeEmail implements ShouldQueue
{
use InteractsWithQueue;
public function __construct()
{
// Optional: perform initialization in the constructor
}
public function handle(UserRegistered $event)
{
$user = $event->user;
Mail::raw('Welcome to our website!', function ($message) use ($user) {
$message->to($user->email)
->subject('Welcome!');
});
}
}
4. Register events and listeners
Open app/Providers/EventServiceProvider.php
and register events and listeners in the $listen
array:
namespace App\Providers;
use App\Events\UserRegistered;
use App\Listeners\SendWelcomeEmail;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
UserRegistered::class => [
SendWelcomeEmail::class,
],
];
public function boot()
{
parent::boot();
}
}
- Trigger events
Trigger the UserRegistered
event in the user registration logic. For example, add the following code to the user controller:
php artisan make:controller UserController
<?php
namespace App\Http\Controllers;
use App\Events\UserRegistered;
use App\Models\User;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function register(Request $request)
{
$user = User::create($request->only('name', 'email', 'password'));
event(new UserRegistered($user));
return response()->json(['message' => 'Registration successful!']);
}
}
api.php
Route::post('register', [\App\Http\Controllers\UserController::class, 'register']);
Test the registration request through Postman or the command line to confirm that you received the welcome email.
☕ Authorization Policies
Using authorization policies in Laravel can help you better manage user permissions. Below are detailed steps and code to create and use policies.
1. Installation
php artisan make:policy PostPolicy
This will create a PostPolicy.php
file in the app/Policies
directory.
2. Define policy methods
Open app/Policies/PostPolicy.php
and define the user permission logic in the policy. The following example shows checking whether the user has the permission to update and delete a specific Post
:
<?php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
/**
* Determine whether the user can update the post
*/
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
/**
* Determine whether the user can delete the post
*/
public function delete(User $user, Post $post)
{
return $user->id === $post->user_id;
}
}
3. Register policies
Open the AuthServiceProvider
file (app/Providers/AuthServiceProvider.php
) and register PostPolicy
in the $policies
array:
<?php
namespace App\Providers;
use App\Models\Post;
use App\Policies\PostPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Post::class => PostPolicy::class,
];
public function boot()
{
$this->registerPolicies();
}
}
4. Use policies for authorization checks
In the controller, you can use policies to check user permissions.
For example, use the authorize
method in PostController
:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function update(Request $request, Post $post)
{
// Check if the user has permission to update the post
$this->authorize('update', $post);
// Perform the update operation
$post->update($request->all());
return response()->json(['message' => 'Post updated successfully']);
}
public function delete(Post $post)
{
// Check if the user has permission to delete the post
$this->authorize('delete', $post);
// Perform the delete operation
$post->delete();
return response()->json(['message' => 'Post deleted successfully']);
}
}
5. Use policies in Blade templates
You can use the @can
directive in Blade templates to check policy permissions:
@can('update', $post)
<a href="{{ route('posts.edit', $post) }}">Edit a post</a>
@endcan
@can('delete', $post)
<form action="{{ route('posts.destroy', $post) }}" method="POST">
@csrf
@method('DELETE')
<button type="submit">Delete a post</button>
</form>
@endcan
☕ Real-time event broadcasting x
In Laravel, real-time event broadcasting can broadcast server-side events to the front-end, allowing the client to receive and respond to events in real time. This is very useful for implementing real-time update functions (such as notifications, chats, etc.). The following are detailed steps and codes for implementing real-time event broadcasting using Laravel Broadcasting.
Real-time event broadcasting is a mechanism that allows Laravel applications to notify client applications, such as web pages or mobile applications, of events in real time. This allows for features such as real-time chat and push notifications without the client constantly polling the server for updates. Pusher is a very commonly used third-party service that makes it easier for Laravel to implement event broadcasting.
Pusher registration is required
1. Install
npm install
npm install vite --save-dev
composer require pusher/pusher-php-server
php artisan make:model Message -m
Edit the Message
model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Message extends Model
{
use HasFactory;
protected $fillable = ['user_id', 'content'];
public function user()
{
return $this->belongsTo(User::class);
}
}
In this model, user_id
indicates the sender of the message, and content
is the message content. You can customize the fields as needed.
Create a migration file for the Messages table
public function up()
{
Schema::create('messages', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->text('content');
$table->timestamps();
});
}
php artisan migrate
2, Configuring the Broadcast Driver
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=your-app-id
PUSHER_APP_KEY=your-app-key
PUSHER_APP_SECRET=your-app-secret
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1
3,Set up broadcast events
php artisan make:event MessageSent
In the generated event class (e.g. app/Events/MessageSent.php
), implement the ShouldBroadcast
interface:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;
use App\Models\Message;
class MessageSent implements ShouldBroadcast
{
use InteractsWithSockets, SerializesModels;
public $message;
public function __construct(Message $message)
{
$this->message = $message;
}
public function broadcastOn()
{
return new Channel('chat');
}
public function broadcastAs()
{
return 'message.sent';
}
}
4. Trigger an event
Call event(new MessageSent($message))
where you need to trigger an event. For example, trigger an event when a new message is sent in MessageController
:
php artisan make:controller MessageController
<?php
namespace App\Http\Controllers;
use App\Events\MessageSent;
use App\Models\Message;
use Illuminate\Http\Request;
class MessageController extends Controller
{
public function send(Request $request)
{
$message = Message::create([
'user_id' => $request->user()->id,
'content' => $request->input('content'),
]);
// Broadcast Events
event(new MessageSent($message));
return response()->json(['message' => 'Message sent successfully!']);
}
}
5. Listen for broadcast events on the front end
Use Laravel Echo and Pusher to receive broadcast events on the front end. First install Laravel Echo and Pusher JavaScript SDK:
npm install --save laravel-echo pusher-js
Initialize Echo in the front-end JavaScript file and listen for events. For example, in resources/js/app.js
:
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
wsHost: window.location.hostname,
wsPort: 6001,
forceTLS: false,
disableStats: true,
});
window.Echo.channel('chat')
.listen('.message.sent', (e) => {
console.log('News:', e.message);
});
6. Run the broadcast service
npm run dev
npm install --save laravel-echo pusher-js
.env
VITE_PUSHER_APP_KEY=your-app-key
VITE_PUSHER_APP_CLUSTER=your-app-cluster
cmd
composer require beyondcode/laravel-websockets --with-all-dependencies
php artisan websockets:serve
php artisan serve
☕ OAuth 2.0 / Laravel Passport
Yes, Laravel Passport does provide a createToken
method that allows the creation of access tokens in an OAuth 2.0 implementation. This method is ideal for generating "Personal Access Tokens" for users, which are often used for API authentication.
1. Installation
composer require laravel/passport
2. Configuration Passport
php artisan migrate
Generate encryption key: Generates the encryption key required by Passport.
php artisan passport:install
3. Add Passport service provider
Add to the providers
array in the config/app.php
file:
Laravel\Passport\PassportServiceProvider::class,
4. Configure Auth
In the config/auth.php
file, set the api
authentication driver to passport
:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
5. Set up the User model
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens;
// Other model codes...
}
6. Define routes
In routes/api.php
, define the Passport route:
use Laravel\Passport\RouteRegistrar;
Route::group(['middleware' => ['auth:api']], function () {
// Routes that require authentication
});
Route::post('register', 'AuthController@register');
Route::post('login', 'AuthController@login');
7. Create an authentication controller
Create a controller to handle registration and login:
php artisan make:controller AuthController
Then implement the registration and login logic in AuthController
:
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class AuthController extends Controller
{
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed',
]);
if ($validator->fails()) {
throw new ValidationException($validator);
}
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
return response()->json(['user' => $user], 201);
}
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (!auth()->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
$user = auth()->user();
$token = $user->createToken('Personal Access Token')->accessToken;
return response()->json(['token' => $token]);
}
}
8. Test the API
You can use Postman or any API client to test the registration and login APIs:
Register:
- Request type: POST
- URL:
http://your-domain/api/register
- Request body:
{
"name": "Your Name",
"email": "your-email@example.com",
"password": "your-password",
"password_confirmation": "your-password"
}
Login:
- Request type: POST
- URL:
http://your-domain/api/login
- Request body:
{
"email": "your-email@example.com",
"password": "your-password"
}
The returned JSON will contain a token
, which you can use for authentication.
9. Protect routes
Add the auth:api
middleware to the routes that need to be protected. For example:
Route::group(['middleware' => ['auth:api']], function () {
Route::get('/user', function (Request $request) {
return $request->user();
});
});
☕ Task Queues
Time-consuming tasks (such as sending emails) can be pushed into queues and processed asynchronously to improve application performance.
With these steps, you can create and use task queues in Laravel. Asynchronous processing of tasks can significantly improve the responsiveness of the system while maintaining the efficiency of background tasks.
1. Configure queue drivers
In the config/queue.php
file, Laravel provides a variety of queue drivers, including database, Redis, Beanstalkd, etc. The database
driver is commonly used in the development environment. Make sure the appropriate driver is set in the .env
file, for example:
QUEUE_CONNECTION=database
2. Create a queue table
If you use the database
driver, please generate a queue table first:
php artisan queue:table
php artisan migrate
The generated table jobs
will store the information of the queue tasks.
3. Create a queue task
Use the Artisan command to create a queue task class. For example, here is a task for sending emails:
php artisan make:job SendEmailJob
This command will generate the SendEmailJob.php
file in the app/Jobs/
directory.
4. Write the queue task logic
In the generated SendEmailJob
class, write the task logic. Suppose we want to send an email, we can use the following code:
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Models\User;
use Illuminate\Support\Facades\Mail;
class SendEmailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function handle()
{
Mail::to($this->user->email)->send(new \App\Mail\WelcomeEmail($this->user));
}
}
In this code, the handle
method defines the specific logic of task execution. Here we use Laravel's email sending function to send a welcome email to the user.
5. Dispatch queue tasks
When using tasks in an application, you can push tasks to the queue through the dispatch
method. For example, send a welcome email after the user registers:
use App\Jobs\SendEmailJob;
use App\Models\User;
$user = User::find(1); // Example User
SendEmailJob::dispatch($user);
6. Run queue tasks
Use the queue:work
command to start a queue worker to process queue tasks:
php artisan queue:work
The queue:work
command will listen to the queue and process the tasks in the queue.
7. Set up task failure retries (optional)
If you need to automatically retry when a task fails, you can define the $tries
and $timeout
properties in the task class:
class SendEmailJob implements ShouldQueue
{
public $tries = 3; // Maximum number of attempts
public $timeout = 120; // Timeout (seconds)
// ...
}
8. Failed task processing (optional)
You can use queue:failed-table
to create a database table for failed tasks:
php artisan queue:failed-table
php artisan migrate
☕ Middleware
Used to filter HTTP requests, such as authentication, cross-site request forgery (CSRF) protection, etc.
Laravel middleware provides flexible control over requests, allowing you to insert custom logic during request processing, such as authentication, logging, cross-site request protection, etc. Through middleware, Laravel can effectively enhance the security and maintainability of applications.
1. Create middleware
php artisan make:middleware CheckAdmin
This command will generate the CheckAdmin.php
file in the app/Http/Middleware
directory.
2. Write middleware logic
In the generated CheckAdmin.php
file, write the logic of the middleware. This example will check whether the user is an administrator and return a 403 error if not.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class CheckAdmin
{
public function handle(Request $request, Closure $next)
{
// Check if the user is logged in and is an administrator
if (!Auth::check() || !Auth::user()->is_admin) {
// If not an administrator, return a 403 error
return response()->json(['error' => 'Unauthorized'], 403);
}
// If the user is an administrator, continue with the request
return $next($request);
}
}
Schema::table('users', function (Blueprint $table) {
$table->boolean('is_admin')->default(false); // Not an administrator by default
});
3. Register middleware
Open the app/Http/Kernel.php
file and register the middleware as routing middleware. Add to the $routeMiddleware
array:
protected $routeMiddleware = [
// Other middleware
'admin' => \App\Http\Middleware\CheckAdmin::class,
];
This way you can use admin
as a middleware alias to call CheckAdmin
in the route.
4. Apply middleware to routes
Middleware can be applied to a single route or a route group. For example, apply the admin
middleware in routes/web.php
:
use Illuminate\Support\Facades\Route;
Route::middleware(['admin'])->group(function () {
Route::get('/admin/dashboard', [AdminController::class, 'dashboard']);
Route::get('/admin/settings', [AdminController::class, 'settings']);
});
Or apply the middleware to a single route:
Route::get('/admin/dashboard', [AdminController::class, 'dashboard'])->middleware('admin');
5. Global middleware (optional)
If you need to apply middleware on all requests, you can add the middleware to the $middleware
array in the app/Http/Kernel.php
file:
protected $middleware = [
// Global Middleware
\App\Http\Middleware\CheckAdmin::class,
];
In this way, each request will be checked by CheckAdmin
first.
☕ API Resources
API resources provide a flexible JSON format for model data, define the structure through the toArray
method, and can attach additional metadata. API resources can make your API clearer and more standardized.
1. Create API resources
Use the make:resource
command to generate an API resource class. For example, create an API resource for the User
model:
php artisan make:resource UserResource
This command will generate the UserResource.php
file in the app/Http/Resources/
directory.
2. Define the API resource format
In the generated UserResource.php
file, use the toArray
method to define the output format of the API resource. You can choose to return specific fields or a custom format. For example:
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at->toDateTimeString(),
];
}
}
In this example, only the id
, name
, email
, and created_at
fields are returned. If you have sensitive fields, such as passwords, make sure not to include them here.
3. Use API resources to return data
Use API resources in controllers to return model data. For example, in UserController
, return data for a single user:
use App\Http\Resources\UserResource;
use App\Models\User;
class UserController extends Controller
{
public function show($id)
{
$user = User::findOrFail($id);
return new UserResource($user);
}
}
If you would like to return a collection of users, you may use the UserResource::collection
method:
public function index()
{
$users = User::all();
return UserResource::collection($users);
}
4. Customize resource collection format (optional)
Laravel also supports creating dedicated resource collection classes. You can use the following command to generate resource collection classes:
php artisan make:resource UserCollection
In UserCollection.php
, you can customize the collection return format.
5. Add additional metadata (optional)
You can add additional metadata to the resource, such as status information or pagination data. You can use the with
method in the resource class:
public function with($request)
{
return [
'status' => 'success',
'code' => 200,
];
}
Complete Example
After creating UserResource
, the API will return JSON in the following format:
{
"data": {
"id": 1,
"name": "John Doe",
"email": "johndoe@example.com",
"created_at": "2024-10-31 12:34:56"
},
"status": "success",
"code": 200
}
☕ Seeder and Factories
Laravel's Seeder and Factories can be used to generate fake data and populate database data during development and testing. The following are detailed steps and complete code examples for using Seeder and Factories.
1. Factories: Create and define factories
Factories are used to create fake data for models, which is suitable for generating different test data when the database is populated.
Use the make:factory
command to generate factories. For example, to generate a factory for the User
model:
php artisan make:factory UserFactory
The generated factory file will be located in the database/factories/
directory.
2. Define fake data for Factory
In the generated UserFactory.php
file, use the Faker library to define fake data for the model. The following is an example of UserFactory
:
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class UserFactory extends Factory
{
protected $model = User::class;
public function definition()
{
return [
'name' => $this->faker->name,
'email' => $this->faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => bcrypt('password'), // Default Password
'remember_token' => Str::random(10),
];
}
}
In this example, the factory generates fake data for fields such as name
and email
for the User
model.
3. Seeder: Create and define data population
Seeder is used to insert batches of test data into the database.
Generate Seeder using Artisan commands, such as generating UserSeeder
:
php artisan make:seeder UserSeeder
The generated Seeder file will be located in the database/seeders/
directory.
4. Define Seeder data population logic
In UserSeeder.php
, call the factory to generate multiple user records:
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
class UserSeeder extends Seeder
{
public function run()
{
// Use the factory to generate 10 users
User::factory()->count(10)->create();
}
}
This code will create 10 user records using UserFactory
.
5. Run Seeder
In DatabaseSeeder.php
, register UserSeeder
to the run
method so that it will be called when running database population:
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call(UserSeeder::class);
}
}
Then, run the db:seed
command to execute the Seeder and populate the data:
php artisan db:seed
You can also run a specific Seeder separately:
php artisan db:seed --class=UserSeeder
6. Use Tinker to test Factory (optional)
Laravel provides the Tinker tool, which can be used to quickly generate data. Enter the Tinker environment:
php artisan tinker
Then run the following command to generate a single user:
User::factory()->create();
Or generate multiple users:
User::factory()->count(5)->create();
☕ Caching
Laravel's cache system provides multiple cache driver support, which can use methods such as put
, get
, and remember
to operate the cache and improve application performance.
Laravel's cache system supports multiple drivers (such as Redis, Memcached, files, etc.), which can effectively improve the performance of the application. The following are detailed steps and code examples for using cache.
1. Configure cache driver
Laravel uses file cache by default. You can change the driver type in the .env
file. For example, change the cache driver to Redis:
CACHE_DRIVER=redis
Confirm that the Redis configuration in the .env
file is correct. The default Redis configuration is as follows:
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
Make sure Redis is running on the server. If you use other drivers (such as Memcached), install the driver and configure the corresponding .env
settings.
2. Using Cache in Laravel
Laravel provides multiple cache methods to easily operate the cache.
Example: Store Data in Cache
Use the following code in a controller or service to store data in the cache:
use Illuminate\Support\Facades\Cache;
// Store data in the cache with a validity period of 60 minutes
Cache::put('key', 'value', 60);
Cache::put('key', 'value', null); // Permanent Cache
Cache::forever('key', 'value'); // Permanent Cache
You can use the remember
method to cache data for a period of time. If the cache does not exist, execute the given callback and cache the result:
Cache::remember('key', 60, function () {
return 'value';
});
Example: Get data from cache
Use the get
method to get data from cache:
$value = Cache::get('key');
// If key does not exist, return the default value
$value = Cache::get('key', 'default');
Example: Delete cache
Use the forget
method to delete cache items:
Cache::forget('key');
3. Cache collection data
Caching collection data such as query results can effectively reduce database queries. For example:
$users = Cache::remember('users', 60, function () {
return \App\Models\User::all();
});
The above example caches all user data for 60 minutes, and subsequent requests will directly retrieve data from the cache.
4. Redis specific cache operations
If you use the Redis driver, you can access the Redis instance to perform operations:
use Illuminate\Support\Facades\Redis;
// Storing Values
Redis::set('key', 'value');
// Get Value
$value = Redis::get('key');
5. Clear the cache
Use the Artisan command to clear all caches:
php artisan cache:clear
☕RabbitMQ
RabbitMQ is a message broker that can be used for task queues, messaging, and asynchronous processing in distributed systems. Here are the complete steps and code examples on how to configure and use RabbitMQ in Laravel.
1. Install the RabbitMQ client library
Laravel does not have built-in support for RabbitMQ, so you need to use a community-provided package, such as the vladimir-yuldashev/laravel-queue-rabbitmq
package. First, install the package:
composer require vladimir-yuldashev/laravel-queue-rabbitmq
2. Configure the queue connection
After the installation is complete, configure the config/queue.php
file and add the RabbitMQ configuration in connections
:
'connections' => [
'rabbitmq' => [
'driver' => 'rabbitmq',
'queue' => 'default', // Default queue name
'connection' => 'default',
'hosts' => [
[
'host' => env('RABBITMQ_HOST', '127.0.0.1'),
'port' => env('RABBITMQ_PORT', 5672),
'user' => env('RABBITMQ_USER', 'guest'),
'password' => env('RABBITMQ_PASSWORD', 'guest'),
'vhost' => env('RABBITMQ_VHOST', '/'),
],
],
'options' => [
'ssl_options' => [
'cafile' => env('RABBITMQ_SSL_CAFILE', null),
'local_cert' => env('RABBITMQ_SSL_LOCALCERT', null),
'local_key' => env('RABBITMQ_SSL_LOCALKEY', null),
'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true),
'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null),
],
'queue' => [
'job' => \VladimirYuldashev\LaravelQueueRabbitMQ\Queue\Jobs\RabbitMQJob::class,
],
],
],
],
Add the following RabbitMQ configuration items to your .env
file:
RABBITMQ_HOST=127.0.0.1
RABBITMQ_PORT=5672
RABBITMQ_USER=guest
RABBITMQ_PASSWORD=guest
RABBITMQ_VHOST=/
3. Create a task queue Job
You can use Laravel's Artisan command to create a Job to process tasks:
php artisan make:job ProcessMessage
In the app/Jobs/ProcessMessage.php
file, define the specific execution content of the task, for example:
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProcessMessage implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $data;
public function __construct($data)
{
$this->data = $data;
}
public function handle()
{
// Process the message here
\Log::info("Processing message: " . $this->data);
}
}
4. Put the task into the queue
Where the queue is needed (such as in the controller), you can use the following code to put the task into the queue:
use App\Jobs\ProcessMessage;
Route::get('/send', function () {
$data = 'This is a message for RabbitMQ';
ProcessMessage::dispatch($data);
return 'Message sent to RabbitMQ!';
});
5. Start the queue listener
Finally, start the queue listener with the following command to process tasks in the RabbitMQ queue:
php artisan queue:work --queue=rabbitmq
By configuring the queue.php
file, creating a Job, and using dispatch
to send tasks to the RabbitMQ queue, you can easily use RabbitMQ as a queue driver for Laravel.
☕ Service Providers
1. Create a service provider
In development, it is often necessary to register common services, such as custom payment processing or data conversion services. Service providers can bind these service classes to the container for easy calling from various parts of the project.
php artisan make:provider CustomServiceProvider
Create CustomService.php
in the app/Services/
directory to implement basic business logic:
namespace App\Services;
class CustomService
{
public function performAction()
{
return "Custom Service Action Performed!";
}
}
In the register
method in CustomServiceProvider.php
, bind CustomService
to the container:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\CustomService;
class CustomServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(CustomService::class, function ($app) {
return new CustomService();
});
}
public function boot()
{
// You can add other startup logic here
}
}
2. Register service provider
Register service provider in config/app.php
:
'providers' => [
// Other service providers
App\Providers\CustomServiceProvider::class,
],
Inject CustomService
in a controller or elsewhere, and call its performAction
method:
namespace App\Http\Controllers;
use App\Services\CustomService;
class ExampleController extends Controller
{
protected $customService;
public function __construct(CustomService $customService)
{
$this->customService = $customService;
}
public function index()
{
return $this->customService->performAction();
}
}
☕ Model Observers
If you use Laravel's built-in php artisan serve
to run a local server during development, the information will be displayed in the command line window where php artisan serve
is started.
Model observers are used to perform specific actions when model events (such as create, update, delete, etc.) occur. Using observers can separate business logic from controllers, making the code clearer and easier to maintain. Here are the detailed steps and code examples:
1. Create Observer
Laravel provides Artisan commands to quickly generate observer files. Suppose you have a User
model and want to listen to user creation and deletion events.
php artisan make:observer UserObserver --model=User
After executing this command, Laravel will generate the UserObserver.php
file in the app/Observers
directory and automatically associate it with the User
model.
2. Define the Observer method
Open the app/Observers/UserObserver.php
file and define the actions to be performed when a specific event occurs. For example, record related actions when a user is created and deleted:
<?php
namespace App\Observers;
use App\Models\User;
class UserObserver
{
// Listen to the user creation event
public function created(User $user)
{
// Logic to execute when a user is created
echo "User created with ID: " . $user->id;
}
// Listen to the user deletion event
public function deleted(User $user)
{
// Logic to execute when a user is deleted
echo "User deleted with ID: " . $user->id;
}
}
3. Register Observer in the service provider
To make the observer effective, you need to register it in AppServiceProvider
or a custom service provider. In the boot
method in App\Providers\AppServiceProvider
, register UserObserver
:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Models\User;
use App\Observers\UserObserver;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
User::observe(UserObserver::class);
}
public function register()
{
//
}
}
4. Test Observer
You can test the observer by creating or deleting users. Open Laravel Tinker or execute the following code in the controller to observe the effect:
// Create User
$user = \App\Models\User::create([
'name' => 'John Doe',
'email' => 'johndoe@example.com',
'password' => bcrypt('password')
]);
// Deleting a User
$user->delete();
The observer will trigger the created
and deleted
methods when the create or delete operation is performed, and output the corresponding message.
Common usage examples
In addition to creation and deletion, observers can also listen to other events, such as updated
, saving
, restoring
, etc. You can define the corresponding methods in UserObserver
as needed:
public function updated(User $user)
{
echo "User updated with ID: " . $user->id;
}
In this way, model observers can help you perform specific actions when model events are triggered, making the code logic more modular and clear.
☕ Custom Commands (Artisan Commands)
Custom Artisan commands allow you to extend Laravel's command line tools, which are very suitable for performing scheduled tasks, batch processing of data, etc. The following are detailed steps and code examples for creating custom commands:
1. Generate custom commands
Use Artisan commands to generate a new command class:
php artisan make:command CustomCommand
After running, Laravel will create a CustomCommand.php
file in the app/Console/Commands
directory.
2. Define the name and function of the command
Open app/Console/Commands/CustomCommand.php
and modify the command name, description and processing logic:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class CustomCommand extends Command
{
// Define the name of the command, used for calling it in the command line
protected $signature = 'custom:run';
// Description of the command, displayed in `php artisan list`
protected $description = 'Execute a custom command';
// The command's processing logic
public function handle()
{
// Write the actual logic of the command here
$this->info('Custom Command Executed Successfully!');
}
}
$signature
: Defines the command's calling name, such ascustom:run
.$description
: The command's description, which can help understand the command's purpose.handle
method: The actual processing logic of the command. You can add any required business logic here, such as querying the database, processing data, etc.
3. Register custom commands
In app/Console/Kernel.php
, register the custom command to the $commands
array:
protected $commands = [
\App\Console\Commands\CustomCommand::class,
];
After registration, Laravel will be able to recognize and use this custom command.
4. Execute custom commands
You can now run custom commands in the terminal with the following command:
php artisan custom:run
After execution, the terminal will output Custom Command Executed Successfully!
, indicating that the command has been successfully run.
5, Another example
Another example, demonstrating how to create a custom Artisan command to get data from an API and store it in the database. Suppose we want to create a command to get user data and insert it into the users
table.
5.1, Generate a custom command
First, generate a new custom command:
php artisan make:command FetchUsers
This will create a file named FetchUsers.php
in the app/Console/Commands
directory.
5.2, define the name and function of the command
Open the app/Console/Commands/FetchUsers.php
file and modify the command name, description and processing logic:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
use App\Models\User;
class FetchUsers extends Command
{
// Define the name of the command
protected $signature = 'fetch:users';
// Description of the command
protected $description = 'Fetch users from an external API and store them in the database';
// Command processing logic
public function handle()
{
// Call an external API to get user data
$response = Http::get('https://jsonplaceholder.typicode.com/users');
if ($response->successful()) {
$users = $response->json();
foreach ($users as $userData) {
// Insert user data into the database
User::updateOrCreate(
['email' => $userData['email']], // Unique identifier
[
'name' => $userData['name'],
'username' => $userData['username'],
'address' => json_encode($userData['address']),
]
);
}
$this->info('Users fetched and stored successfully!');
} else {
$this->error('Failed to fetch users from the API.');
}
}
}
Code analysis
-
$signature
: defines the command call name asfetch:users
. -
$description
: describes the command's function. -
handle
method -
Use Laravel's HTTP client to get user data from the specified API (here using JSONPlaceholder's sample API).
-
If the request is successful, traverse the user data and use the
updateOrCreate
method to insert the user information into the database. If the user already exists (based on the email field), update the user's information. -
Output a success or failure message.
5.3, Register custom commands
In the app/Console/Kernel.php
file, register the custom command to the $commands
array:
protected $commands = [
\App\Console\Commands\FetchUsers::class,
];
5.4, Execute custom commands
You can now run custom commands in the terminal with the following command:
php artisan fetch:users
After execution, the command will fetch user data from the API and store it in the database. The terminal will display Users fetched and stored successfully!
to indicate that the operation was successful.
Application scenarios
This command can be used to periodically synchronize user data from an external API to your application, such as maintaining data consistency when registering, updating information, or performing data analysis. You can set this command to run on a scheduled basis in conjunction with Laravel's task scheduler to ensure that your database is always in sync with the external data source.
☕ User avatars
Here are detailed steps and code examples for processing user avatar uploads and saving avatar images to Laravel applications.
1, Create database fields
First, make sure you have a field in your user table to store the path to the avatar. If you don't have this field yet, you can add it through migration.
Run the following command in your terminal to create a migration:
php artisan make:migration add_avatar_to_users_table --table=users
Then, add the avatar
field to the generated migration file:
// database/migrations/xxxx_xx_xx_xxxxxx_add_avatar_to_users_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddAvatarToUsersTable extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('avatar')->nullable(); // Add an avatar field
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('avatar'); // Delete the avatar field
});
}
}
Run the migration command to update the database:
php artisan migrate
2. Create an avatar upload controller
Next, create a controller to handle avatar uploads. Run in the terminal:
php artisan make:controller AvatarController
Add the following code to the generated AvatarController
:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
class AvatarController extends Controller
{
public function upload(Request $request)
{
// Validate the file in the request
$request->validate([
'avatar' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048',
]);
// Get the current user
$user = Auth::user();
// Process the uploaded avatar
if ($request->hasFile('avatar')) {
// Delete old avatar if it exists
if ($user->avatar) {
Storage::delete($user->avatar);
}
// Upload new avatar
$path = $request->file('avatar')->store('avatars'); // Stored in storage/app/avatars
// Update the user's avatar path
$user->avatar = $path;
$user->save();
}
return response()->json(['message' => 'Avatar uploaded successfully', 'avatar' => $path]);
}
public function getAvatar()
{
// Get the current user's avatar
$user = Auth::user();
return response()->json(['avatar' => $user->avatar]);
}
}
3. Routing configuration
Add the corresponding routes in routes/web.php
or routes/api.php
:
use App\Http\Controllers\AvatarController;
Route::middleware('auth:sanctum')->post('/upload-avatar', [AvatarController::class, 'upload']);
Route::middleware('auth:sanctum')->get('/get-avatar', [AvatarController::class, 'getAvatar']);
4. Front-end upload form example
You can use HTML form or JavaScript/Axios to upload avatars. The following is a simple HTML form example:
<form id="avatar-form" enctype="multipart/form-data">
@csrf
<input type="file" name="avatar" id="avatar" required>
<button type="submit">Upload an avatar</button>
</form>
<script>
document.getElementById('avatar-form').addEventListener('submit', function (e) {
e.preventDefault();
let formData = new FormData(this);
fetch('/upload-avatar', {
method: 'POST',
body: formData,
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}', // Laravel CSRF token
},
})
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Error:', error);
});
});
</script>
5. Get the avatar
To get the current user's avatar, you can call the getAvatar
method:
fetch('/get-avatar', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + token, // Replace with your Bearer Token
},
})
.then(response => response.json())
.then(data => {
if (data.avatar) {
console.log('User avatar path:', data.avatar);
}
});
6. Display avatar
You can display the avatar through the generated avatar path, for example:
<img src="{{ asset($user->avatar) }}" alt="User Avatar" />
Summary
The above steps show how to implement the user avatar upload function in Laravel, including database migration, controller, route configuration, and front-end code examples. With these codes, users can upload, save, and get their avatars. If needed, you can further expand this function, such as adding more verification, adjusting the storage path, etc.
☕ middleware('auth:sanctum')
middleware('auth:sanctum')
is a middleware in Laravel that is used to protect your routes so that they can only be accessed by authenticated users. Specifically, sanctum
is a lightweight authentication system provided by Laravel, which is particularly suitable for API development.
Verify user identity.
Log request information.
Modify the request or response.
auth:api
: Suitable for applications that require complex authentication, usually used in conjunction with Passport.
auth:sanctum
: For quick, simple applications, typically used in SPAs or mobile applications, using simple token authentication provided by Laravel Sanctum
Which one to choose depends on the needs and complexity of your application. If your application only needs basic user authentication, using Sanctum will be simpler and faster; if you need more complex OAuth2 functionality, you should choose Passport.
The steps for using middleware('auth:sanctum')
and HasApiTokens
for API authentication are as follows. This will include installing Sanctum, setting up a user model, creating tokens, and protecting routes.
1. Install Laravel Sanctum
In your Laravel project, first install Sanctum via Composer:
composer require laravel/sanctum
2. Publish Sanctum configuration
Once installed, publish Sanctum's configuration and migration files:
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
3. Run database migrations
Run database migrations to create the necessary tables:
php artisan migrate
4. Configure authentication guards
In the config/auth.php
file, set the API guard to use Sanctum:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'sanctum', // Set the API guard to Sanctum
'provider' => 'users',
],
],
5. Use HasApiTokens
Trait in User Model
Introduce HasApiTokens
feature in user model (usually App\Models\User
):
namespace App\Models;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use HasApiTokens; // Introducing the HasApiTokens trait
// Other model properties and methods
}
6. Create a user token
Create a token for the user in the controller. The following is an example controller for user login and generating a token:
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
class AuthController extends Controller
{
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
$user = User::where('email', $request->email)->first();
if ($user && Hash::check($request->password, $user->password)) {
// Creating a Token
$token = $user->createToken('token-name')->plainTextToken;
return response()->json(['token' => $token], 200);
}
return response()->json(['error' => 'Unauthorized'], 401);
}
}
7. Protect routes
Use middleware('auth:sanctum')
in the route file to protect routes that require authentication. For example, to protect a route that obtains user information:
use App\Http\Controllers\AuthController;
use Illuminate\Support\Facades\Route;
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user(); // Returns the information of the currently logged in user
});
8. Make requests using API tokens
In the client (e.g., Postman or a front-end application), use the generated token to make API requests. Add the Authorization
field to the request header:
Authorization: Bearer your-token-here
Revoke tokens
You can revoke a user's token in the following ways:
// Revoke all tokens
$user->tokens()->delete();
// Or revoke a specific token
$token = $user->tokens()->find($tokenId);
$token->delete();
Summary
Through the above steps, you can successfully use middleware('auth:sanctum')
and the HasApiTokens
feature to implement API authentication. Laravel Sanctum provides a simple and effective way to manage API tokens for single-page applications (SPA) and mobile applications.
☕ Define Model Relationships
In Laravel, if you want to define a relationship in one model with another model and connect the two models through the user_id
field, you usually use the belongsTo
relationship. The following are detailed codes and steps, assuming that we have a User
model and a Post
model, and the user_id
field in the Post
model points to the User
model.
Step 1: Define Model Relationships
1.1. User Model
Define the relationship with Post
in the User
model:
// app/Models/User.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
use HasFactory;
// Define a relationship with the Post model
public function posts()
{
return $this->hasMany(Post::class);
}
}
1.2. Post model
Define the relationship between Post
and User
in the Post
model:
// app/Models/Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
// Define a relationship with the User model
public function user()
{
return $this->belongsTo(User::class);
}
}
Step 2: Create database migrations
If you haven't created the posts
table yet, you can create it through migrations. Run the following command to generate the migration file:
php artisan make:migration create_posts_table
Then in the generated migration file, define the structure of the posts
table:
// database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade'); // Adding a user_id field
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('posts');
}
}
Step 3: Run Migrations
Run migrations to create the posts
table:
php artisan migrate
Step 4: Use Relationships
Now you can use the defined relationships to get a user's posts or get a user's posts.
4.1. Get all posts for a user
use App\Models\User;
$user = User::find(1); // Get the user with ID 1
$posts = $user->posts; // Get all posts by this user
foreach ($posts as $post) {
echo $post->title; // Output the title of each post
}
4.2. Get the user of the post
use App\Models\Post;
$post = Post::find(1); // Get the post with ID 1
$user = $post->user; // Get the user of the post
echo $user->name; // Output the user name of the post
Summary
Through the above steps, you can define the relationship between User
and Post
in Laravel, and use the belongsTo
and hasMany
methods to easily perform database operations. This makes navigating between models simple and intuitive.
☕ Request
In Laravel, Request
is the core component for handling HTTP requests. Using the Request
class, you can easily get the requested data, validate input, manage file uploads, and more. The following is a detailed code and steps to introduce how to use the Request
class.
1. Import Request
class
In your controller, you can use the Request
class through dependency injection or direct import.
Dependency injection
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function store(Request $request)
{
// Handling Requests
}
}
Using the Request
facade directly
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Request;
class UserController extends Controller
{
public function store()
{
$data = Request::all(); // Get all request data
}
}
2. Get request data
You can get various data in the request through the Request
instance.
public function store(Request $request)
{
$name = $request->input('name'); // Get a single input value
$email = $request->get('email'); // Get input using the get method
$allData = $request->all(); // Get all input data
}
3. Validate request data
Use Laravel's validation function to validate the request data. You can use the validate
method in the controller.
public function store(Request $request)
{
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|string|min:8|confirmed',
]);
// After validation, you can use $validatedData
$user = User::create($validatedData);
}
4. Handling file uploads
Handling file uploads using Request
is very simple. You can use the file
method to get the uploaded file, and the store
method to save the file.
public function store(Request $request)
{
$request->validate([
'avatar' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048',
]);
if ($request->hasFile('avatar')) {
$path = $request->file('avatar')->store('avatars', 'public'); // Save to the storage/app/public/avatars directory
// You can save $path to the database
$user->avatar = $path;
$user->save();
}
}