issues Documentation

TypeScript repository by @z-song. Model Context Protocol (MCP) server & tools.

0 stars TypeScript TypeScript 1 file ยท ~50,848 tokens
RAW Doc

1. Project Overview & Quickstart (z-song/issues)

issues

Open-source repository z-song/issues

Repository Details

Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.

2. Official Technical Reference & Guides (z-song/docs)

File: readme.md

Laravel Documentation

You can find the online version of the Laravel documentation at https://laravel.com/docs

Contribution Guidelines

If you are submitting documentation for the current stable release, submit it to the corresponding branch. For example, documentation for Laravel 5.8 would be submitted to the 5.8 branch. Documentation intended for the next release of Laravel should be submitted to the master branch.


File: api-authentication.md

API Authentication

Introduction

By default, Laravel ships with a simple solution to API authentication via a random token assigned to each user of your application. In your config/auth.php configuration file, an api guard is already defined and utilizes a token driver. This driver is responsible for inspecting the API token on the incoming request and verifying that it matches the user's assigned token in the database.

Note: While Laravel ships with a simple, token based authentication guard, we strongly recommend you consider using Laravel Passport for robust, production applications that offer API authentication.

Configuration

Database Preparation

Before using the token driver, you will need to create a migration which adds an api_token column to your users table:

text
Schema::table('users', function ($table) {
    $table->string('api_token', 80)->after('password')
                        ->unique()
                        ->nullable()
                        ->default(null);
});

Once the migration has been created, run the migrate Artisan command.

{tip} If you choose to use a different column name, be sure to update your API's storage_key configuration option within the config/auth.php configuration file.

Generating Tokens

Once the api_token column has been added to your users table, you are ready to assign random API tokens to each user that registers with your application. You should assign these tokens when a User model is created for the user during registration. When using the authentication scaffolding provided by the laravel/ui Composer package, this may be done in the create method of the RegisterController:

text
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

/**
 * Create a new user instance after a valid registration.
 *
 * @param  array  $data
 * @return \App\User
 */
protected function create(array $data)
{
    return User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => Hash::make($data['password']),
        'api_token' => Str::random(60),
    ]);
}

Hashing Tokens

In the examples above, API tokens are stored in your database as plain-text. If you would like to hash your API tokens using SHA-256 hashing, you may set the hash option of your api guard configuration to true. The api guard is defined in your config/auth.php configuration file:

text
'api' => [
    'driver' => 'token',
    'provider' => 'users',
    'hash' => true,
],

Generating Hashed Tokens

When using hashed API tokens, you should not generate your API tokens during user registration. Instead, you will need to implement your own API token management page within your application. This page should allow users to initialize and refresh their API token. When a user makes a request to initialize or refresh their token, you should store a hashed copy of the token in the database, and return the plain-text copy of token to the view / frontend client for one-time display.

For example, a controller method that initializes / refreshes the token for a given user and returns the plain-text token as a JSON response might look like the following:

text
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Str;

class ApiTokenController extends Controller
{
    /**
     * Update the authenticated user's API token.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function update(Request $request)
    {
        $token = Str::random(60);

        $request->user()->forceFill([
            'api_token' => hash('sha256', $token),
        ])->save();

        return ['token' => $token];
    }
}

{tip} Since the API tokens in the example above have sufficient entropy, it is impractical to create "rainbow tables" to lookup the original value of the hashed token. Therefore, slow hashing methods such as bcrypt are unnecessary.

Protecting Routes

Laravel includes an authentication guard that will automatically validate API tokens on incoming requests. You only need to specify the auth:api middleware on any route that requires a valid access token:

text
use Illuminate\Http\Request;

Route::middleware('auth:api')->get('/user', function(Request $request) {
    return $request->user();
});

Passing Tokens In Requests

There are several ways of passing the API token to your application. We'll discuss each of these approaches while using the Guzzle HTTP library to demonstrate their usage. You may choose any of these approaches based on the needs of your application.

Query String

Your application's API consumers may specify their token as an api_token query string value:

text
$response = $client->request('GET', '/api/user?api_token='.$token);

Request Payload

Your application's API consumers may include their API token in the request's form parameters as an api_token:

text
$response = $client->request('POST', '/api/user', [
    'headers' => [
        'Accept' => 'application/json',
    ],
    'form_params' => [
        'api_token' => $token,
    ],
]);

Bearer Token

Your application's API consumers may provide their API token as a Bearer token in the Authorization header of the request:

text
$response = $client->request('POST', '/api/user', [
    'headers' => [
        'Authorization' => 'Bearer '.$token,
        'Accept' => 'application/json',
    ],
]);

File: artisan.md

Artisan Console

Introduction

Artisan is the command-line interface included with Laravel. It provides a number of helpful commands that can assist you while you build your application. To view a list of all available Artisan commands, you may use the list command:

text
php artisan list

Every command also includes a "help" screen which displays and describes the command's available arguments and options. To view a help screen, precede the name of the command with help:

text
php artisan help migrate

Tinker (REPL)

All Laravel applications include Tinker, a REPL powered by the PsySH package. Tinker allows you to interact with your entire Laravel application on the command line, including the Eloquent ORM, jobs, events, and more. To enter the Tinker environment, run the tinker Artisan command:

text
php artisan tinker

You can publish Tinker's configuration file using the vendor:publish command:

text
php artisan vendor:publish --provider="Laravel\Tinker\TinkerServiceProvider"

Command Whitelist

Tinker utilizes a white-list to determine which Artisan commands are allowed to be run within its shell. By default, you may run the clear-compiled, down, env, inspire, migrate, optimize, and up commands. If you would like to white-list more commands you may add them to the commands array in your tinker.php configuration file:

text
'commands' => [
    // App\Console\Commands\ExampleCommand::class,
],

Alias Blacklist

Typically, Tinker automatically aliases classes as you require them in Tinker. However, you may wish to never alias some classes. You may accomplish this by listing the classes in the dont_alias array of your tinker.php configuration file:

text
'dont_alias' => [
    App\User::class,
],

Writing Commands

In addition to the commands provided with Artisan, you may also build your own custom commands. Commands are typically stored in the app/Console/Commands directory; however, you are free to choose your own storage location as long as your commands can be loaded by Composer.

Generating Commands

To create a new command, use the make:command Artisan command. This command will create a new command class in the app/Console/Commands directory. Don't worry if this directory does not exist in your application, since it will be created the first time you run the make:command Artisan command. The generated command will include the default set of properties and methods that are present on all commands:

text
php artisan make:command SendEmails

Command Structure

After generating your command, you should fill in the signature and description properties of the class, which will be used when displaying your command on the list screen. The handle method will be called when your command is executed. You may place your command logic in this method.

{tip} For greater code reuse, it is good practice to keep your console commands light and let them defer to application services to accomplish their tasks. In the example below, note that we inject a service class to do the "heavy lifting" of sending the e-mails.

Let's take a look at an example command. Note that we are able to inject any dependencies we need into the command's handle method. The Laravel service container will automatically inject all dependencies that are type-hinted in this method's signature:

text
<?php

namespace App\Console\Commands;

use App\DripEmailer;
use App\User;
use Illuminate\Console\Command;

class SendEmails extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'email:send {user}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Send drip e-mails to a user';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @param  \App\DripEmailer  $drip
     * @return mixed
     */
    public function handle(DripEmailer $drip)
    {
        $drip->send(User::find($this->argument('user')));
    }
}

Closure Commands

Closure based commands provide an alternative to defining console commands as classes. In the same way that route Closures are an alternative to controllers, think of command Closures as an alternative to command classes. Within the commands method of your app/Console/Kernel.php file, Laravel loads the routes/console.php file:

text
/**
 * Register the Closure based commands for the application.
 *
 * @return void
 */
protected function commands()
{
    require base_path('routes/console.php');
}

Even though this file does not define HTTP routes, it defines console based entry points (routes) into your application. Within this file, you may define all of your Closure based routes using the Artisan::command method. The command method accepts two arguments: the command signature and a Closure which receives the commands arguments and options:

text
Artisan::command('build {project}', function ($project) {
    $this->info("Building {$project}!");
});

The Closure is bound to the underlying command instance, so you have full access to all of the helper methods you would typically be able to access on a full command class.

Type-Hinting Dependencies

In addition to receiving your command's arguments and options, command Closures may also type-hint additional dependencies that you would like resolved out of the service container:

text
use App\DripEmailer;
use App\User;

Artisan::command('email:send {user}', function (DripEmailer $drip, $user) {
    $drip->send(User::find($user));
});

Closure Command Descriptions

When defining a Closure based command, you may use the describe method to add a description to the command. This description will be displayed when you run the php artisan list or php artisan help commands:

text
Artisan::command('build {project}', function ($project) {
    $this->info("Building {$project}!");
})->describe('Build the project');

Defining Input Expectations

When writing console commands, it is common to gather input from the user through arguments or options. Laravel makes it very convenient to define the input you expect from the user using the signature property on your commands. The signature property allows you to define the name, arguments, and options for the command in a single, expressive, route-like syntax.

Arguments

All user supplied arguments and options are wrapped in curly braces. In the following example, the command defines one required argument: user:

text
/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send {user}';

You may also make arguments optional and define default values for arguments:

text
// Optional argument...
email:send {user?}

// Optional argument with default value...
email:send {user=foo}

Options

Options, like arguments, are another form of user input. Options are prefixed by two hyphens (--) when they are specified on the command line. There are two types of options: those that receive a value and those that don't. Options that don't receive a value serve as a boolean "switch". Let's take a look at an example of this type of option:

text
/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue}';

In this example, the --queue switch may be specified when calling the Artisan command. If the --queue switch is passed, the value of the option will be true. Otherwise, the value will be false:

text
php artisan email:send 1 --queue

Options With Values

Next, let's take a look at an option that expects a value. If the user must specify a value for an option, suffix the option name with a = sign:

text
/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send {user} {--queue=}';

In this example, the user may pass a value for the option like so:

text
php artisan email:send 1 --queue=default

You may assign default values to options by specifying the default value after the option name. If no option value is passed by the user, the default value will be used:

text
email:send {user} {--queue=default}

Option Shortcuts

To assign a shortcut when defining an option, you may specify it before the option name and use a | delimiter to separate the shortcut from the full option name:

text
email:send {user} {--Q|queue}

Input Arrays

If you would like to define arguments or options to expect array inputs, you may use the * character. First, let's take a look at an example that specifies an array argument:

text
email:send {user*}

When calling this method, the user arguments may be passed in order to the command line. For example, the following command will set the value of user to ['foo', 'bar']:

text
php artisan email:send foo bar

When defining an option that expects an array input, each option value passed to the command should be prefixed with the option name:

text
email:send {user} {--id=*}

php artisan email:send --id=1 --id=2

Input Descriptions

You may assign descriptions to input arguments and options by separating the parameter from the description using a colon. If you need a little extra room to define your command, feel free to spread the definition across multiple lines:

text
/**
 * The name and signature of the console command.
 *
 * @var string
 */
protected $signature = 'email:send
                        {user : The ID of the user}
                        {--queue= : Whether the job should be queued}';

Command I/O

Retrieving Input

While your command is executing, you will obviously need to access the values for the arguments and options accepted by your command. To do so, you may use the argument and option methods:

text
/**
 * Execute the console command.
 *
 * @return mixed
 */
public function handle()
{
    $userId = $this->argument('user');

    //
}

If you need to retrieve all of the arguments as an array, call the arguments method:

text
$arguments = $this->arguments();

Options may be retrieved just as easily as arguments using the option method. To retrieve all of the options as an array, call the options method:

text
// Retrieve a specific option...
$queueName = $this->option('queue');

// Retrieve all options...
$options = $this->options();

If the argument or option does not exist, null will be returned.

Prompting For Input

In addition to displaying output, you may also ask the user to provide input during the execution of your command. The ask method will prompt the user with the given question, accept their input, and then return the user's input back to your command:

text
/**
 * Execute the console command.
 *
 * @return mixed
 */
public function handle()
{
    $name = $this->ask('What is your name?');
}

The secret method is similar to ask, but the user's input will not be visible to them as they type in the console. This method is useful when asking for sensitive information such as a password:

text
$password = $this->secret('What is the password?');

Asking For Confirmation

If you need to ask the user for a simple confirmation, you may use the confirm method. By default, this method will return false. However, if the user enters y or yes in response to the prompt, the method will return true.

text
if ($this->confirm('Do you wish to continue?')) {
    //
}

Auto-Completion

The anticipate method can be used to provide auto-completion for possible choices. The user can still choose any answer, regardless of the auto-completion hints:

text
$name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']);

Multiple Choice Questions

If you need to give the user a predefined set of choices, you may use the choice method. You may set the array index of the default value to be returned if no option is chosen:

text
$name = $this->choice('What is your name?', ['Taylor', 'Dayle'], $defaultIndex);

Writing Output

To send output to the console, use the line, info, comment, question and error methods. Each of these methods will use appropriate ANSI colors for their purpose. For example, let's display some general information to the user. Typically, the info method will display in the console as green text:

text
/**
 * Execute the console command.
 *
 * @return mixed
 */
public function handle()
{
    $this->info('Display this on the screen');
}

To display an error message, use the error method. Error message text is typically displayed in red:

text
$this->error('Something went wrong!');

If you would like to display plain, uncolored console output, use the line method:

text
$this->line('Display this on the screen');

Table Layouts

The table method makes it easy to correctly format multiple rows / columns of data. Just pass in the headers and rows to the method. The width and height will be dynamically calculated based on the given data:

text
$headers = ['Name', 'Email'];

$users = App\User::all(['name', 'email'])->toArray();

$this->table($headers, $users);

Progress Bars

For long running tasks, it could be helpful to show a progress indicator. Using the output object, we can start, advance and stop the Progress Bar. First, define the total number of steps the process will iterate through. Then, advance the Progress Bar after processing each item:

text
$users = App\User::all();

$bar = $this->output->createProgressBar(count($users));

$bar->start();

foreach ($users as $user) {
    $this->performTask($user);

    $bar->advance();
}

$bar->finish();

For more advanced options, check out the Symfony Progress Bar component documentation.

Registering Commands

Because of the load method call in your console kernel's commands method, all commands within the app/Console/Commands directory will automatically be registered with Artisan. In fact, you are free to make additional calls to the load method to scan other directories for Artisan commands:

text
/**
 * Register the commands for the application.
 *
 * @return void
 */
protected function commands()
{
    $this->load(__DIR__.'/Commands');
    $this->load(__DIR__.'/MoreCommands');

    // ...
}

You may also manually register commands by adding its class name to the $commands property of your app/Console/Kernel.php file. When Artisan boots, all the commands listed in this property will be resolved by the service container and registered with Artisan:

text
protected $commands = [
    Commands\SendEmails::class
];

Programmatically Executing Commands

Sometimes you may wish to execute an Artisan command outside of the CLI. For example, you may wish to fire an Artisan command from a route or controller. You may use the call method on the Artisan facade to accomplish this. The call method accepts either the command's name or class as the first argument, and an array of command parameters as the second argument. The exit code will be returned:

text
Route::get('/foo', function () {
    $exitCode = Artisan::call('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);

    //
});

Alternatively, you may pass the entire Artisan command to the call method as a string:

text
Artisan::call('email:send 1 --queue=default');

Using the queue method on the Artisan facade, you may even queue Artisan commands so they are processed in the background by your queue workers. Before using this method, make sure you have configured your queue and are running a queue listener:

text
Route::get('/foo', function () {
    Artisan::queue('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);

    //
});

You may also specify the connection or queue the Artisan command should be dispatched to:

text
Artisan::queue('email:send', [
    'user' => 1, '--queue' => 'default'
])->onConnection('redis')->onQueue('commands');

Passing Array Values

If your command defines an option that accepts an array, you may pass an array of values to that option:

text
Route::get('/foo', function () {
    $exitCode = Artisan::call('email:send', [
        'user' => 1, '--id' => [5, 13]
    ]);
});

Passing Boolean Values

If you need to specify the value of an option that does not accept string values, such as the --force flag on the migrate:refresh command, you should pass true or false:

text
$exitCode = Artisan::call('migrate:refresh', [
    '--force' => true,
]);

Calling Commands From Other Commands

Sometimes you may wish to call other commands from an existing Artisan command. You may do so using the call method. This call method accepts the command name and an array of command parameters:

text
/**
 * Execute the console command.
 *
 * @return mixed
 */
public function handle()
{
    $this->call('email:send', [
        'user' => 1, '--queue' => 'default'
    ]);

    //
}

If you would like to call another console command and suppress all of its output, you may use the callSilent method. The callSilent method has the same signature as the call method:

text
$this->callSilent('email:send', [
    'user' => 1, '--queue' => 'default'
]);

File: authentication.md

Authentication

Introduction

{tip} Want to get started fast? Install the laravel/ui Composer package and run php artisan ui vue --auth in a fresh Laravel application. After migrating your database, navigate your browser to http://your-app.test/register or any other URL that is assigned to your application. These commands will take care of scaffolding your entire authentication system!

Laravel makes implementing authentication very simple. In fact, almost everything is configured for you out of the box. The authentication configuration file is located at config/auth.php, which contains several well documented options for tweaking the behavior of the authentication services.

At its core, Laravel's authentication facilities are made up of "guards" and "providers". Guards define how users are authenticated for each request. For example, Laravel ships with a session guard which maintains state using session storage and cookies.

Providers define how users are retrieved from your persistent storage. Laravel ships with support for retrieving users using Eloquent and the database query builder. However, you are free to define additional providers as needed for your application.

Don't worry if this all sounds confusing now! Many applications will never need to modify the default authentication configuration.

Database Considerations

By default, Laravel includes an App\User Eloquent model in your app directory. This model may be used with the default Eloquent authentication driver. If your application is not using Eloquent, you may use the database authentication driver which uses the Laravel query builder.

When building the database schema for the App\User model, make sure the password column is at least 60 characters in length. Maintaining the default string column length of 255 characters would be a good choice.

Also, you should verify that your users (or equivalent) table contains a nullable, string remember_token column of 100 characters. This column will be used to store a token for users that select the "remember me" option when logging into your application.

Authentication Quickstart

Laravel ships with several pre-built authentication controllers, which are located in the App\Http\Controllers\Auth namespace. The RegisterController handles new user registration, the LoginController handles authentication, the ForgotPasswordController handles e-mailing links for resetting passwords, and the ResetPasswordController contains the logic to reset passwords. Each of these controllers uses a trait to include their necessary methods. For many applications, you will not need to modify these controllers at all.

Routing

Laravel's laravel/ui package provides a quick way to scaffold all of the routes and views you need for authentication using a few simple commands:

text
composer require laravel/ui --dev

php artisan ui vue --auth

This command should be used on fresh applications and will install a layout view, registration and login views, as well as routes for all authentication end-points. A HomeController will also be generated to handle post-login requests to your application's dashboard.

{tip} If your application doesnโ€™t need registration, you may disable it by removing the newly created RegisterController and modifying your route declaration: Auth::routes(['register' => false]);.

Views

As mentioned in the previous section, the laravel/ui package's php artisan ui vue --auth command will create all of the views you need for authentication and place them in the resources/views/auth directory.

The ui command will also create a resources/views/layouts directory containing a base layout for your application. All of these views use the Bootstrap CSS framework, but you are free to customize them however you wish.

Authenticating

Now that you have routes and views setup for the included authentication controllers, you are ready to register and authenticate new users for your application! You may access your application in a browser since the authentication controllers already contain the logic (via their traits) to authenticate existing users and store new users in the database.

Path Customization

When a user is successfully authenticated, they will be redirected to the /home URI. You can customize the post-authentication redirect location by defining a redirectTo property on the LoginController, RegisterController, ResetPasswordController, and VerificationController:

text
protected $redirectTo = '/';

Next, you should modify the RedirectIfAuthenticated middleware's handle method to use your new URI when redirecting the user.

If the redirect path needs custom generation logic you may define a redirectTo method instead of a redirectTo property:

text
protected function redirectTo()
{
    return '/path';
}

{tip} The redirectTo method will take precedence over the redirectTo property.

Username Customization

By default, Laravel uses the email field for authentication. If you would like to customize this, you may define a username method on your LoginController:

text
public function username()
{
    return 'username';
}

Guard Customization

You may also customize the "guard" that is used to authenticate and register users. To get started, define a guard method on your LoginController, RegisterController, and ResetPasswordController. The method should return a guard instance:

text
use Illuminate\Support\Facades\Auth;

protected function guard()
{
    return Auth::guard('guard-name');
}

Validation / Storage Customization

To modify the form fields that are required when a new user registers with your application, or to customize how new users are stored into your database, you may modify the RegisterController class. This class is responsible for validating and creating new users of your application.

The validator method of the RegisterController contains the validation rules for new users of the application. You are free to modify this method as you wish.

The create method of the RegisterController is responsible for creating new App\User records in your database using the Eloquent ORM. You are free to modify this method according to the needs of your database.

Retrieving The Authenticated User

You may access the authenticated user via the Auth facade:

text
use Illuminate\Support\Facades\Auth;

// Get the currently authenticated user...
$user = Auth::user();

// Get the currently authenticated user's ID...
$id = Auth::id();

Alternatively, once a user is authenticated, you may access the authenticated user via an Illuminate\Http\Request instance. Remember, type-hinted classes will automatically be injected into your controller methods:

text
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ProfileController extends Controller
{
    /**
     * Update the user's profile.
     *
     * @param  Request  $request
     * @return Response
     */
    public function update(Request $request)
    {
        // $request->user() returns an instance of the authenticated user...
    }
}

Determining If The Current User Is Authenticated

To determine if the user is already logged into your application, you may use the check method on the Auth facade, which will return true if the user is authenticated:

text
use Illuminate\Support\Facades\Auth;

if (Auth::check()) {
    // The user is logged in...
}

{tip} Even though it is possible to determine if a user is authenticated using the check method, you will typically use a middleware to verify that the user is authenticated before allowing the user access to certain routes / controllers. To learn more about this, check out the documentation on protecting routes.

Protecting Routes

Route middleware can be used to only allow authenticated users to access a given route. Laravel ships with an auth middleware, which is defined at Illuminate\Auth\Middleware\Authenticate. Since this middleware is already registered in your HTTP kernel, all you need to do is attach the middleware to a route definition:

text
Route::get('profile', function () {
    // Only authenticated users may enter...
})->middleware('auth');

If you are using controllers, you may call the middleware method from the controller's constructor instead of attaching it in the route definition directly:

text
public function __construct()
{
    $this->middleware('auth');
}

Redirecting Unauthenticated Users

When the auth middleware detects an unauthorized user, it will redirect the user to the login named route. You may modify this behavior by updating the redirectTo function in your app/Http/Middleware/Authenticate.php file:

text
/**
 * Get the path the user should be redirected to.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return string
 */
protected function redirectTo($request)
{
    return route('login');
}

Specifying A Guard

When attaching the auth middleware to a route, you may also specify which guard should be used to authenticate the user. The guard specified should correspond to one of the keys in the guards array of your auth.php configuration file:

text
public function __construct()
{
    $this->middleware('auth:api');
}

Password Confirmation

Sometimes, you may wish to require the user to confirm their password before accessing a specific area of your application. For example, you may require this before the user modifies any billing settings within the application.

To accomplish this, Laravel provides a password.confirm middleware. Attaching the password.confirm middleware to a route will redirect users to a screen where they need to confirm their password before they can continue:

text
Route::get('/settings/security', function () {
    // Users must confirm their password before continuing...
})->middleware(['auth', 'password.confirm']);

After the user has successfully confirmed their password, the user is redirected to the route they originally tried to access. By default, after confirming their password, the user will not have to confirm their password again for three hours. You are free to customize the length of time before the user must re-confirm their password using the auth.password_timeout configuration option.

Login Throttling

If you are using Laravel's built-in LoginController class, the Illuminate\Foundation\Auth\ThrottlesLogins trait will already be included in your controller. By default, the user will not be able to login for one minute if they fail to provide the correct credentials after several attempts. The throttling is unique to the user's username / e-mail address and their IP address.

Manually Authenticating Users

Note that you are not required to use the authentication controllers included with Laravel. If you choose to remove these controllers, you will need to manage user authentication using the Laravel authentication classes directly. Don't worry, it's a cinch!

We will access Laravel's authentication services via the Auth facade, so we'll need to make sure to import the Auth facade at the top of the class. Next, let's check out the attempt method:

text
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    /**
     * Handle an authentication attempt.
     *
     * @param  \Illuminate\Http\Request $request
     *
     * @return Response
     */
    public function authenticate(Request $request)
    {
        $credentials = $request->only('email', 'password');

        if (Auth::attempt($credentials)) {
            // Authentication passed...
            return redirect()->intended('dashboard');
        }
    }
}

The attempt method accepts an array of key / value pairs as its first argument. The values in the array will be used to find the user in your database table. So, in the example above, the user will be retrieved by the value of the email column. If the user is found, the hashed password stored in the database will be compared with the password value passed to the method via the array. You should not hash the password specified as the password value, since the framework will automatically hash the value before comparing it to the hashed password in the database. If the two hashed passwords match an authenticated session will be started for the user.

The attempt method will return true if authentication was successful. Otherwise, false will be returned.

The intended method on the redirector will redirect the user to the URL they were attempting to access before being intercepted by the authentication middleware. A fallback URI may be given to this method in case the intended destination is not available.

Specifying Additional Conditions

If you wish, you may also add extra conditions to the authentication query in addition to the user's e-mail and password. For example, we may verify that user is marked as "active":

text
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
    // The user is active, not suspended, and exists.
}

{note} In these examples, email is not a required option, it is merely used as an example. You should use whatever column name corresponds to a "username" in your database.

Accessing Specific Guard Instances

You may specify which guard instance you would like to utilize using the guard method on the Auth facade. This allows you to manage authentication for separate parts of your application using entirely separate authenticatable models or user tables.

The guard name passed to the guard method should correspond to one of the guards configured in your auth.php configuration file:

text
if (Auth::guard('admin')->attempt($credentials)) {
    //
}

Logging Out

To log users out of your application, you may use the logout method on the Auth facade. This will clear the authentication information in the user's session:

text
Auth::logout();

Remembering Users

If you would like to provide "remember me" functionality in your application, you may pass a boolean value as the second argument to the attempt method, which will keep the user authenticated indefinitely, or until they manually logout. Your users table must include the string remember_token column, which will be used to store the "remember me" token.

text
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
    // The user is being remembered...
}

{tip} If you are using the built-in LoginController that is shipped with Laravel, the proper logic to "remember" users is already implemented by the traits used by the controller.

If you are "remembering" users, you may use the viaRemember method to determine if the user was authenticated using the "remember me" cookie:

text
if (Auth::viaRemember()) {
    //
}

Other Authentication Methods

Authenticate A User Instance

If you need to log an existing user instance into your application, you may call the login method with the user instance. The given object must be an implementation of the Illuminate\Contracts\Auth\Authenticatable contract. The App\User model included with Laravel already implements this interface:

text
Auth::login($user);

// Login and "remember" the given user...
Auth::login($user, true);

You may specify the guard instance you would like to use:

text
Auth::guard('admin')->login($user);

Authenticate A User By ID

To log a user into the application by their ID, you may use the loginUsingId method. This method accepts the primary key of the user you wish to authenticate:

text
Auth::loginUsingId(1);

// Login and "remember" the given user...
Auth::loginUsingId(1, true);

Authenticate A User Once

You may use the once method to log a user into the application for a single request. No sessions or cookies will be utilized, which means this method may be helpful when building a stateless API:

text
if (Auth::once($credentials)) {
    //
}

HTTP Basic Authentication

HTTP Basic Authentication provides a quick way to authenticate users of your application without setting up a dedicated "login" page. To get started, attach the auth.basic middleware to your route. The auth.basic middleware is included with the Laravel framework, so you do not need to define it:

text
Route::get('profile', function () {
    // Only authenticated users may enter...
})->middleware('auth.basic');

Once the middleware has been attached to the route, you will automatically be prompted for credentials when accessing the route in your browser. By default, the auth.basic middleware will use the email column on the user record as the "username".

A Note On FastCGI

If you are using PHP FastCGI, HTTP Basic authentication may not work correctly out of the box. The following lines should be added to your .htaccess file:

text
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Stateless HTTP Basic Authentication

You may also use HTTP Basic Authentication without setting a user identifier cookie in the session, which is particularly useful for API authentication. To do so, define a middleware that calls the onceBasic method. If no response is returned by the onceBasic method, the request may be passed further into the application:

text
<?php

namespace App\Http\Middleware;

use Illuminate\Support\Facades\Auth;

class AuthenticateOnceWithBasicAuth
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, $next)
    {
        return Auth::onceBasic() ?: $next($request);
    }

}

Next, register the route middleware and attach it to a route:

text
Route::get('api/user', function () {
    // Only authenticated users may enter...
})->middleware('auth.basic.once');

Logging Out

To manually log users out of your application, you may use the logout method on the Auth facade. This will clear the authentication information in the user's session:

text
use Illuminate\Support\Facades\Auth;

Auth::logout();

Invalidating Sessions On Other Devices

Laravel also provides a mechanism for invalidating and "logging out" a user's sessions that are active on other devices without invalidating the session on their current device. Before getting started, you should make sure that the Illuminate\Session\Middleware\AuthenticateSession middleware is present and un-commented in your app/Http/Kernel.php class' web middleware group:

text
'web' => [
    // ...
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    // ...
],

Then, you may use the logoutOtherDevices method on the Auth facade. This method requires the user to provide their current password, which your application should accept through an input form:

text
use Illuminate\Support\Facades\Auth;

Auth::logoutOtherDevices($password);

{note} When the logoutOtherDevices method is invoked, the user's other sessions will be invalidated entirely, meaning they will be "logged out" of all guards they were previously authenticated by.

Adding Custom Guards

You may define your own authentication guards using the extend method on the Auth facade. You should place this call to extend within a service provider. Since Laravel already ships with an AuthServiceProvider, we can place the code in that provider:

text
<?php

namespace App\Providers;

use App\Services\Auth\JwtGuard;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * Register any application authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Auth::extend('jwt', function ($app, $name, array $config) {
            // Return an instance of Illuminate\Contracts\Auth\Guard...

            return new JwtGuard(Auth::createUserProvider($config['provider']));
        });
    }
}

As you can see in the example above, the callback passed to the extend method should return an implementation of Illuminate\Contracts\Auth\Guard. This interface contains a few methods you will need to implement to define a custom guard. Once your custom guard has been defined, you may use this guard in the guards configuration of your auth.php configuration file:

text
'guards' => [
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

Closure Request Guards

The simplest way to implement a custom, HTTP request based authentication system is by using the Auth::viaRequest method. This method allows you to quickly define your authentication process using a single Closure.

To get started, call the Auth::viaRequest method within the boot method of your AuthServiceProvider. The viaRequest method accepts an authentication driver name as its first argument. This name can be any string that describes your custom guard. The second argument passed to the method should be a Closure that receives the incoming HTTP request and returns a user instance or, if authentication fails, null:

text
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

/**
 * Register any application authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Auth::viaRequest('custom-token', function ($request) {
        return User::where('token', $request->token)->first();
    });
}

Once your custom authentication driver has been defined, you use it as a driver within guards configuration of your auth.php configuration file:

text
'guards' => [
    'api' => [
        'driver' => 'custom-token',
    ],
],

Adding Custom User Providers

If you are not using a traditional relational database to store your users, you will need to extend Laravel with your own authentication user provider. We will use the provider method on the Auth facade to define a custom user provider:

text
<?php

namespace App\Providers;

use App\Extensions\RiakUserProvider;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * Register any application authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Auth::provider('riak', function ($app, array $config) {
            // Return an instance of Illuminate\Contracts\Auth\UserProvider...

            return new RiakUserProvider($app->make('riak.connection'));
        });
    }
}

After you have registered the provider using the provider method, you may switch to the new user provider in your auth.php configuration file. First, define a provider that uses your new driver:

text
'providers' => [
    'users' => [
        'driver' => 'riak',
    ],
],

Finally, you may use this provider in your guards configuration:

text
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
],

The User Provider Contract

The Illuminate\Contracts\Auth\UserProvider implementations are only responsible for fetching a Illuminate\Contracts\Auth\Authenticatable implementation out of a persistent storage system, such as MySQL, Riak, etc. These two interfaces allow the Laravel authentication mechanisms to continue functioning regardless of how the user data is stored or what type of class is used to represent it.

Let's take a look at the Illuminate\Contracts\Auth\UserProvider contract:

text
<?php

namespace Illuminate\Contracts\Auth;

interface UserProvider
{
    public function retrieveById($identifier);
    public function retrieveByToken($identifier, $token);
    public function updateRememberToken(Authenticatable $user, $token);
    public function retrieveByCredentials(array $credentials);
    public function validateCredentials(Authenticatable $user, array $credentials);
}

The retrieveById function typically receives a key representing the user, such as an auto-incrementing ID from a MySQL database. The Authenticatable implementation matching the ID should be retrieved and returned by the method.

The retrieveByToken function retrieves a user by their unique $identifier and "remember me" $token, stored in a field remember_token. As with the previous method, the Authenticatable implementation should be returned.

The updateRememberToken method updates the $user field remember_token with the new $token. A fresh token is assigned on a successful "remember me" login attempt or when the user is logging out.

The retrieveByCredentials method receives the array of credentials passed to the Auth::attempt method when attempting to sign into an application. The method should then "query" the underlying persistent storage for the user matching those credentials. Typically, this method will run a query with a "where" condition on $credentials['username']. The method should then return an implementation of Authenticatable. This method should not attempt to do any password validation or authentication.

The validateCredentials method should compare the given $user with the $credentials to authenticate the user. For example, this method should probably use Hash::check to compare the value of $user->getAuthPassword() to the value of $credentials['password']. This method should return true or false indicating on whether the password is valid.

The Authenticatable Contract

Now that we have explored each of the methods on the UserProvider, let's take a look at the Authenticatable contract. Remember, the provider should return implementations of this interface from the retrieveById, retrieveByToken, and retrieveByCredentials methods:

text
<?php

namespace Illuminate\Contracts\Auth;

interface Authenticatable
{
    public function getAuthIdentifierName();
    public function getAuthIdentifier();
    public function getAuthPassword();
    public function getRememberToken();
    public function setRememberToken($value);
    public function getRememberTokenName();
}

This interface is simple. The getAuthIdentifierName method should return the name of the "primary key" field of the user and the getAuthIdentifier method should return the "primary key" of the user. In a MySQL back-end, again, this would be the auto-incrementing primary key. The getAuthPassword should return the user's hashed password. This interface allows the authentication system to work with any User class, regardless of what ORM or storage abstraction layer you are using. By default, Laravel includes a User class in the app directory which implements this interface, so you may consult this class for an implementation example.

Events

Laravel raises a variety of events during the authentication process. You may attach listeners to these events in your EventServiceProvider:

text
/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'Illuminate\Auth\Events\Registered' => [
        'App\Listeners\LogRegisteredUser',
    ],

    'Illuminate\Auth\Events\Attempting' => [
        'App\Listeners\LogAuthenticationAttempt',
    ],

    'Illuminate\Auth\Events\Authenticated' => [
        'App\Listeners\LogAuthenticated',
    ],

    'Illuminate\Auth\Events\Login' => [
        'App\Listeners\LogSuccessfulLogin',
    ],

    'Illuminate\Auth\Events\Failed' => [
        'App\Listeners\LogFailedLogin',
    ],

    'Illuminate\Auth\Events\Logout' => [
        'App\Listeners\LogSuccessfulLogout',
    ],

    'Illuminate\Auth\Events\Lockout' => [
        'App\Listeners\LogLockout',
    ],

    'Illuminate\Auth\Events\PasswordReset' => [
        'App\Listeners\LogPasswordReset',
    ],
];

File: authorization.md

Authorization

Introduction

In addition to providing authentication services out of the box, Laravel also provides a simple way to authorize user actions against a given resource. Like authentication, Laravel's approach to authorization is simple, and there are two primary ways of authorizing actions: gates and policies.

Think of gates and policies like routes and controllers. Gates provide a simple, Closure based approach to authorization while policies, like controllers, group their logic around a particular model or resource. We'll explore gates first and then examine policies.

You do not need to choose between exclusively using gates or exclusively using policies when building an application. Most applications will most likely contain a mixture of gates and policies, and that is perfectly fine! Gates are most applicable to actions which are not related to any model or resource, such as viewing an administrator dashboard. In contrast, policies should be used when you wish to authorize an action for a particular model or resource.

Gates

Writing Gates

Gates are Closures that determine if a user is authorized to perform a given action and are typically defined in the App\Providers\AuthServiceProvider class using the Gate facade. Gates always receive a user instance as their first argument, and may optionally receive additional arguments such as a relevant Eloquent model:

text
/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Gate::define('edit-settings', function ($user) {
        return $user->isAdmin;
    });

    Gate::define('update-post', function ($user, $post) {
        return $user->id === $post->user_id;
    });
}

Gates may also be defined using a Class@method style callback string, like controllers:

text
/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Gate::define('update-post', 'App\Policies\PostPolicy@update');
}

Authorizing Actions

To authorize an action using gates, you should use the allows or denies methods. Note that you are not required to pass the currently authenticated user to these methods. Laravel will automatically take care of passing the user into the gate Closure:

text
if (Gate::allows('edit-settings')) {
    // The current user can edit settings
}

if (Gate::allows('update-post', $post)) {
    // The current user can update the post...
}

if (Gate::denies('update-post', $post)) {
    // The current user can't update the post...
}

If you would like to determine if a particular user is authorized to perform an action, you may use the forUser method on the Gate facade:

text
if (Gate::forUser($user)->allows('update-post', $post)) {
    // The user can update the post...
}

if (Gate::forUser($user)->denies('update-post', $post)) {
    // The user can't update the post...
}

You may authorize multiple actions at a time with the any or none methods:

text
if (Gate::any(['update-post', 'delete-post'], $post)) {
    // The user can update or delete the post
}

if (Gate::none(['update-post', 'delete-post'], $post)) {
    // The user cannot update or delete the post
}

Authorizing Or Throwing Exceptions

If you would like to attempt to authorize an action and automatically throw an Illuminate\Auth\Access\AuthorizationException if the user is not allowed to perform the given action, you may use the Gate::authorize method. Instances of AuthorizationException are automatically converted to 403 HTTP response:

text
Gate::authorize('update-post', $post);

// The action is authorized...

Supplying Additional Context

The gate methods for authorizing abilities (allows, denies, check, any, none, authorize, can, cannot) and the authorization Blade directives (@can, @cannot, @canany) can receive an array as the second argument. These array elements are passed as parameters to gate, and can be used for additional context when making authorization decisions:

text
Gate::define('create-post', function ($user, $category, $extraFlag) {
    return $category->group > 3 && $extraFlag === true;
});

if (Gate::check('create-post', [$category, $extraFlag])) {
    // The user can create the post...
}

Gate Responses

So far, we have only examined gates that return simple boolean values. However, sometimes you may wish to return a more detail response, including an error message. To do so, you may return a Illuminate\Auth\Access\Response from your gate:

text
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;

Gate::define('edit-settings', function ($user) {
    return $user->isAdmin
                ? Response::allow()
                : Response::deny('You must be a super administrator.');
});

When returning an authorization response from your gate, the Gate::allows method will still return a simple boolean value; however, you may use the Gate::inspect method to get the full authorization response returned by the gate:

text
$response = Gate::inspect('edit-settings', $post);

if ($response->allowed()) {
    // The action is authorized...
} else {
    echo $response->message();
}

Of course, when using the Gate::authorize method to throw an AuthorizationException if the action is not authorized, the error message provided by the authorization response will be propagated to the HTTP response:

text
Gate::authorize('edit-settings', $post);

// The action is authorized...

Intercepting Gate Checks

Sometimes, you may wish to grant all abilities to a specific user. You may use the before method to define a callback that is run before all other authorization checks:

text
Gate::before(function ($user, $ability) {
    if ($user->isSuperAdmin()) {
        return true;
    }
});

If the before callback returns a non-null result that result will be considered the result of the check.

You may use the after method to define a callback to be executed after all other authorization checks:

text
Gate::after(function ($user, $ability, $result, $arguments) {
    if ($user->isSuperAdmin()) {
        return true;
    }
});

Similar to the before check, if the after callback returns a non-null result that result will be considered the result of the check.

Creating Policies

Generating Policies

Policies are classes that organize authorization logic around a particular model or resource. For example, if your application is a blog, you may have a Post model and a corresponding PostPolicy to authorize user actions such as creating or updating posts.

You may generate a policy using the make:policy artisan command. The generated policy will be placed in the app/Policies directory. If this directory does not exist in your application, Laravel will create it for you:

text
php artisan make:policy PostPolicy

The make:policy command will generate an empty policy class. If you would like to generate a class with the basic "CRUD" policy methods already included in the class, you may specify a --model when executing the command:

text
php artisan make:policy PostPolicy --model=Post

{tip} All policies are resolved via the Laravel service container, allowing you to type-hint any needed dependencies in the policy's constructor to have them automatically injected.

Registering Policies

Once the policy exists, it needs to be registered. The AuthServiceProvider included with fresh Laravel applications contains a policies property which maps your Eloquent models to their corresponding policies. Registering a policy will instruct Laravel which policy to utilize when authorizing actions against a given model:

text
<?php

namespace App\Providers;

use App\Policies\PostPolicy;
use App\Post;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        Post::class => PostPolicy::class,
    ];

    /**
     * Register any application authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        //
    }
}

Policy Auto-Discovery

Instead of manually registering model policies, Laravel can auto-discover policies as long as the model and policy follow standard Laravel naming conventions. Specifically, the policies must be in a Policies directory below the directory that contains the models. So, for example, the models may be placed in the app directory while the policies may be placed in the app/Policies directory. In addition, the policy name must match the model name and have a Policy suffix. So, a User model would correspond to a UserPolicy class.

If you would like to provide your own policy discovery logic, you may register a custom callback using the Gate::guessPolicyNamesUsing method. Typically, this method should be called from the boot method of your application's AuthServiceProvider:

text
use Illuminate\Support\Facades\Gate;

Gate::guessPolicyNamesUsing(function ($modelClass) {
    // return policy class name...
});

{note} Any policies that are explicitly mapped in your AuthServiceProvider will take precedence over any potential auto-discovered policies.

Writing Policies

Policy Methods

Once the policy has been registered, you may add methods for each action it authorizes. For example, let's define an update method on our PostPolicy which determines if a given User can update a given Post instance.

The update method will receive a User and a Post instance as its arguments, and should return true or false indicating whether the user is authorized to update the given Post. So, for this example, let's verify that the user's id matches the user_id on the post:

text
<?php

namespace App\Policies;

use App\Post;
use App\User;

class PostPolicy
{
    /**
     * Determine if the given post can be updated by the user.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return bool
     */
    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}

You may continue to define additional methods on the policy as needed for the various actions it authorizes. For example, you might define view or delete methods to authorize various Post actions, but remember you are free to give your policy methods any name you like.

{tip} If you used the --model option when generating your policy via the Artisan console, it will already contain methods for the view, create, update, delete, restore, and forceDelete actions.

Policy Responses

So far, we have only examined policy methods that return simple boolean values. However, sometimes you may wish to return a more detail response, including an error message. To do so, you may return a Illuminate\Auth\Access\Response from your policy method:

text
use Illuminate\Auth\Access\Response;

/**
 * Determine if the given post can be updated by the user.
 *
 * @param  \App\User  $user
 * @param  \App\Post  $post
 * @return bool
 */
public function update(User $user, Post $post)
{
    return $user->id === $post->user_id
                ? Response::allow()
                : Response::deny('You do not own this post.');
}

When returning an authorization response from your policy, the Gate::allows method will still return a simple boolean value; however, you may use the Gate::inspect method to get the full authorization response returned by the gate:

text
$response = Gate::inspect('update', $post);

if ($response->allowed()) {
    // The action is authorized...
} else {
    echo $response->message();
}

Of course, when using the Gate::authorize method to throw an AuthorizationException if the action is not authorized, the error message provided by the authorization response will be propagated to the HTTP response:

text
Gate::authorize('update', $post);

// The action is authorized...

Methods Without Models

Some policy methods only receive the currently authenticated user and not an instance of the model they authorize. This situation is most common when authorizing create actions. For example, if you are creating a blog, you may wish to check if a user is authorized to create any posts at all.

When defining policy methods that will not receive a model instance, such as a create method, it will not receive a model instance. Instead, you should define the method as only expecting the authenticated user:

text
/**
 * Determine if the given user can create posts.
 *
 * @param  \App\User  $user
 * @return bool
 */
public function create(User $user)
{
    //
}

Guest Users

By default, all gates and policies automatically return false if the incoming HTTP request was not initiated by an authenticated user. However, you may allow these authorization checks to pass through to your gates and policies by declaring an "optional" type-hint or supplying a null default value for the user argument definition:

text
<?php

namespace App\Policies;

use App\Post;
use App\User;

class PostPolicy
{
    /**
     * Determine if the given post can be updated by the user.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return bool
     */
    public function update(?User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}

Policy Filters

For certain users, you may wish to authorize all actions within a given policy. To accomplish this, define a before method on the policy. The before method will be executed before any other methods on the policy, giving you an opportunity to authorize the action before the intended policy method is actually called. This feature is most commonly used for authorizing application administrators to perform any action:

text
public function before($user, $ability)
{
    if ($user->isSuperAdmin()) {
        return true;
    }
}

If you would like to deny all authorizations for a user you should return false from the before method. If null is returned, the authorization will fall through to the policy method.

{note} The before method of a policy class will not be called if the class doesn't contain a method with a name matching the name of the ability being checked.

Authorizing Actions Using Policies

Via The User Model

The User model that is included with your Laravel application includes two helpful methods for authorizing actions: can and cant. The can method receives the action you wish to authorize and the relevant model. For example, let's determine if a user is authorized to update a given Post model:

text
if ($user->can('update', $post)) {
    //
}

If a policy is registered for the given model, the can method will automatically call the appropriate policy and return the boolean result. If no policy is registered for the model, the can method will attempt to call the Closure based Gate matching the given action name.

Actions That Don't Require Models

Remember, some actions like create may not require a model instance. In these situations, you may pass a class name to the can method. The class name will be used to determine which policy to use when authorizing the action:

text
use App\Post;

if ($user->can('create', Post::class)) {
    // Executes the "create" method on the relevant policy...
}

Via Middleware

Laravel includes a middleware that can authorize actions before the incoming request even reaches your routes or controllers. By default, the Illuminate\Auth\Middleware\Authorize middleware is assigned the can key in your App\Http\Kernel class. Let's explore an example of using the can middleware to authorize that a user can update a blog post:

text
use App\Post;

Route::put('/post/{post}', function (Post $post) {
    // The current user may update the post...
})->middleware('can:update,post');

In this example, we're passing the can middleware two arguments. The first is the name of the action we wish to authorize and the second is the route parameter we wish to pass to the policy method. In this case, since we are using implicit model binding, a Post model will be passed to the policy method. If the user is not authorized to perform the given action, a HTTP response with a 403 status code will be generated by the middleware.

Actions That Don't Require Models

Again, some actions like create may not require a model instance. In these situations, you may pass a class name to the middleware. The class name will be used to determine which policy to use when authorizing the action:

text
Route::post('/post', function () {
    // The current user may create posts...
})->middleware('can:create,App\Post');

Via Controller Helpers

In addition to helpful methods provided to the User model, Laravel provides a helpful authorize method to any of your controllers which extend the App\Http\Controllers\Controller base class. Like the can method, this method accepts the name of the action you wish to authorize and the relevant model. If the action is not authorized, the authorize method will throw an Illuminate\Auth\Access\AuthorizationException, which the default Laravel exception handler will convert to an HTTP response with a 403 status code:

text
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Update the given blog post.
     *
     * @param  Request  $request
     * @param  Post  $post
     * @return Response
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function update(Request $request, Post $post)
    {
        $this->authorize('update', $post);

        // The current user can update the blog post...
    }
}

Actions That Don't Require Models

As previously discussed, some actions like create may not require a model instance. In these situations, you should pass a class name to the authorize method. The class name will be used to determine which policy to use when authorizing the action:

text
/**
 * Create a new blog post.
 *
 * @param  Request  $request
 * @return Response
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
public function create(Request $request)
{
    $this->authorize('create', Post::class);

    // The current user can create blog posts...
}

Authorizing Resource Controllers

If you are utilizing resource controllers, you may make use of the authorizeResource method in the controller's constructor. This method will attach the appropriate can middleware definitions to the resource controller's methods.

The authorizeResource method accepts the model's class name as its first argument, and the name of the route / request parameter that will contain the model's ID as its second argument:

text
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function __construct()
    {
        $this->authorizeResource(Post::class, 'post');
    }
}

The following controller methods will be mapped to their corresponding policy method:

Controller Method Policy Method
index viewAny
show view
create create
store create
edit update
update update
destroy delete

{tip} You may use the make:policy command with the --model option to quickly generate a policy class for a given model: php artisan make:policy PostPolicy --model=Post.

Via Blade Templates

When writing Blade templates, you may wish to display a portion of the page only if the user is authorized to perform a given action. For example, you may wish to show an update form for a blog post only if the user can actually update the post. In this situation, you may use the @can and @cannot family of directives:

text
@can('update', $post)
    
@elsecan('create', App\Post::class)
    
@endcan

@cannot('update', $post)
    
@elsecannot('create', App\Post::class)
    
@endcannot

These directives are convenient shortcuts for writing @if and @unless statements. The @can and @cannot statements above respectively translate to the following statements:

text
@if (Auth::user()->can('update', $post))
    
@endif

@unless (Auth::user()->can('update', $post))
    
@endunless

You may also determine if a user has any authorization ability from a given list of abilities. To accomplish this, use the @canany directive:

text
@canany(['update', 'view', 'delete'], $post)
    // The current user can update, view, or delete the post
@elsecanany(['create'], \App\Post::class)
    // The current user can create a post
@endcanany

Actions That Don't Require Models

Like most of the other authorization methods, you may pass a class name to the @can and @cannot directives if the action does not require a model instance:

text
@can('create', App\Post::class)
    
@endcan

@cannot('create', App\Post::class)
    
@endcannot

Supplying Additional Context

When authorizing actions using policies, you may pass an array as the second argument to the various authorization functions and helpers. The first element in the array will be used to determine which policy should be invoked, while the rest of the array elements are passed as parameters to the policy method and can be used for additional context when making authorization decisions. For example, consider the following PostPolicy method definition which contains an additional $category parameter:

text
/**
 * Determine if the given post can be updated by the user.
 *
 * @param  \App\User  $user
 * @param  \App\Post  $post
 * @param  int  $category
 * @return bool
 */
public function update(User $user, Post $post, int $category)
{
    return $user->id === $post->user_id &&
           $category > 3;
}

When attempting to determine if the authenticated user can update a given post, we can invoke this policy method like so:

text
/**
 * Update the given blog post.
 *
 * @param  Request  $request
 * @param  Post  $post
 * @return Response
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
public function update(Request $request, Post $post)
{
    $this->authorize('update', [$post, $request->input('category')]);

    // The current user can update the blog post...
}

File: billing.md

Laravel Cashier

Introduction

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services. It handles almost all of the boilerplate subscription billing code you are dreading writing. In addition to basic subscription management, Cashier can handle coupons, swapping subscription, subscription "quantities", cancellation grace periods, and even generate invoice PDFs.

Upgrading Cashier

When upgrading to a new version of Cashier, it's important that you carefully review the upgrade guide.

{note} To prevent breaking changes, Cashier uses a fixed Stripe API version. Cashier 10.1 utilizes Stripe API version 2019-08-14. The Stripe API version will be updated on minor releases in order to make use of new Stripe features and improvements.

Installation

First, require the Cashier package for Stripe with Composer:

text
composer require laravel/cashier

{note} To ensure Cashier properly handles all Stripe events, remember to set up Cashier's webhook handling.

Database Migrations

The Cashier service provider registers its own database migration directory, so remember to migrate your database after installing the package. The Cashier migrations will add several columns to your users table as well as create a new subscriptions table to hold all of your customer's subscriptions:

text
php artisan migrate

If you need to overwrite the migrations that ship with the Cashier package, you can publish them using the vendor:publish Artisan command:

text
php artisan vendor:publish --tag="cashier-migrations"

If you would like to prevent Cashier's migrations from running entirely, you may use the ignoreMigrations provided by Cashier. Typically, this method should be called in the register method of your AppServiceProvider:

text
use Laravel\Cashier\Cashier;

Cashier::ignoreMigrations();

{note} Stripe recommends that any column used for storing Stripe identifiers should be case-sensitive. Therefore, you should ensure the column collation for the stripe_id column is set to, for example, utf8_bin in MySQL. More info can be found in the Stripe documentation.

Configuration

Billable Model

Before using Cashier, add the Billable trait to your model definition. This trait provides various methods to allow you to perform common billing tasks, such as creating subscriptions, applying coupons, and updating payment method information:

text
use Laravel\Cashier\Billable;

class User extends Authenticatable
{
    use Billable;
}

Cashier assumes your Billable model will be the App\User class that ships with Laravel. If you wish to change this you can specify a different model in your .env file:

text
CASHIER_MODEL=App\User

{note} If you're using a model other than Laravel's supplied App\User model, you'll need to publish and alter the migrations provided to match your alternative model's table name.

API Keys

Next, you should configure your Stripe key in your .env file. You can retrieve your Stripe API keys from the Stripe control panel.

text
STRIPE_KEY=your-stripe-key
STRIPE_SECRET=your-stripe-secret

Currency Configuration

The default Cashier currency is United States Dollars (USD). You can change the default currency by setting the CASHIER_CURRENCY environment variable:

text
CASHIER_CURRENCY=eur

In addition to configuring Cashier's currency, you may also specify a locale to be used when formatting money values for display on invoices. Internally, Cashier utilizes PHP's NumberFormatter class to set the currency locale:

text
CASHIER_CURRENCY_LOCALE=nl_BE

{note} In order to use locales other than en, ensure the ext-intl PHP extension is installed and configured on your server.

Logging

Cashier allows you to specify the log channel to be used when logging all Stripe related exceptions. You may specify the log channel using the CASHIER_LOGGER environment variable:

text
CASHIER_LOGGER=default

Customers

Creating Customers

Occasionally, you may wish to create a Stripe customer without beginning a subscription. You may accomplish this using the createAsStripeCustomer method:

text
$user->createAsStripeCustomer();

Once the customer has been created in Stripe, you may begin a subscription at a later date.

Payment Methods

Storing Payment Methods

In order to create subscriptions or perform "one off" charges with Stripe, you will need to store a payment method and retrieve its identifier from Stripe. The approach used to accomplish differs based on whether you plan to use the payment method for subscriptions or single charges, so we will examine both below.

Payment Methods For Subscriptions

When storing credit cards to a customer for future use, the Stripe Setup Intents API must be used to securely gather the customer's payment method details. A "Setup Intent" indicates to Stripe the intention to charge a customer's payment method. Cashier's Billable trait includes the createSetupIntent to easily create a new Setup Intent. You should call this method from the route or controller that will render the form which gathers your customer's payment method details:

text
return view('update-payment-method', [
    'intent' => $user->createSetupIntent()
]);

After you have created the Setup Intent and passed it to the view, you should attach its secret to the element that will gather the payment method. For example, consider this "update payment method" form:

text
client_secret }}">
    Update Payment Method

Next, the Stripe.js library may be used to attach a Stripe Element to the form and securely gather the customer's payment details:

text
<script src="https://js.stripe.com/v3/"></script>

<script>
    const stripe = Stripe('stripe-public-key');

    const elements = stripe.elements();
    const cardElement = elements.create('card');

    cardElement.mount('#card-element');
</script>

Next, the card can be verified and a secure "payment method identifier" can be retrieved from Stripe using Stripe's handleCardSetup method:

text
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;

cardButton.addEventListener('click', async (e) => {
    const { setupIntent, error } = await stripe.handleCardSetup(
        clientSecret, cardElement, {
            payment_method_data: {
                billing_details: { name: cardHolderName.value }
            }
        }
    );

    if (error) {
        // Display "error.message" to the user...
    } else {
        // The card has been verified successfully...
    }
});

After the card has been verified by Stripe, you may pass the resulting setupIntent.payment_method identifier to your Laravel application, where it can be attached to the customer. The payment method can either be added as a new payment method or used to update the default payment method. You can also immediately use the payment method identifier to create a new subscription.

{tip} If you would like more information about Setup Intents and gathering customer payment details please review this overview provided by Stripe.

Payment Methods For Single Charges

Of course, when making a single charge against a customer's payment method we'll only need to use a payment method identifier a single time. Due to Stripe limitations, you may not use the stored default payment method of a customer for single charges. You must allow the customer to enter their payment method details using the Stripe.js library. For example, consider the following form:

text
Process Payment

Next, the Stripe.js library may be used to attach a Stripe Element to the form and securely gather the customer's payment details:

text
<script src="https://js.stripe.com/v3/"></script>

<script>
    const stripe = Stripe('stripe-public-key');

    const elements = stripe.elements();
    const cardElement = elements.create('card');

    cardElement.mount('#card-element');
</script>

Next, the card can be verified and a secure "payment method identifier" can be retrieved from Stripe using Stripe's createPaymentMethod method:

text
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');

cardButton.addEventListener('click', async (e) => {
    const { paymentMethod, error } = await stripe.createPaymentMethod(
        'card', cardElement, {
            billing_details: { name: cardHolderName.value }
        }
    );

    if (error) {
        // Display "error.message" to the user...
    } else {
        // The card has been verified successfully...
    }
});

If the card is verified successfully, you may pass the paymentMethod.id to your Laravel application and process a single charge.

Retrieving Payment Methods

The paymentMethods method on the Billable model instance returns a collection of Laravel\Cashier\PaymentMethod instances:

text
$paymentMethods = $user->paymentMethods();

To retrieve the default payment method, the defaultPaymentMethod method may be used;

text
$paymentMethod = $user->defaultPaymentMethod();

Determining If A User Has A Payment Method

To determine if a Billable model has a payment method attached to their account, use the hasPaymentMethod method:

text
if ($user->hasPaymentMethod()) {
    //
}

Updating The Default Payment Method

The updateDefaultPaymentMethod method may be used to update a customer's default payment method information. This method accepts a Stripe payment method identifier and will assign the new payment method as the default billing payment method:

text
$user->updateDefaultPaymentMethod($paymentMethod);

To sync your default payment method information with the customer's default payment method information in Stripe, you may use the updateDefaultPaymentMethodFromStripe method:

text
$user->updateDefaultPaymentMethodFromStripe();

{note} The default payment method on a customer can only be used for invoicing and creating new subscriptions. Due to limitations from Stripe, it may not be used for single charges.

Adding Payment Methods

To add a new payment method, you may call the addPaymentMethod method on the billable user, passing the payment method identifier:

text
$user->addPaymentMethod($paymentMethod);

{tip} To learn how to retrieve payment method identifiers please review the payment method storage documentation.

Deleting Payment Methods

To delete a payment method, you may call the delete method on the Laravel\Cashier\PaymentMethod instance you wish to delete:

text
$paymentMethod->delete();

The deletePaymentMethods method will delete all of the payment method information for the Billable model:

text
$user->deletePaymentMethods();

{note} If a user has an active subscription, you should prevent them from deleting their default payment method.

Subscriptions

Creating Subscriptions

To create a subscription, first retrieve an instance of your billable model, which typically will be an instance of App\User. Once you have retrieved the model instance, you may use the newSubscription method to create the model's subscription:

text
$user = User::find(1);

$user->newSubscription('main', 'premium')->create($paymentMethod);

The first argument passed to the newSubscription method should be the name of the subscription. If your application only offers a single subscription, you might call this main or primary. The second argument is the specific plan the user is subscribing to. This value should correspond to the plan's identifier in Stripe.

The create method, which accepts a Stripe payment method identifier or Stripe PaymentMethod object, will begin the subscription as well as update your database with the customer ID and other relevant billing information.

{note} Passing a payment method identifier directly to the create() subscription method will also automatically add it to the user's stored payment methods.

Additional User Details

If you would like to specify additional customer details, you may do so by passing them as the second argument to the create method:

text
$user->newSubscription('main', 'monthly')->create($paymentMethod, [
    'email' => $email,
]);

To learn more about the additional fields supported by Stripe, check out Stripe's documentation on customer creation.

Coupons

If you would like to apply a coupon when creating the subscription, you may use the withCoupon method:

text
$user->newSubscription('main', 'monthly')
     ->withCoupon('code')
     ->create($paymentMethod);

Checking Subscription Status

Once a user is subscribed to your application, you may easily check their subscription status using a variety of convenient methods. First, the subscribed method returns true if the user has an active subscription, even if the subscription is currently within its trial period:

text
if ($user->subscribed('main')) {
    //
}

The subscribed method also makes a great candidate for a route middleware, allowing you to filter access to routes and controllers based on the user's subscription status:

text
public function handle($request, Closure $next)
{
    if ($request->user() && ! $request->user()->subscribed('main')) {
        // This user is not a paying customer...
        return redirect('billing');
    }

    return $next($request);
}

If you would like to determine if a user is still within their trial period, you may use the onTrial method. This method can be useful for displaying a warning to the user that they are still on their trial period:

text
if ($user->subscription('main')->onTrial()) {
    //
}

The subscribedToPlan method may be used to determine if the user is subscribed to a given plan based on a given Stripe plan ID. In this example, we will determine if the user's main subscription is actively subscribed to the monthly plan:

text
if ($user->subscribedToPlan('monthly', 'main')) {
    //
}

By passing an array to the subscribedToPlan method, you may determine if the user's main subscription is actively subscribed to the monthly or the yearly plan:

text
if ($user->subscribedToPlan(['monthly', 'yearly'], 'main')) {
    //
}

The recurring method may be used to determine if the user is currently subscribed and is no longer within their trial period:

text
if ($user->subscription('main')->recurring()) {
    //
}

Cancelled Subscription Status

To determine if the user was once an active subscriber, but has cancelled their subscription, you may use the cancelled method:

text
if ($user->subscription('main')->cancelled()) {
    //
}

You may also determine if a user has cancelled their subscription, but are still on their "grace period" until the subscription fully expires. For example, if a user cancels a subscription on March 5th that was originally scheduled to expire on March 10th, the user is on their "grace period" until March 10th. Note that the subscribed method still returns true during this time:

text
if ($user->subscription('main')->onGracePeriod()) {
    //
}

To determine if the user has cancelled their subscription and is no longer within their "grace period", you may use the ended method:

text
if ($user->subscription('main')->ended()) {
    //
}

Incomplete and Past Due Status

If a subscription requires a secondary payment action after creation the subscription will be marked as incomplete. Subscription statuses are stored in the stripe_status column of Cashier's subscriptions database table.

Similarly, if a secondary payment action is required when swapping plans the subscription will be marked as past_due. When your subscription is in either of these states it will not be active until the customer has confirmed their payment. Checking if a subscription has an incomplete payment can be done using the hasIncompletePayment method on the Billable model or a subscription instance:

text
if ($user->hasIncompletePayment('main')) {
    //
}

if ($user->subscription('main')->hasIncompletePayment()) {
    //
}

When a subscription has an incomplete payment, you should direct the user to Cashier's payment confirmation page, passing the latestPayment identifier. You may use the latestPayment method available on subscription instance to retrieve this identifier:

text
<a href="{{ route('cashier.payment', $subscription->latestPayment()->id) }}">
    Please confirm your payment.
</a>

{note} When a subscription is in an incomplete state it cannot be changed until the payment is confirmed. Therefore, the swap and updateQuantity methods will throw an exception when the subscription is in an incomplete state.

Changing Plans

After a user is subscribed to your application, they may occasionally want to change to a new subscription plan. To swap a user to a new subscription, pass the plan's identifier to the swap method:

text
$user = App\User::find(1);

$user->subscription('main')->swap('provider-plan-id');

If the user is on trial, the trial period will be maintained. Also, if a "quantity" exists for the subscription, that quantity will also be maintained.

If you would like to swap plans and cancel any trial period the user is currently on, you may use the skipTrial method:

text
$user->subscription('main')
        ->skipTrial()
        ->swap('provider-plan-id');

If you would like to swap plans and immediately invoice the user instead of waiting for their next billing cycle, you may use the swapAndInvoice method:

text
$user = App\User::find(1);

$user->subscription('main')->swapAndInvoice('provider-plan-id');

Subscription Quantity

Sometimes subscriptions are affected by "quantity". For example, your application might charge $10 per month per user on an account. To easily increment or decrement your subscription quantity, use the incrementQuantity and decrementQuantity methods:

text
$user = User::find(1);

$user->subscription('main')->incrementQuantity();

// Add five to the subscription's current quantity...
$user->subscription('main')->incrementQuantity(5);

$user->subscription('main')->decrementQuantity();

// Subtract five to the subscription's current quantity...
$user->subscription('main')->decrementQuantity(5);

Alternatively, you may set a specific quantity using the updateQuantity method:

text
$user->subscription('main')->updateQuantity(10);

The noProrate method may be used to update the subscription's quantity without pro-rating the charges:

text
$user->subscription('main')->noProrate()->updateQuantity(10);

For more information on subscription quantities, consult the Stripe documentation.

Subscription Taxes

To specify the tax percentage a user pays on a subscription, implement the taxPercentage method on your billable model, and return a numeric value between 0 and 100, with no more than 2 decimal places.

text
public function taxPercentage()
{
    return 20;
}

The taxPercentage method enables you to apply a tax rate on a model-by-model basis, which may be helpful for a user base that spans multiple countries and tax rates.

{note} The taxPercentage method only applies to subscription charges. If you use Cashier to make "one off" charges, you will need to manually specify the tax rate at that time.

Syncing Tax Percentages

When changing the hard-coded value returned by the taxPercentage method, the tax settings on any existing subscriptions for the user will remain the same. If you wish to update the tax value for existing subscriptions with the returned taxPercentage value, you should call the syncTaxPercentage method on the user's subscription instance:

text
$user->subscription('main')->syncTaxPercentage();

Subscription Anchor Date

By default, the billing cycle anchor is the date the subscription was created, or if a trial period is used, the date that the trial ends. If you would like to modify the billing anchor date, you may use the anchorBillingCycleOn method:

text
use App\User;
use Carbon\Carbon;

$user = User::find(1);

$anchor = Carbon::parse('first day of next month');

$user->newSubscription('main', 'premium')
            ->anchorBillingCycleOn($anchor->startOfDay())
            ->create($paymentMethod);

For more information on managing subscription billing cycles, consult the Stripe billing cycle documentation

Cancelling Subscriptions

To cancel a subscription, call the cancel method on the user's subscription:

text
$user->subscription('main')->cancel();

When a subscription is cancelled, Cashier will automatically set the ends_at column in your database. This column is used to know when the subscribed method should begin returning false. For example, if a customer cancels a subscription on March 1st, but the subscription was not scheduled to end until March 5th, the subscribed method will continue to return true until March 5th.

You may determine if a user has cancelled their subscription but are still on their "grace period" using the onGracePeriod method:

text
if ($user->subscription('main')->onGracePeriod()) {
    //
}

If you wish to cancel a subscription immediately, call the cancelNow method on the user's subscription:

text
$user->subscription('main')->cancelNow();

Resuming Subscriptions

If a user has cancelled their subscription and you wish to resume it, use the resume method. The user must still be on their grace period in order to resume a subscription:

text
$user->subscription('main')->resume();

If the user cancels a subscription and then resumes that subscription before the subscription has fully expired, they will not be billed immediately. Instead, their subscription will be re-activated, and they will be billed on the original billing cycle.

Subscription Trials

With Payment Method Up Front

If you would like to offer trial periods to your customers while still collecting payment method information up front, you should use the trialDays method when creating your subscriptions:

text
$user = User::find(1);

$user->newSubscription('main', 'monthly')
            ->trialDays(10)
            ->create($paymentMethod);

This method will set the trial period ending date on the subscription record within the database, as well as instruct Stripe to not begin billing the customer until after this date. When using the trialDays method, Cashier will overwrite any default trial period configured for the plan in Stripe.

{note} If the customer's subscription is not cancelled before the trial ending date they will be charged as soon as the trial expires, so you should be sure to notify your users of their trial ending date.

The trialUntil method allows you to provide a DateTime instance to specify when the trial period should end:

text
use Carbon\Carbon;

$user->newSubscription('main', 'monthly')
            ->trialUntil(Carbon::now()->addDays(10))
            ->create($paymentMethod);

You may determine if the user is within their trial period using either the onTrial method of the user instance, or the onTrial method of the subscription instance. The two examples below are identical:

text
if ($user->onTrial('main')) {
    //
}

if ($user->subscription('main')->onTrial()) {
    //
}

Without Payment Method Up Front

If you would like to offer trial periods without collecting the user's payment method information up front, you may set the trial_ends_at column on the user record to your desired trial ending date. This is typically done during user registration:

text
$user = User::create([
    // Populate other user properties...
    'trial_ends_at' => now()->addDays(10),
]);

{note} Be sure to add a date mutator for trial_ends_at to your model definition.

Cashier refers to this type of trial as a "generic trial", since it is not attached to any existing subscription. The onTrial method on the User instance will return true if the current date is not past the value of trial_ends_at:

text
if ($user->onTrial()) {
    // User is within their trial period...
}

You may also use the onGenericTrial method if you wish to know specifically that the user is within their "generic" trial period and has not created an actual subscription yet:

text
if ($user->onGenericTrial()) {
    // User is within their "generic" trial period...
}

Once you are ready to create an actual subscription for the user, you may use the newSubscription method as usual:

text
$user = User::find(1);

$user->newSubscription('main', 'monthly')->create($paymentMethod);

Handling Stripe Webhooks

{tip} You may use Laravel Valet's valet share command to help test webhooks during local development.

Stripe can notify your application of a variety of events via webhooks. By default, a route that points to Cashier's webhook controller is configured through the Cashier service provider. This controller will handle all incoming webhook requests.

By default, this controller will automatically handle cancelling subscriptions that have too many failed charges (as defined by your Stripe settings), customer updates, customer deletions, subscription updates, and payment method changes; however, as we'll soon discover, you can extend this controller to handle any webhook event you like.

To ensure your application can handle Stripe webhooks, be sure to configure the webhook URL in the Stripe control panel. The full list of all webhooks you should configure in the Stripe control panel are:

  • customer.subscription.updated
  • customer.subscription.deleted
  • customer.updated
  • customer.deleted
  • invoice.payment_action_required

{note} Make sure you protect incoming requests with Cashier's included webhook signature verification middleware.

Webhooks & CSRF Protection

Since Stripe webhooks need to bypass Laravel's CSRF protection, be sure to list the URI as an exception in your VerifyCsrfToken middleware or list the route outside of the web middleware group:

text
protected $except = [
    'stripe/*',
];

Defining Webhook Event Handlers

Cashier automatically handles subscription cancellation on failed charges, but if you have additional webhook events you would like to handle, extend the Webhook controller. Your method names should correspond to Cashier's expected convention, specifically, methods should be prefixed with handle and the "camel case" name of the webhook you wish to handle. For example, if you wish to handle the invoice.payment_succeeded webhook, you should add a handleInvoicePaymentSucceeded method to the controller:

text
<?php

namespace App\Http\Controllers;

use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;

class WebhookController extends CashierController
{
    /**
     * Handle invoice payment succeeded.
     *
     * @param  array  $payload
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function handleInvoicePaymentSucceeded($payload)
    {
        // Handle The Event
    }
}

Next, define a route to your Cashier controller within your routes/web.php file. This will overwrite the default shipped route:

text
Route::post(
    'stripe/webhook',
    '\App\Http\Controllers\WebhookController@handleWebhook'
);

Failed Subscriptions

What if a customer's credit card expires? No worries - Cashier's Webhook controller will cancel the customer's subscription for you. Failed payments will automatically be captured and handled by the controller. The controller will cancel the customer's subscription when Stripe determines the subscription has failed (normally after three failed payment attempts).

Verifying Webhook Signatures

To secure your webhooks, you may use Stripe's webhook signatures. For convenience, Cashier automatically includes a middleware which validates that the incoming Stripe webhook request is valid.

To enable webhook verification, ensure that the STRIPE_WEBHOOK_SECRET environment variable is set in your .env file. The webhook secret may be retrieved from your Stripe account dashboard.

Single Charges

Simple Charge

{note} The charge method accepts the amount you would like to charge in the lowest denominator of the currency used by your application.

If you would like to make a "one off" charge against a subscribed customer's payment method, you may use the charge method on a billable model instance. You'll need to provide a payment method identifier as the second argument:

text
// Stripe Accepts Charges In Cents...
$stripeCharge = $user->charge(100, $paymentMethod);

The charge method accepts an array as its third argument, allowing you to pass any options you wish to the underlying Stripe charge creation. Consult the Stripe documentation regarding the options available to you when creating charges:

text
$user->charge(100, $paymentMethod, [
    'custom_option' => $value,
]);

The charge method will throw an exception if the charge fails. If the charge is successful, an instance of Laravel\Cashier\Payment will be returned from the method:

text
try {
    $payment = $user->charge(100, $paymentMethod);
} catch (Exception $e) {
    //
}

Charge With Invoice

Sometimes you may need to make a one-time charge but also generate an invoice for the charge so that you may offer a PDF receipt to your customer. The invoiceFor method lets you do just that. For example, let's invoice the customer $5.00 for a "One Time Fee":

text
// Stripe Accepts Charges In Cents...
$user->invoiceFor('One Time Fee', 500);

The invoice will be charged immediately against the user's default payment method. The invoiceFor method also accepts an array as its third argument. This array contains the billing options for the invoice item. The fourth argument accepted by the method is also an array. This final argument accepts the billing options for the invoice itself:

text
$user->invoiceFor('Stickers', 500, [
    'quantity' => 50,
], [
    'tax_percent' => 21,
]);

{note} The invoiceFor method will create a Stripe invoice which will retry failed billing attempts. If you do not want invoices to retry failed charges, you will need to close them using the Stripe API after the first failed charge.

Refunding Charges

If you need to refund a Stripe charge, you may use the refund method. This method accepts the Stripe Payment Intent ID as its first argument:

text
$payment = $user->charge(100, $paymentMethod);

$user->refund($payment->id);

Invoices

You may easily retrieve an array of a billable model's invoices using the invoices method:

text
$invoices = $user->invoices();

// Include pending invoices in the results...
$invoices = $user->invoicesIncludingPending();

When listing the invoices for the customer, you may use the invoice's helper methods to display the relevant invoice information. For example, you may wish to list every invoice in a table, allowing the user to easily download any of them:

{{ $invoice->date()->toFormattedDateString() }} {{ $invoice->total() }} [Download](/user/invoice/{{ $invoice->id }})

Generating Invoice PDFs

From within a route or controller, use the downloadInvoice method to generate a PDF download of the invoice. This method will automatically generate the proper HTTP response to send the download to the browser:

text
use Illuminate\Http\Request;

Route::get('user/invoice/{invoice}', function (Request $request, $invoiceId) {
    return $request->user()->downloadInvoice($invoiceId, [
        'vendor' => 'Your Company',
        'product' => 'Your Product',
    ]);
});

Strong Customer Authentication

If your business is based in Europe you will need to abide by the Strong Customer Authentication (SCA) regulations. These regulations were imposedย in September 2019 by the European Union to prevent payment fraud. Luckily, Stripe and Cashier are prepared for building SCA compliant applications.

{note} Before getting started, review Stripe's guide on PSD2 and SCA as well as their documentation on the new SCA API's.

Payments Requiring Additional Confirmation

SCA regulations often require extra verification in order to confirm and process a payment. When this happens, Cashier will throw an IncompletePayment exception that informs you that this extra verification is needed. After catching this exception, you have two options on how to proceed.

First, you could redirect your customer to the dedicated payment confirmation page which is included with Cashier. This page already has an associated route that is registered via Cashier's service provider. So, you may catch the IncompletePayment exception and redirect to the payment confirmation page:

text
use Laravel\Cashier\Exceptions\IncompletePayment;

try {
    $subscription = $user->newSubscription('default', $planId)
                            ->create($paymentMethod);
} catch (IncompletePayment $exception) {
    return redirect()->route(
        'cashier.payment',
        [$exception->payment->id, 'redirect' => route('home')]
    );
}

On the payment confirmation page, the customer will be prompted to enter their credit card info again and perform any additional actions required by Stripe, such as "3D Secure" confirmation. After confirming their payment, the user will be redirected to the URL provided by the redirect parameter specified above.

Alternatively, you could allow Stripe to handle the payment confirmation for you. In this case, instead of redirecting to the payment confirmation page, you may setup Stripe's automatic billing emails in your Stripe dashboard. However, if an IncompletePayment exception is caught, you should still inform the user they will receive an email with further payment confirmation instructions.

Incomplete payment exceptions may be thrown for the following methods: charge, invoiceFor, and invoice on the Billable user. When handling subscriptions, the create method on the SubscriptionBuilder, and the incrementAndInvoice and swapAndInvoice methods on the Subscription model may throw exceptions.

Incomplete and Past Due State

When a payment needs additional confirmation, the subscription will remain in an incomplete or past_due state as indicated by its stripe_status database column. Cashier will make automatically activate the customer's subscription via a webhook as soon as payment confirmation is complete.

For more information on incomplete and past_due states, please refer to our additional documentation.

Off-Session Payment Notifications

Since SCA regulations require customers to occasionally verify their payment details even while their subscription is active, Cashier can send a payment notification to the customer when off-session payment confirmation is required. For example, this may occur when a subscription is renewing. Cashier's payment notification can be enabled by setting the CASHIER_PAYMENT_NOTIFICATION environment variable to a notification class. By default, this notification is disabled. Of course, Cashier includes a notification class you may use for this purpose, but you are free to provide your own notification class if desired:

text
CASHIER_PAYMENT_NOTIFICATION=Laravel\Cashier\Notifications\ConfirmPayment

To ensure that off-session payment confirmation notifications are delivered, verify that Stripe webhooks are configured for your application and the invoice.payment_action_required webhook is enabled in your Stripe dashboard. In addition, your Billable model should also use Laravel's Illuminate\Notifications\Notifiable trait.

{note} Notifications will be sent even when customers are manually making a payment that requires additional confirmation. Unfortunately, there is no way for Stripe to know that the payment was done manually or "off-session". But, a customer will simply see a "Payment Successful" message if they visit the payment page after already confirming their payment. The customer will not be allowed to accidentally confirm the same payment twice and incur an accidental second charge.


File: blade.md

Blade Templates

Introduction

Blade is the simple, yet powerful templating engine provided with Laravel. Unlike other popular PHP templating engines, Blade does not restrict you from using plain PHP code in your views. In fact, all Blade views are compiled into plain PHP code and cached until they are modified, meaning Blade adds essentially zero overhead to your application. Blade view files use the .blade.php file extension and are typically stored in the resources/views directory.

Template Inheritance

Defining A Layout

Two of the primary benefits of using Blade are template inheritance and sections. To get started, let's take a look at a simple example. First, we will examine a "master" page layout. Since most web applications maintain the same general layout across various pages, it's convenient to define this layout as a single Blade view:

text
<html>
    <head>
        <title>App Name - @yield('title')</title>
    </head>
    
        @section('sidebar')
            This is the master sidebar.
        @show

        
            @yield('content')
        
    
</html>

As you can see, this file contains typical HTML mark-up. However, take note of the @section and @yield directives. The @section directive, as the name implies, defines a section of content, while the @yield directive is used to display the contents of a given section.

Now that we have defined a layout for our application, let's define a child page that inherits the layout.

Extending A Layout

When defining a child view, use the Blade @extends directive to specify which layout the child view should "inherit". Views which extend a Blade layout may inject content into the layout's sections using @section directives. Remember, as seen in the example above, the contents of these sections will be displayed in the layout using @yield:

text
@extends('layouts.app')

@section('title', 'Page Title')

@section('sidebar')
    @@parent

    This is appended to the master sidebar.
@endsection

@section('content')
    This is my body content.
@endsection

In this example, the sidebar section is utilizing the @@parent directive to append (rather than overwriting) content to the layout's sidebar. The @@parent directive will be replaced by the content of the layout when the view is rendered.

{tip} Contrary to the previous example, this sidebar section ends with @endsection instead of @show. The @endsection directive will only define a section while @show will define and immediately yield the section.

The @yield directive also accepts a default value as its second parameter. This value will be rendered if the section being yielded is undefined:

text
@yield('content', View::make('view.name'))

Blade views may be returned from routes using the global view helper:

text
Route::get('blade', function () {
    return view('child');
});

Components & Slots

Components and slots provide similar benefits to sections and layouts; however, some may find the mental model of components and slots easier to understand. First, let's imagine a reusable "alert" component we would like to reuse throughout our application:

text
{{ $slot }}

The {{ $slot }} variable will contain the content we wish to inject into the component. Now, to construct this component, we can use the @component Blade directive:

text
@component('alert')
    **Whoops!** Something went wrong!
@endcomponent

To instruct Laravel to load the first view that exists from a given array of possible views for the component, you may use the componentFirst directive:

text
@componentFirst(['custom.alert', 'alert'])
    **Whoops!** Something went wrong!
@endcomponent

Sometimes it is helpful to define multiple slots for a component. Let's modify our alert component to allow for the injection of a "title". Named slots may be displayed by "echoing" the variable that matches their name:

text
{{ $title }}

    {{ $slot }}

Now, we can inject content into the named slot using the @slot directive. Any content not within a @slot directive will be passed to the component in the $slot variable:

text
@component('alert')
    @slot('title')
        Forbidden
    @endslot

    You are not allowed to access this resource!
@endcomponent

Passing Additional Data To Components

Sometimes you may need to pass additional data to a component. For this reason, you can pass an array of data as the second argument to the @component directive. All of the data will be made available to the component template as variables:

text
@component('alert', ['foo' => 'bar'])
    ...
@endcomponent

Aliasing Components

If your Blade components are stored in a sub-directory, you may wish to alias them for easier access. For example, imagine a Blade component that is stored at resources/views/components/alert.blade.php. You may use the component method to alias the component from components.alert to alert. Typically, this should be done in the boot method of your AppServiceProvider:

text
use Illuminate\Support\Facades\Blade;

Blade::component('components.alert', 'alert');

Once the component has been aliased, you may render it using a directive:

text
@alert(['type' => 'danger'])
    You are not allowed to access this resource!
@endalert

You may omit the component parameters if it has no additional slots:

text
@alert
    You are not allowed to access this resource!
@endalert

Displaying Data

You may display data passed to your Blade views by wrapping the variable in curly braces. For example, given the following route:

text
Route::get('greeting', function () {
    return view('welcome', ['name' => 'Samantha']);
});

You may display the contents of the name variable like so:

text
Hello, {{ $name }}.

{tip} Blade {{ }} statements are automatically sent through PHP's htmlspecialchars function to prevent XSS attacks.

You are not limited to displaying the contents of the variables passed to the view. You may also echo the results of any PHP function. In fact, you can put any PHP code you wish inside of a Blade echo statement:

text
The current UNIX timestamp is {{ time() }}.

Displaying Unescaped Data

By default, Blade {{ }} statements are automatically sent through PHP's htmlspecialchars function to prevent XSS attacks. If you do not want your data to be escaped, you may use the following syntax:

text
Hello, {!! $name !!}.

{note} Be very careful when echoing content that is supplied by users of your application. Always use the escaped, double curly brace syntax to prevent XSS attacks when displaying user supplied data.

Rendering JSON

Sometimes you may pass an array to your view with the intention of rendering it as JSON in order to initialize a JavaScript variable. For example:

text
<script>
    var app = <?php echo json_encode($array); ?>;
</script>

However, instead of manually calling json_encode, you may use the @json Blade directive. The @json directive accepts the same arguments as PHP's json_encode function:

text
<script>
    var app = @json($array);

    var app = @json($array, JSON_PRETTY_PRINT);
</script>

{note} You should only use the @json directive to render existing variables as JSON. The Blade templating is based on regular expressions and attempts to pass a complex expression to the directive may cause unexpected failures.

The @json directive is also useful for seeding Vue components or data-* attributes:

text
<example-component :some-prop='@json($array)'></example-component>

{note} Using @json in element attributes requires that it be surrounded by single quotes.

HTML Entity Encoding

By default, Blade (and the Laravel e helper) will double encode HTML entities. If you would like to disable double encoding, call the Blade::withoutDoubleEncoding method from the boot method of your AppServiceProvider:

text
<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::withoutDoubleEncoding();
    }
}

Blade & JavaScript Frameworks

Since many JavaScript frameworks also use "curly" braces to indicate a given expression should be displayed in the browser, you may use the @ symbol to inform the Blade rendering engine an expression should remain untouched. For example:

text
<h1>Laravel</h1>

Hello, @{{ name }}.

In this example, the @ symbol will be removed by Blade; however, {{ name }} expression will remain untouched by the Blade engine, allowing it to instead be rendered by your JavaScript framework.

The `@verbatim` Directive

If you are displaying JavaScript variables in a large portion of your template, you may wrap the HTML in the @verbatim directive so that you do not have to prefix each Blade echo statement with an @ symbol:

text
@verbatim
    
        Hello, {{ name }}.
    
@endverbatim

Control Structures

In addition to template inheritance and displaying data, Blade also provides convenient shortcuts for common PHP control structures, such as conditional statements and loops. These shortcuts provide a very clean, terse way of working with PHP control structures, while also remaining familiar to their PHP counterparts.

If Statements

You may construct if statements using the @if, @elseif, @else, and @endif directives. These directives function identically to their PHP counterparts:

text
@if (count($records) === 1)
    I have one record!
@elseif (count($records) > 1)
    I have multiple records!
@else
    I don't have any records!
@endif

For convenience, Blade also provides an @unless directive:

text
@unless (Auth::check())
    You are not signed in.
@endunless

In addition to the conditional directives already discussed, the @isset and @empty directives may be used as convenient shortcuts for their respective PHP functions:

text
@isset($records)
    // $records is defined and is not null...
@endisset

@empty($records)
    // $records is "empty"...
@endempty

Authentication Directives

The @auth and @guest directives may be used to quickly determine if the current user is authenticated or is a guest:

text
@auth
    // The user is authenticated...
@endauth

@guest
    // The user is not authenticated...
@endguest

If needed, you may specify the authentication guard that should be checked when using the @auth and @guest directives:

text
@auth('admin')
    // The user is authenticated...
@endauth

@guest('admin')
    // The user is not authenticated...
@endguest

Section Directives

You may check if a section has content using the @hasSection directive:

text
@hasSection('navigation')
    
        @yield('navigation')
    

    
@endif

Switch Statements

Switch statements can be constructed using the @switch, @case, @break, @default and @endswitch directives:

text
@switch($i)
    @case(1)
        First case...
        @break

    @case(2)
        Second case...
        @break

    @default
        Default case...
@endswitch

Loops

In addition to conditional statements, Blade provides simple directives for working with PHP's loop structures. Again, each of these directives functions identically to their PHP counterparts:

text
@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor

@foreach ($users as $user)
    This is user {{ $user->id }}
@endforeach

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    No users
@endforelse

@while (true)
    I'm looping forever.
@endwhile

{tip} When looping, you may use the loop variable to gain valuable information about the loop, such as whether you are in the first or last iteration through the loop.

When using loops you may also end the loop or skip the current iteration:

text
@foreach ($users as $user)
    @if ($user->type == 1)
        @continue
    @endif

    <li>{{ $user->name }}</li>

    @if ($user->number == 5)
        @break
    @endif
@endforeach

You may also include the condition with the directive declaration in one line:

text
@foreach ($users as $user)
    @continue($user->type == 1)

    <li>{{ $user->name }}</li>

    @break($user->number == 5)
@endforeach

The Loop Variable

When looping, a $loop variable will be available inside of your loop. This variable provides access to some useful bits of information such as the current loop index and whether this is the first or last iteration through the loop:

text
@foreach ($users as $user)
    @if ($loop->first)
        This is the first iteration.
    @endif

    @if ($loop->last)
        This is the last iteration.
    @endif

    This is user {{ $user->id }}
@endforeach

If you are in a nested loop, you may access the parent loop's $loop variable via the parent property:

text
@foreach ($users as $user)
    @foreach ($user->posts as $post)
        @if ($loop->parent->first)
            This is first iteration of the parent loop.
        @endif
    @endforeach
@endforeach

The $loop variable also contains a variety of other useful properties:

Property Description
$loop->index The index of the current loop iteration (starts at 0).
$loop->iteration The current loop iteration (starts at 1).
$loop->remaining The iterations remaining in the loop.
$loop->count The total number of items in the array being iterated.
$loop->first Whether this is the first iteration through the loop.
$loop->last Whether this is the last iteration through the loop.
$loop->even Whether this is an even iteration through the loop.
$loop->odd Whether this is an odd iteration through the loop.
$loop->depth The nesting level of the current loop.
$loop->parent When in a nested loop, the parent's loop variable.

Comments

Blade also allows you to define comments in your views. However, unlike HTML comments, Blade comments are not included in the HTML returned by your application:

text
{{-- This comment will not be present in the rendered HTML --}}

PHP

In some situations, it's useful to embed PHP code into your views. You can use the Blade @php directive to execute a block of plain PHP within your template:

text
@php
    //
@endphp

{tip} While Blade provides this feature, using it frequently may be a signal that you have too much logic embedded within your template.

Forms

CSRF Field

Anytime you define an HTML form in your application, you should include a hidden CSRF token field in the form so that the CSRF protection middleware can validate the request. You may use the @csrf Blade directive to generate the token field:

text
<form method="POST" action="/profile">
    @csrf

    ...
</form>

Method Field

Since HTML forms can't make PUT, PATCH, or DELETE requests, you will need to add a hidden _method field to spoof these HTTP verbs. The @method Blade directive can create this field for you:

text
<form action="/foo/bar" method="POST">
    @method('PUT')

    ...
</form>

Validation Errors

The @error directive may be used to quickly check if validation error messages exist for a given attribute. Within an @error directive, you may echo the $message variable to display the error message:

text
<label for="title">Post Title</label>



@error('title')
    {{ $message }}
@enderror

You may pass the name of a specific error bag as the second parameter to the @error directive to retrieve validation error messages on pages containing multiple forms:

text
<label for="email">Email address</label>



@error('email', 'login')
    {{ $message }}
@enderror

Including Sub-Views

Blade's @include directive allows you to include a Blade view from within another view. All variables that are available to the parent view will be made available to the included view:

text
@include('shared.errors')

    <form>
        
    </form>

Even though the included view will inherit all data available in the parent view, you may also pass an array of extra data to the included view:

text
@include('view.name', ['some' => 'data'])

If you attempt to @include a view which does not exist, Laravel will throw an error. If you would like to include a view that may or may not be present, you should use the @includeIf directive:

text
@includeIf('view.name', ['some' => 'data'])

If you would like to @include a view depending on a given boolean condition, you may use the @includeWhen directive:

text
@includeWhen($boolean, 'view.name', ['some' => 'data'])

To include the first view that exists from a given array of views, you may use the includeFirst directive:

text
@includeFirst(['custom.admin', 'admin'], ['some' => 'data'])

{note} You should avoid using the __DIR__ and __FILE__ constants in your Blade views, since they will refer to the location of the cached, compiled view.

Aliasing Includes

If your Blade includes are stored in a sub-directory, you may wish to alias them for easier access. For example, imagine a Blade include that is stored at resources/views/includes/input.blade.php with the following content:

You may use the include method to alias the include from includes.input to input. Typically, this should be done in the boot method of your AppServiceProvider:

text
use Illuminate\Support\Facades\Blade;

Blade::include('includes.input', 'input');

Once the include has been aliased, you may render it using the alias name as the Blade directive:

text
@input(['type' => 'email'])

Rendering Views For Collections

You may combine loops and includes into one line with Blade's @each directive:

text
@each('view.name', $jobs, 'job')

The first argument is the view partial to render for each element in the array or collection. The second argument is the array or collection you wish to iterate over, while the third argument is the variable name that will be assigned to the current iteration within the view. So, for example, if you are iterating over an array of jobs, typically you will want to access each job as a job variable within your view partial. The key for the current iteration will be available as the key variable within your view partial.

You may also pass a fourth argument to the @each directive. This argument determines the view that will be rendered if the given array is empty.

text
@each('view.name', $jobs, 'job', 'view.empty')

{note} Views rendered via @each do not inherit the variables from the parent view. If the child view requires these variables, you should use @foreach and @include instead.

Stacks

Blade allows you to push to named stacks which can be rendered somewhere else in another view or layout. This can be particularly useful for specifying any JavaScript libraries required by your child views:

text
@push('scripts')
    <script src="/example.js"></script>
@endpush

You may push to a stack as many times as needed. To render the complete stack contents, pass the name of the stack to the @stack directive:

text
<head>
    

    @stack('scripts')
</head>

If you would like to prepend content onto the beginning of a stack, you should use the @prepend directive:

text
@push('scripts')
    This will be second...
@endpush

// Later...

@prepend('scripts')
    This will be first...
@endprepend

Service Injection

The @inject directive may be used to retrieve a service from the Laravel service container. The first argument passed to @inject is the name of the variable the service will be placed into, while the second argument is the class or interface name of the service you wish to resolve:

text
@inject('metrics', 'App\Services\MetricsService')


    Monthly Revenue: {{ $metrics->monthlyRevenue() }}.

Extending Blade

Blade allows you to define your own custom directives using the directive method. When the Blade compiler encounters the custom directive, it will call the provided callback with the expression that the directive contains.

The following example creates a @datetime($var) directive which formats a given $var, which should be an instance of DateTime:

text
<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('datetime', function ($expression) {
            return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
        });
    }
}

As you can see, we will chain the format method onto whatever expression is passed into the directive. So, in this example, the final PHP generated by this directive will be:

text
<?php echo ($var)->format('m/d/Y H:i'); ?>

{note} After updating the logic of a Blade directive, you will need to delete all of the cached Blade views. The cached Blade views may be removed using the view:clear Artisan command.

Custom If Statements

Programming a custom directive is sometimes more complex than necessary when defining simple, custom conditional statements. For that reason, Blade provides a Blade::if method which allows you to quickly define custom conditional directives using Closures. For example, let's define a custom conditional that checks the current application environment. We may do this in the boot method of our AppServiceProvider:

text
use Illuminate\Support\Facades\Blade;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Blade::if('env', function ($environment) {
        return app()->environment($environment);
    });
}

Once the custom conditional has been defined, we can easily use it on our templates:

text
@env('local')
    // The application is in the local environment...
@elseenv('testing')
    // The application is in the testing environment...
@else
    // The application is not in the local or testing environment...
@endenv

File: broadcasting.md

Broadcasting

Introduction

In many modern web applications, WebSockets are used to implement realtime, live-updating user interfaces. When some data is updated on the server, a message is typically sent over a WebSocket connection to be handled by the client. This provides a more robust, efficient alternative to continually polling your application for changes.

To assist you in building these types of applications, Laravel makes it easy to "broadcast" your events over a WebSocket connection. Broadcasting your Laravel events allows you to share the same event names between your server-side code and your client-side JavaScript application.

{tip} Before diving into event broadcasting, make sure you have read all of the documentation regarding Laravel events and listeners.

Configuration

All of your application's event broadcasting configuration is stored in the config/broadcasting.php configuration file. Laravel supports several broadcast drivers out of the box: Pusher Channels, Redis, and a log driver for local development and debugging. Additionally, a null driver is included which allows you to totally disable broadcasting. A configuration example is included for each of these drivers in the config/broadcasting.php configuration file.

Broadcast Service Provider

Before broadcasting any events, you will first need to register the App\Providers\BroadcastServiceProvider. In fresh Laravel applications, you only need to uncomment this provider in the providers array of your config/app.php configuration file. This provider will allow you to register the broadcast authorization routes and callbacks.

CSRF Token

Laravel Echo will need access to the current session's CSRF token. You should verify that your application's head HTML element defines a meta tag containing the CSRF token:

text
<meta name="csrf-token" content="{{ csrf_token() }}">

Driver Prerequisites

Pusher Channels

If you are broadcasting your events over Pusher Channels, you should install the Pusher Channels PHP SDK using the Composer package manager:

text
composer require pusher/pusher-php-server "~4.0"

Next, you should configure your Channels credentials in the config/broadcasting.php configuration file. An example Channels configuration is already included in this file, allowing you to quickly specify your Channels key, secret, and application ID. The config/broadcasting.php file's pusher configuration also allows you to specify additional options that are supported by Channels, such as the cluster:

text
'options' => [
    'cluster' => 'eu',
    'useTLS' => true
],

When using Channels and Laravel Echo, you should specify pusher as your desired broadcaster when instantiating the Echo instance in your resources/js/bootstrap.js file:

text
import Echo from "laravel-echo";

window.Pusher = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key'
});

Redis

If you are using the Redis broadcaster, you should install the Predis library:

text
composer require predis/predis

The Redis broadcaster will broadcast messages using Redis' pub / sub feature; however, you will need to pair this with a WebSocket server that can receive the messages from Redis and broadcast them to your WebSocket channels.

When the Redis broadcaster publishes an event, it will be published on the event's specified channel names and the payload will be a JSON encoded string containing the event name, a data payload, and the user that generated the event's socket ID (if applicable).

Socket.IO

If you are going to pair the Redis broadcaster with a Socket.IO server, you will need to include the Socket.IO JavaScript client library in your application. You may install it via the NPM package manager:

text
npm install --save socket.io-client

Next, you will need to instantiate Echo with the socket.io connector and a host.

text
import Echo from "laravel-echo"

window.io = require('socket.io-client');

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':6001'
});

Finally, you will need to run a compatible Socket.IO server. Laravel does not include a Socket.IO server implementation; however, a community driven Socket.IO server is currently maintained at the tlaverdure/laravel-echo-server GitHub repository.

Queue Prerequisites

Before broadcasting events, you will also need to configure and run a queue listener. All event broadcasting is done via queued jobs so that the response time of your application is not seriously affected.

Concept Overview

Laravel's event broadcasting allows you to broadcast your server-side Laravel events to your client-side JavaScript application using a driver-based approach to WebSockets. Currently, Laravel ships with Pusher Channels and Redis drivers. The events may be easily consumed on the client-side using the Laravel Echo Javascript package.

Events are broadcast over "channels", which may be specified as public or private. Any visitor to your application may subscribe to a public channel without any authentication or authorization; however, in order to subscribe to a private channel, a user must be authenticated and authorized to listen on that channel.

Using An Example Application

Before diving into each component of event broadcasting, let's take a high level overview using an e-commerce store as an example. We won't discuss the details of configuring Pusher Channels or Laravel Echo since that will be discussed in detail in other sections of this documentation.

In our application, let's assume we have a page that allows users to view the shipping status for their orders. Let's also assume that a ShippingStatusUpdated event is fired when a shipping status update is processed by the application:

text
event(new ShippingStatusUpdated($update));

The `ShouldBroadcast` Interface

When a user is viewing one of their orders, we don't want them to have to refresh the page to view status updates. Instead, we want to broadcast the updates to the application as they are created. So, we need to mark the ShippingStatusUpdated event with the ShouldBroadcast interface. This will instruct Laravel to broadcast the event when it is fired:

text
<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;

class ShippingStatusUpdated implements ShouldBroadcast
{
    /**
     * Information about the shipping status update.
     *
     * @var string
     */
    public $update;
}

The ShouldBroadcast interface requires our event to define a broadcastOn method. This method is responsible for returning the channels that the event should broadcast on. An empty stub of this method is already defined on generated event classes, so we only need to fill in its details. We only want the creator of the order to be able to view status updates, so we will broadcast the event on a private channel that is tied to the order:

text
/**
 * Get the channels the event should broadcast on.
 *
 * @return \Illuminate\Broadcasting\PrivateChannel
 */
public function broadcastOn()
{
    return new PrivateChannel('order.'.$this->update->order_id);
}

Authorizing Channels

Remember, users must be authorized to listen on private channels. We may define our channel authorization rules in the routes/channels.php file. In this example, we need to verify that any user attempting to listen on the private order.1 channel is actually the creator of the order:

text
Broadcast::channel('order.{orderId}', function ($user, $orderId) {
    return $user->id === Order::findOrNew($orderId)->user_id;
});

The channel method accepts two arguments: the name of the channel and a callback which returns true or false indicating whether the user is authorized to listen on the channel.

All authorization callbacks receive the currently authenticated user as their first argument and any additional wildcard parameters as their subsequent arguments. In this example, we are using the {orderId} placeholder to indicate that the "ID" portion of the channel name is a wildcard.

Listening For Event Broadcasts

Next, all that remains is to listen for the event in our JavaScript application. We can do this using Laravel Echo. First, we'll use the private method to subscribe to the private channel. Then, we may use the listen method to listen for the ShippingStatusUpdated event. By default, all of the event's public properties will be included on the broadcast event:

text
Echo.private(`order.${orderId}`)
    .listen('ShippingStatusUpdated', (e) => {
        console.log(e.update);
    });

Defining Broadcast Events

To inform Laravel that a given event should be broadcast, implement the Illuminate\Contracts\Broadcasting\ShouldBroadcast interface on the event class. This interface is already imported into all event classes generated by the framework so you may easily add it to any of your events.

The ShouldBroadcast interface requires you to implement a single method: broadcastOn. The broadcastOn method should return a channel or array of channels that the event should broadcast on. The channels should be instances of Channel, PrivateChannel, or PresenceChannel. Instances of Channel represent public channels that any user may subscribe to, while PrivateChannels and PresenceChannels represent private channels that require channel authorization:

text
<?php

namespace App\Events;

use App\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;

class ServerCreated implements ShouldBroadcast
{
    use SerializesModels;

    public $user;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(User $user)
    {
        $this->user = $user;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('user.'.$this->user->id);
    }
}

Then, you only need to fire the event as you normally would. Once the event has been fired, a queued job will automatically broadcast the event over your specified broadcast driver.

Broadcast Name

By default, Laravel will broadcast the event using the event's class name. However, you may customize the broadcast name by defining a broadcastAs method on the event:

text
/**
 * The event's broadcast name.
 *
 * @return string
 */
public function broadcastAs()
{
    return 'server.created';
}

If you customize the broadcast name using the broadcastAs method, you should make sure to register your listener with a leading . character. This will instruct Echo to not prepend the application's namespace to the event:

text
.listen('.server.created', function (e) {
    ....
});

Broadcast Data

When an event is broadcast, all of its public properties are automatically serialized and broadcast as the event's payload, allowing you to access any of its public data from your JavaScript application. So, for example, if your event has a single public $user property that contains an Eloquent model, the event's broadcast payload would be:

text
{
    "user": {
        "id": 1,
        "name": "Patrick Stewart"
        ...
    }
}

However, if you wish to have more fine-grained control over your broadcast payload, you may add a broadcastWith method to your event. This method should return the array of data that you wish to broadcast as the event payload:

text
/**
 * Get the data to broadcast.
 *
 * @return array
 */
public function broadcastWith()
{
    return ['id' => $this->user->id];
}

Broadcast Queue

By default, each broadcast event is placed on the default queue for the default queue connection specified in your queue.php configuration file. You may customize the queue used by the broadcaster by defining a broadcastQueue property on your event class. This property should specify the name of the queue you wish to use when broadcasting:

text
/**
 * The name of the queue on which to place the event.
 *
 * @var string
 */
public $broadcastQueue = 'your-queue-name';

If you want to broadcast your event using the sync queue instead of the default queue driver, you can implement the ShouldBroadcastNow interface instead of ShouldBroadcast:

text
<?php

use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;

class ShippingStatusUpdated implements ShouldBroadcastNow
{
    //
}

Broadcast Conditions

Sometimes you want to broadcast your event only if a given condition is true. You may define these conditions by adding a broadcastWhen method to your event class:

text
/**
 * Determine if this event should broadcast.
 *
 * @return bool
 */
public function broadcastWhen()
{
    return $this->value > 100;
}

Authorizing Channels

Private channels require you to authorize that the currently authenticated user can actually listen on the channel. This is accomplished by making an HTTP request to your Laravel application with the channel name and allowing your application to determine if the user can listen on that channel. When using Laravel Echo, the HTTP request to authorize subscriptions to private channels will be made automatically; however, you do need to define the proper routes to respond to these requests.

Defining Authorization Routes

Thankfully, Laravel makes it easy to define the routes to respond to channel authorization requests. In the BroadcastServiceProvider included with your Laravel application, you will see a call to the Broadcast::routes method. This method will register the /broadcasting/auth route to handle authorization requests:

text
Broadcast::routes();

The Broadcast::routes method will automatically place its routes within the web middleware group; however, you may pass an array of route attributes to the method if you would like to customize the assigned attributes:

text
Broadcast::routes($attributes);

Customizing The Authorization Endpoint

By default, Echo will use the /broadcasting/auth endpoint to authorize channel access. However, you may specify your own authorization endpoint by passing the authEndpoint configuration option to your Echo instance:

text
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key',
    authEndpoint: '/custom/endpoint/auth'
});

Defining Authorization Callbacks

Next, we need to define the logic that will actually perform the channel authorization. This is done in the routes/channels.php file that is included with your application. In this file, you may use the Broadcast::channel method to register channel authorization callbacks:

text
Broadcast::channel('order.{orderId}', function ($user, $orderId) {
    return $user->id === Order::findOrNew($orderId)->user_id;
});

The channel method accepts two arguments: the name of the channel and a callback which returns true or false indicating whether the user is authorized to listen on the channel.

All authorization callbacks receive the currently authenticated user as their first argument and any additional wildcard parameters as their subsequent arguments. In this example, we are using the {orderId} placeholder to indicate that the "ID" portion of the channel name is a wildcard.

Authorization Callback Model Binding

Just like HTTP routes, channel routes may also take advantage of implicit and explicit route model binding. For example, instead of receiving the string or numeric order ID, you may request an actual Order model instance:

text
use App\Order;

Broadcast::channel('order.{order}', function ($user, Order $order) {
    return $user->id === $order->user_id;
});

Authorization Callback Authentication

Private and presence broadcast channels authenticate the current user via your application's default authentication guard. If the user is not authenticated, channel authorization is automatically denied and the authorization callback is never executed. However, you may assign multiple, custom guards that should authenticate the incoming request if necessary:

text
Broadcast::channel('channel', function() {
    // ...
}, ['guards' => ['web', 'admin']]);

Defining Channel Classes

If your application is consuming many different channels, your routes/channels.php file could become bulky. So, instead of using Closures to authorize channels, you may use channel classes. To generate a channel class, use the make:channel Artisan command. This command will place a new channel class in the App/Broadcasting directory.

text
php artisan make:channel OrderChannel

Next, register your channel in your routes/channels.php file:

text
use App\Broadcasting\OrderChannel;

Broadcast::channel('order.{order}', OrderChannel::class);

Finally, you may place the authorization logic for your channel in the channel class' join method. This join method will house the same logic you would have typically placed in your channel authorization Closure. You may also take advantage of channel model binding:

text
<?php

namespace App\Broadcasting;

use App\Order;
use App\User;

class OrderChannel
{
    /**
     * Create a new channel instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Authenticate the user's access to the channel.
     *
     * @param  \App\User  $user
     * @param  \App\Order  $order
     * @return array|bool
     */
    public function join(User $user, Order $order)
    {
        return $user->id === $order->user_id;
    }
}

{tip} Like many other classes in Laravel, channel classes will automatically be resolved by the service container. So, you may type-hint any dependencies required by your channel in its constructor.

Broadcasting Events

Once you have defined an event and marked it with the ShouldBroadcast interface, you only need to fire the event using the event function. The event dispatcher will notice that the event is marked with the ShouldBroadcast interface and will queue the event for broadcasting:

text
event(new ShippingStatusUpdated($update));

Only To Others

When building an application that utilizes event broadcasting, you may substitute the event function with the broadcast function. Like the event function, the broadcast function dispatches the event to your server-side listeners:

text
broadcast(new ShippingStatusUpdated($update));

However, the broadcast function also exposes the toOthers method which allows you to exclude the current user from the broadcast's recipients:

text
broadcast(new ShippingStatusUpdated($update))->toOthers();

To better understand when you may want to use the toOthers method, let's imagine a task list application where a user may create a new task by entering a task name. To create a task, your application might make a request to a /task end-point which broadcasts the task's creation and returns a JSON representation of the new task. When your JavaScript application receives the response from the end-point, it might directly insert the new task into its task list like so:

text
axios.post('/task', task)
    .then((response) => {
        this.tasks.push(response.data);
    });

However, remember that we also broadcast the task's creation. If your JavaScript application is listening for this event in order to add tasks to the task list, you will have duplicate tasks in your list: one from the end-point and one from the broadcast. You may solve this by using the toOthers method to instruct the broadcaster to not broadcast the event to the current user.

{note} Your event must use the Illuminate\Broadcasting\InteractsWithSockets trait in order to call the toOthers method.

Configuration

When you initialize a Laravel Echo instance, a socket ID is assigned to the connection. If you are using Vue and Axios, the socket ID will automatically be attached to every outgoing request as a X-Socket-ID header. Then, when you call the toOthers method, Laravel will extract the socket ID from the header and instruct the broadcaster to not broadcast to any connections with that socket ID.

If you are not using Vue and Axios, you will need to manually configure your JavaScript application to send the X-Socket-ID header. You may retrieve the socket ID using the Echo.socketId method:

text
var socketId = Echo.socketId();

Receiving Broadcasts

Installing Laravel Echo

Laravel Echo is a JavaScript library that makes it painless to subscribe to channels and listen for events broadcast by Laravel. You may install Echo via the NPM package manager. In this example, we will also install the pusher-js package since we will be using the Pusher Channels broadcaster:

text
npm install --save laravel-echo pusher-js

Once Echo is installed, you are ready to create a fresh Echo instance in your application's JavaScript. A great place to do this is at the bottom of the resources/js/bootstrap.js file that is included with the Laravel framework:

text
import Echo from "laravel-echo"

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key'
});

When creating an Echo instance that uses the pusher connector, you may also specify a cluster as well as whether the connection must be made over TLS (by default, when forceTLS is false, a non-TLS connection will be made if the page was loaded over HTTP, or as a fallback if a TLS connection fails):

text
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key',
    cluster: 'eu',
    forceTLS: true
});

Using An Existing Client Instance

If you already have a Pusher Channels or Socket.io client instance that you would like Echo to utilize, you may pass it to Echo via the client configuration option:

text
const client = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key',
    client: client
});

Listening For Events

Once you have installed and instantiated Echo, you are ready to start listening for event broadcasts. First, use the channel method to retrieve an instance of a channel, then call the listen method to listen for a specified event:

text
Echo.channel('orders')
    .listen('OrderShipped', (e) => {
        console.log(e.order.name);
    });

If you would like to listen for events on a private channel, use the private method instead. You may continue to chain calls to the listen method to listen for multiple events on a single channel:

text
Echo.private('orders')
    .listen(...)
    .listen(...)
    .listen(...);

Leaving A Channel

To leave a channel, you may call the leaveChannel method on your Echo instance:

text
Echo.leaveChannel('orders');

If you would like to leave a channel and also its associated private and presence channels, you may call the leave method:

text
Echo.leave('orders');

Namespaces

You may have noticed in the examples above that we did not specify the full namespace for the event classes. This is because Echo will automatically assume the events are located in the App\Events namespace. However, you may configure the root namespace when you instantiate Echo by passing a namespace configuration option:

text
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-channels-key',
    namespace: 'App.Other.Namespace'
});

Alternatively, you may prefix event classes with a . when subscribing to them using Echo. This will allow you to always specify the fully-qualified class name:

text
Echo.channel('orders')
    .listen('.Namespace\\Event\\Class', (e) => {
        //
    });

Presence Channels

Presence channels build on the security of private channels while exposing the additional feature of awareness of who is subscribed to the channel. This makes it easy to build powerful, collaborative application features such as notifying users when another user is viewing the same page.

Authorizing Presence Channels

All presence channels are also private channels; therefore, users must be authorized to access them. However, when defining authorization callbacks for presence channels, you will not return true if the user is authorized to join the channel. Instead, you should return an array of data about the user.

The data returned by the authorization callback will be made available to the presence channel event listeners in your JavaScript application. If the user is not authorized to join the presence channel, you should return false or null:

text
Broadcast::channel('chat.{roomId}', function ($user, $roomId) {
    if ($user->canJoinRoom($roomId)) {
        return ['id' => $user->id, 'name' => $user->name];
    }
});

Joining Presence Channels

To join a presence channel, you may use Echo's join method. The join method will return a PresenceChannel implementation which, along with exposing the listen method, allows you to subscribe to the here, joining, and leaving events.

text
Echo.join(`chat.${roomId}`)
    .here((users) => {
        //
    })
    .joining((user) => {
        console.log(user.name);
    })
    .leaving((user) => {
        console.log(user.name);
    });

The here callback will be executed immediately once the channel is joined successfully, and will receive an array containing the user information for all of the other users currently subscribed to the channel. The joining method will be executed when a new user joins a channel, while the leaving method will be executed when a user leaves the channel.

Broadcasting To Presence Channels

Presence channels may receive events just like public or private channels. Using the example of a chatroom, we may want to broadcast NewMessage events to the room's presence channel. To do so, we'll return an instance of PresenceChannel from the event's broadcastOn method:

text
/**
 * Get the channels the event should broadcast on.
 *
 * @return Channel|array
 */
public function broadcastOn()
{
    return new PresenceChannel('room.'.$this->message->room_id);
}

Like public or private events, presence channel events may be broadcast using the broadcast function. As with other events, you may use the toOthers method to exclude the current user from receiving the broadcast:

text
broadcast(new NewMessage($message));

broadcast(new NewMessage($message))->toOthers();

You may listen for the join event via Echo's listen method:

text
Echo.join(`chat.${roomId}`)
    .here(...)
    .joining(...)
    .leaving(...)
    .listen('NewMessage', (e) => {
        //
    });

Client Events

{tip} When using Pusher Channels, you must enable the "Client Events" option in the "App Settings" section of your application dashboard in order to send client events.

Sometimes you may wish to broadcast an event to other connected clients without hitting your Laravel application at all. This can be particularly useful for things like "typing" notifications, where you want to alert users of your application that another user is typing a message on a given screen.

To broadcast client events, you may use Echo's whisper method:

text
Echo.private('chat')
    .whisper('typing', {
        name: this.user.name
    });

To listen for client events, you may use the listenForWhisper method:

text
Echo.private('chat')
    .listenForWhisper('typing', (e) => {
        console.log(e.name);
    });

Notifications

By pairing event broadcasting with notifications, your JavaScript application may receive new notifications as they occur without needing to refresh the page. First, be sure to read over the documentation on using the broadcast notification channel.

Once you have configured a notification to use the broadcast channel, you may listen for the broadcast events using Echo's notification method. Remember, the channel name should match the class name of the entity receiving the notifications:

text
Echo.private(`App.User.${userId}`)
    .notification((notification) => {
        console.log(notification.type);
    });

In this example, all notifications sent to App\User instances via the broadcast channel would be received by the callback. A channel authorization callback for the App.User.{id} channel is included in the default BroadcastServiceProvider that ships with the Laravel framework.


File: cache.md

Cache

Configuration

Laravel provides an expressive, unified API for various caching backends. The cache configuration is located at config/cache.php. In this file you may specify which cache driver you would like to be used by default throughout your application. Laravel supports popular caching backends like Memcached and Redis out of the box.

The cache configuration file also contains various other options, which are documented within the file, so make sure to read over these options. By default, Laravel is configured to use the file cache driver, which stores the serialized, cached objects in the filesystem. For larger applications, it is recommended that you use a more robust driver such as Memcached or Redis. You may even configure multiple cache configurations for the same driver.

Driver Prerequisites

Database

When using the database cache driver, you will need to setup a table to contain the cache items. You'll find an example Schema declaration for the table below:

text
Schema::create('cache', function ($table) {
    $table->string('key')->unique();
    $table->text('value');
    $table->integer('expiration');
});

{tip} You may also use the php artisan cache:table Artisan command to generate a migration with the proper schema.

Memcached

Using the Memcached driver requires the Memcached PECL package to be installed. You may list all of your Memcached servers in the config/cache.php configuration file:

text
'memcached' => [
    [
        'host' => '127.0.0.1',
        'port' => 11211,
        'weight' => 100
    ],
],

You may also set the host option to a UNIX socket path. If you do this, the port option should be set to 0:

text
'memcached' => [
    [
        'host' => '/var/run/memcached/memcached.sock',
        'port' => 0,
        'weight' => 100
    ],
],

Redis

Before using a Redis cache with Laravel, you will need to either install the PhpRedis PHP extension via PECL or install the predis/predis package (~1.0) via Composer.

For more information on configuring Redis, consult its Laravel documentation page.

Cache Usage

Obtaining A Cache Instance

The Illuminate\Contracts\Cache\Factory and Illuminate\Contracts\Cache\Repository contracts provide access to Laravel's cache services. The Factory contract provides access to all cache drivers defined for your application. The Repository contract is typically an implementation of the default cache driver for your application as specified by your cache configuration file.

However, you may also use the Cache facade, which is what we will use throughout this documentation. The Cache facade provides convenient, terse access to the underlying implementations of the Laravel cache contracts:

text
<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;

class UserController extends Controller
{
    /**
     * Show a list of all users of the application.
     *
     * @return Response
     */
    public function index()
    {
        $value = Cache::get('key');

        //
    }
}

Accessing Multiple Cache Stores

Using the Cache facade, you may access various cache stores via the store method. The key passed to the store method should correspond to one of the stores listed in the stores configuration array in your cache configuration file:

text
$value = Cache::store('file')->get('foo');

Cache::store('redis')->put('bar', 'baz', 600); // 10 Minutes

Retrieving Items From The Cache

The get method on the Cache facade is used to retrieve items from the cache. If the item does not exist in the cache, null will be returned. If you wish, you may pass a second argument to the get method specifying the default value you wish to be returned if the item doesn't exist:

text
$value = Cache::get('key');

$value = Cache::get('key', 'default');

You may even pass a Closure as the default value. The result of the Closure will be returned if the specified item does not exist in the cache. Passing a Closure allows you to defer the retrieval of default values from a database or other external service:

text
$value = Cache::get('key', function () {
    return DB::table(...)->get();
});

Checking For Item Existence

The has method may be used to determine if an item exists in the cache. This method will return false if the value is null:

text
if (Cache::has('key')) {
    //
}

Incrementing / Decrementing Values

The increment and decrement methods may be used to adjust the value of integer items in the cache. Both of these methods accept an optional second argument indicating the amount by which to increment or decrement the item's value:

text
Cache::increment('key');
Cache::increment('key', $amount);
Cache::decrement('key');
Cache::decrement('key', $amount);

Retrieve & Store

Sometimes you may wish to retrieve an item from the cache, but also store a default value if the requested item doesn't exist. For example, you may wish to retrieve all users from the cache or, if they don't exist, retrieve them from the database and add them to the cache. You may do this using the Cache::remember method:

text
$value = Cache::remember('users', $seconds, function () {
    return DB::table('users')->get();
});

If the item does not exist in the cache, the Closure passed to the remember method will be executed and its result will be placed in the cache.

You may use the rememberForever method to retrieve an item from the cache or store it forever:

text
$value = Cache::rememberForever('users', function () {
    return DB::table('users')->get();
});

Retrieve & Delete

If you need to retrieve an item from the cache and then delete the item, you may use the pull method. Like the get method, null will be returned if the item does not exist in the cache:

text
$value = Cache::pull('key');

Storing Items In The Cache

You may use the put method on the Cache facade to store items in the cache:

text
Cache::put('key', 'value', $seconds);

If the storage time is not passed to the put method, the item will be stored indefinitely:

text
Cache::put('key', 'value');

Instead of passing the number of seconds as an integer, you may also pass a DateTime instance representing the expiration time of the cached item:

text
Cache::put('key', 'value', now()->addMinutes(10));

Store If Not Present

The add method will only add the item to the cache if it does not already exist in the cache store. The method will return true if the item is actually added to the cache. Otherwise, the method will return false:

text
Cache::add('key', 'value', $seconds);

Storing Items Forever

The forever method may be used to store an item in the cache permanently. Since these items will not expire, they must be manually removed from the cache using the forget method:

text
Cache::forever('key', 'value');

{tip} If you are using the Memcached driver, items that are stored "forever" may be removed when the cache reaches its size limit.

Removing Items From The Cache

You may remove items from the cache using the forget method:

text
Cache::forget('key');

You may also remove items by providing a zero or negative TTL:

text
Cache::put('key', 'value', 0);

Cache::put('key', 'value', -5);

You may clear the entire cache using the flush method:

text
Cache::flush();

{note} Flushing the cache does not respect the cache prefix and will remove all entries from the cache. Consider this carefully when clearing a cache which is shared by other applications.

Atomic Locks

{note} To utilize this feature, your application must be using the memcached, dynamodb, or redis cache driver as your application's default cache driver. In addition, all servers must be communicating with the same central cache server.

Atomic locks allow for the manipulation of distributed locks without worrying about race conditions. For example, Laravel Forge uses atomic locks to ensure that only one remote task is being executed on a server at a time. You may create and manage locks using the Cache::lock method:

text
use Illuminate\Support\Facades\Cache;

$lock = Cache::lock('foo', 10);

if ($lock->get()) {
    // Lock acquired for 10 seconds...

    $lock->release();
}

The get method also accepts a Closure. After the Closure is executed, Laravel will automatically release the lock:

text
Cache::lock('foo')->get(function () {
    // Lock acquired indefinitely and automatically released...
});

If the lock is not available at the moment you request it, you may instruct Laravel to wait for a specified number of seconds. If the lock can not be acquired within the specified time limit, an Illuminate\Contracts\Cache\LockTimeoutException will be thrown:

text
use Illuminate\Contracts\Cache\LockTimeoutException;

$lock = Cache::lock('foo', 10);

try {
    $lock->block(5);

    // Lock acquired after waiting maximum of 5 seconds...
} catch (LockTimeoutException $e) {
    // Unable to acquire lock...
} finally {
    optional($lock)->release();
}

Cache::lock('foo', 10)->block(5, function () {
    // Lock acquired after waiting maximum of 5 seconds...
});

Managing Locks Across Processes

Sometimes, you may wish to acquire a lock in one process and release it in another process. For example, you may acquire a lock during a web request and wish to release the lock at the end of a queued job that is triggered by that request. In this scenario, you should pass the lock's scoped "owner token" to the queued job so that the job can re-instantiate the lock using the given token:

text
// Within Controller...
$podcast = Podcast::find($id);

$lock = Cache::lock('foo', 120);

if ($result = $lock->get()) {
    ProcessPodcast::dispatch($podcast, $lock->owner());
}

// Within ProcessPodcast Job...
Cache::restoreLock('foo', $this->owner)->release();

If you would like to release a lock without respecting its current owner, you may use the forceRelease method:

text
Cache::lock('foo')->forceRelease();

The Cache Helper

In addition to using the Cache facade or cache contract, you may also use the global cache function to retrieve and store data via the cache. When the cache function is called with a single, string argument, it will return the value of the given key:

text
$value = cache('key');

If you provide an array of key / value pairs and an expiration time to the function, it will store values in the cache for the specified duration:

text
cache(['key' => 'value'], $seconds);

cache(['key' => 'value'], now()->addMinutes(10));

When the cache function is called without any arguments, it returns an instance of the Illuminate\Contracts\Cache\Factory implementation, allowing you to call other caching methods:

text
cache()->remember('users', $seconds, function () {
    return DB::table('users')->get();
});

{tip} When testing call to the global cache function, you may use the Cache::shouldReceive method just as if you were testing a facade.

Cache Tags

{note} Cache tags are not supported when using the file or database cache drivers. Furthermore, when using multiple tags with caches that are stored "forever", performance will be best with a driver such as memcached, which automatically purges stale records.

Storing Tagged Cache Items

Cache tags allow you to tag related items in the cache and then flush all cached values that have been assigned a given tag. You may access a tagged cache by passing in an ordered array of tag names. For example, let's access a tagged cache and put value in the cache:

text
Cache::tags(['people', 'artists'])->put('John', $john, $seconds);

Cache::tags(['people', 'authors'])->put('Anne', $anne, $seconds);

Accessing Tagged Cache Items

To retrieve a tagged cache item, pass the same ordered list of tags to the tags method and then call the get method with the key you wish to retrieve:

text
$john = Cache::tags(['people', 'artists'])->get('John');

$anne = Cache::tags(['people', 'authors'])->get('Anne');

Removing Tagged Cache Items

You may flush all items that are assigned a tag or list of tags. For example, this statement would remove all caches tagged with either people, authors, or both. So, both Anne and John would be removed from the cache:

text
Cache::tags(['people', 'authors'])->flush();

In contrast, this statement would remove only caches tagged with authors, so Anne would be removed, but not John:

text
Cache::tags('authors')->flush();

Adding Custom Cache Drivers

Writing The Driver

To create our custom cache driver, we first need to implement the Illuminate\Contracts\Cache\Store contract. So, a MongoDB cache implementation would look something like this:

text
<?php

namespace App\Extensions;

use Illuminate\Contracts\Cache\Store;

class MongoStore implements Store
{
    public function get($key) {}
    public function many(array $keys) {}
    public function put($key, $value, $seconds) {}
    public function putMany(array $values, $seconds) {}
    public function increment($key, $value = 1) {}
    public function decrement($key, $value = 1) {}
    public function forever($key, $value) {}
    public function forget($key) {}
    public function flush() {}
    public function getPrefix() {}
}

We just need to implement each of these methods using a MongoDB connection. For an example of how to implement each of these methods, take a look at the Illuminate\Cache\MemcachedStore in the framework source code. Once our implementation is complete, we can finish our custom driver registration.

text
Cache::extend('mongo', function ($app) {
    return Cache::repository(new MongoStore);
});

{tip} If you're wondering where to put your custom cache driver code, you could create an Extensions namespace within your app directory. However, keep in mind that Laravel does not have a rigid application structure and you are free to organize your application according to your preferences.

Registering The Driver

To register the custom cache driver with Laravel, we will use the extend method on the Cache facade. The call to Cache::extend could be done in the boot method of the default App\Providers\AppServiceProvider that ships with fresh Laravel applications, or you may create your own service provider to house the extension - just don't forget to register the provider in the config/app.php provider array:

text
<?php

namespace App\Providers;

use App\Extensions\MongoStore;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;

class CacheServiceProvider extends ServiceProvider
{
    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Cache::extend('mongo', function ($app) {
            return Cache::repository(new MongoStore);
        });
    }
}

The first argument passed to the extend method is the name of the driver. This will correspond to your driver option in the config/cache.php configuration file. The second argument is a Closure that should return an Illuminate\Cache\Repository instance. The Closure will be passed an $app instance, which is an instance of the service container.

Once your extension is registered, update your config/cache.php configuration file's driver option to the name of your extension.

Events

To execute code on every cache operation, you may listen for the events fired by the cache. Typically, you should place these event listeners within your EventServiceProvider:

text
/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'Illuminate\Cache\Events\CacheHit' => [
        'App\Listeners\LogCacheHit',
    ],

    'Illuminate\Cache\Events\CacheMissed' => [
        'App\Listeners\LogCacheMissed',
    ],

    'Illuminate\Cache\Events\KeyForgotten' => [
        'App\Listeners\LogKeyForgotten',
    ],

    'Illuminate\Cache\Events\KeyWritten' => [
        'App\Listeners\LogKeyWritten',
    ],
];