Docs

GitHub - laravel/docs
Repo URL: https://github.com/laravel/docs
Edited by:
Cover image: Cover image
Share this using: email, Google+, Twitter, Facebook.
Exports: EPUB | MOBI

1 Artisan Console

<a name=“introduction”></a>

1.1 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:

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:

php artisan help migrate

1.1.0.1 Laravel 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:

php artisan tinker

<a name=“writing-commands”></a>

1.2 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.

<a name=“generating-commands”></a>

1.2.1 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:

php artisan make:command SendEmails

<a name=“command-structure”></a>

1.2.2 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 constructor. The Laravel service container will automatically inject all dependencies type-hinted in the constructor:

<?php

namespace App\Console\Commands;

use App\User;
use App\DripEmailer;
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';

    /**
     * The drip e-mail service.
     *
     * @var DripEmailer
     */
    protected $drip;

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

        $this->drip = $drip;
    }

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

<a name=“closure-commands”></a>

1.2.3 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:

/**
 * 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:

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.

1.2.3.1 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:

use App\User;
use App\DripEmailer;

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

1.2.3.2 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:

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

<a name=“defining-input-expectations”></a>

1.3 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.

<a name=“arguments”></a>

1.3.1 Arguments

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

/**
 * 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:

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

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

<a name=“options”></a>

1.3.2 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:

/**
 * 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:

php artisan email:send 1 --queue

<a name=“options-with-values”></a>

1.3.2.1 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:

/**
 * 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:

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:

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

<a name=“option-shortcuts”></a>

1.3.2.2 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:

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

<a name=“input-arrays”></a>

1.3.3 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:

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']:

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:

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

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

<a name=“input-descriptions”></a>

1.3.4 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:

/**
 * 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}';

<a name=“command-io”></a>

1.4 Command I/O

<a name=“retrieving-input”></a>

1.4.1 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:

/**
 * 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:

$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:

// 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.

<a name=“prompting-for-input”></a>

1.4.2 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:

/**
 * 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:

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

1.4.2.1 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.

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

1.4.2.2 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:

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

1.4.2.3 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:

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

<a name=“writing-output”></a>

1.4.3 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:

/**
 * 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:

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

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

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

1.4.3.1 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:

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

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

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

1.4.3.2 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:

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

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

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

    $bar->advance();
}

$bar->finish();

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

<a name=“registering-commands”></a>

1.5 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:

/**
 * 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:

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

<a name=“programmatically-executing-commands”></a>

1.6 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 the name of the command as the first argument, and an array of command parameters as the second argument. The exit code will be returned:

Route::get('/foo', function () {
    $exitCode = Artisan::call('email:send', [
        'user' => 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:

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:

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

1.6.0.1 Passing Array Values

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

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

1.6.0.2 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:

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

<a name=“calling-commands-from-other-commands”></a>

1.6.1 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:

/**
 * 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:

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

2 Authentication

<a name=“introduction”></a>

2.1 Introduction

{tip} Want to get started fast? Just run php artisan make:auth and php artisan migrate in a fresh Laravel application. Then, navigate your browser to http://your-app.dev/register or any other URL that is assigned to your application. These two 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.

<a name=“introduction-database-considerations”></a>

2.1.1 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.

<a name=“authentication-quickstart”></a>

2.2 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.

<a name=“included-routing”></a>

2.2.1 Routing

Laravel provides a quick way to scaffold all of the routes and views you need for authentication using one simple command:

php artisan make: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.

<a name=“included-views”></a>

2.2.2 Views

As mentioned in the previous section, the php artisan make:auth command will create all of the views you need for authentication and place them in the resources/views/auth directory.

The make:auth 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.

<a name=“included-authenticating”></a>

2.2.3 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.

2.2.3.1 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, and ResetPasswordController:

protected $redirectTo = '/';

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

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

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

2.2.3.2 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:

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

2.2.3.3 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:

use Illuminate\Support\Facades\Auth;

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

2.2.3.4 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.

<a name=“retrieving-the-authenticated-user”></a>

2.2.4 Retrieving The Authenticated User

You may access the authenticated user via the Auth facade:

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:

<?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...
    }
}

2.2.4.1 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:

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.

<a name=“protecting-routes”></a>

2.2.5 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:

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

Of course, 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:

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

2.2.5.1 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:

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

<a name=“login-throttling”></a>

2.2.6 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.

<a name=“authenticating-users”></a>

2.3 Manually Authenticating Users

Of course, 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:

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    /**
     * Handle an authentication attempt.
     *
     * @return Response
     */
    public function authenticate()
    {
        if (Auth::attempt(['email' => $email, 'password' => $password])) {
            // 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.

2.3.0.1 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”:

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.

2.3.0.2 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:

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

2.3.0.3 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:

Auth::logout();

<a name=“remembering-users”></a>

2.3.1 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. Of course, your users table must include the string remember_token column, which will be used to store the “remember me” token.

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:

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

<a name=“other-authentication-methods”></a>

2.3.2 Other Authentication Methods

2.3.2.1 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. Of course, the App\User model included with Laravel already implements this interface:

Auth::login($user);

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

Of course, you may specify the guard instance you would like to use:

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

2.3.2.2 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:

Auth::loginUsingId(1);

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

2.3.2.3 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:

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

<a name=“http-basic-authentication”></a>

2.4 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:

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”.

2.4.0.1 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:

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

<a name=“stateless-http-basic-authentication”></a>

2.4.1 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:

<?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:

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

<a name=“adding-custom-guards”></a>

2.5 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:

<?php

namespace App\Providers;

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

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:

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

<a name=“adding-custom-user-providers”></a>

2.6 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:

<?php

namespace App\Providers;

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

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:

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

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

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

<a name=“the-user-provider-contract”></a>

2.6.1 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:

<?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. The new token can be either a fresh token, 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.

<a name=“the-authenticatable-contract”></a>

2.6.2 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 and retrieveByCredentials methods:

<?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.

<a name=“events”></a>

2.7 Events

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

/**
 * 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',
    ],
];

3 Authorization

<a name=“introduction”></a>

3.1 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.

<a name=“gates”></a>

3.2 Gates

<a name=“writing-gates”></a>

3.2.1 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:

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

    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:

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

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

3.2.1.1 Resource Gates

You may also define multiple Gate abilities at once using the resource method:

Gate::resource('posts', 'PostPolicy');

This is identical to manually defining the following Gate definitions:

Gate::define('posts.view', 'PostPolicy@view');
Gate::define('posts.create', 'PostPolicy@create');
Gate::define('posts.update', 'PostPolicy@update');
Gate::define('posts.delete', 'PostPolicy@delete');

By default, the view, create, update, and delete abilities will be defined. You may override or add to the default abilities by passing an array as a third argument to the resource method. The keys of the array define the names of the abilities while the values define the method names. For example, the following code will create two new Gate definitions - posts.image and posts.photo:

Gate::resource('posts', 'PostPolicy', [
    'image' => 'updateImage',
    'photo' => 'updatePhoto',
]);

<a name=“authorizing-actions-via-gates”></a>

3.2.2 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:

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:

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...
}

<a name=“creating-policies”></a>

3.3 Creating Policies

<a name=“generating-policies”></a>

3.3.1 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:

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:

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.

<a name=“registering-policies”></a>

3.3.2 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:

<?php

namespace App\Providers;

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

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();

        //
    }
}

<a name=“writing-policies”></a>

3.4 Writing Policies

<a name=“policy-methods”></a>

3.4.1 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:

<?php

namespace App\Policies;

use App\User;
use App\Post;

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, and delete actions.

<a name=“methods-without-models”></a>

3.4.2 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:

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

<a name=“policy-filters”></a>

3.4.3 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:

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.

<a name=“authorizing-actions-using-policies”></a>

3.5 Authorizing Actions Using Policies

<a name=“via-the-user-model”></a>

3.5.1 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:

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.

3.5.1.1 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:

use App\Post;

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

<a name=“via-middleware”></a>

3.5.2 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:

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.

3.5.2.1 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:

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

<a name=“via-controller-helpers”></a>

3.5.3 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:

<?php

namespace App\Http\Controllers;

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

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

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

3.5.3.1 Actions That Don’t Require Models

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

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

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

<a name=“via-blade-templates”></a>

3.5.4 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:

@can('update', $post)
    <!-- The Current User Can Update The Post -->
@elsecan('create', App\Post::class)
    <!-- The Current User Can Create New Post -->
@endcan

@cannot('update', $post)
    <!-- The Current User Can't Update The Post -->
@elsecannot('create', App\Post::class)
    <!-- The Current User Can't Create New Post -->
@endcannot

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

@if (Auth::user()->can('update', $post))
    <!-- The Current User Can Update The Post -->
@endif

@unless (Auth::user()->can('update', $post))
    <!-- The Current User Can't Update The Post -->
@endunless

3.5.4.1 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:

@can('create', App\Post::class)
    <!-- The Current User Can Create Posts -->
@endcan

@cannot('create', App\Post::class)
    <!-- The Current User Can't Create Posts -->
@endcannot

4 Laravel Cashier

<a name=“introduction”></a>

4.1 Introduction

Laravel Cashier provides an expressive, fluent interface to Stripe’s and Braintree’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.

{note} If you’re only performing “one-off” charges and do not offer subscriptions, you should not use Cashier. Instead, use the Stripe and Braintree SDKs directly.

<a name=“configuration”></a>

4.2 Configuration

<a name=“stripe-configuration”></a>

4.2.1 Stripe

4.2.1.1 Composer

First, add the Cashier package for Stripe to your dependencies:

composer require "laravel/cashier":"~7.0"

4.2.1.2 Database Migrations

Before using Cashier, we’ll also need to prepare the database. We need to add several columns to your users table and create a new subscriptions table to hold all of our customer’s subscriptions:

Schema::table('users', function ($table) {
    $table->string('stripe_id')->nullable();
    $table->string('card_brand')->nullable();
    $table->string('card_last_four')->nullable();
    $table->timestamp('trial_ends_at')->nullable();
});

Schema::create('subscriptions', function ($table) {
    $table->increments('id');
    $table->integer('user_id');
    $table->string('name');
    $table->string('stripe_id');
    $table->string('stripe_plan');
    $table->integer('quantity');
    $table->timestamp('trial_ends_at')->nullable();
    $table->timestamp('ends_at')->nullable();
    $table->timestamps();
});

Once the migrations have been created, run the migrate Artisan command.

4.2.1.3 Billable Model

Next, 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 credit card information:

use Laravel\Cashier\Billable;

class User extends Authenticatable
{
    use Billable;
}

4.2.1.4 API Keys

Finally, you should configure your Stripe key in your services.php configuration file. You can retrieve your Stripe API keys from the Stripe control panel:

'stripe' => [
    'model'  => App\User::class,
    'key' => env('STRIPE_KEY'),
    'secret' => env('STRIPE_SECRET'),
],

<a name=“braintree-configuration”></a>

4.2.2 Braintree

4.2.2.1 Braintree Caveats

For many operations, the Stripe and Braintree implementations of Cashier function the same. Both services provide subscription billing with credit cards but Braintree also supports payments via PayPal. However, Braintree also lacks some features that are supported by Stripe. You should keep the following in mind when deciding to use Stripe or Braintree:

<div class=“content-list” markdown=“1”>

  • Braintree supports PayPal while Stripe does not.
  • Braintree does not support the increment and decrement methods on subscriptions. This is a Braintree limitation, not a Cashier limitation.
  • Braintree does not support percentage based discounts. This is a Braintree limitation, not a Cashier limitation.
    </div>

4.2.2.2 Composer

First, add the Cashier package for Braintree to your dependencies:

composer require "laravel/cashier-braintree":"~2.0"

4.2.2.3 Service Provider

Next, register the Laravel\Cashier\CashierServiceProvider service provider in your config/app.php configuration file:

Laravel\Cashier\CashierServiceProvider::class

4.2.2.4 Plan Credit Coupon

Before using Cashier with Braintree, you will need to define a plan-credit discount in your Braintree control panel. This discount will be used to properly prorate subscriptions that change from yearly to monthly billing, or from monthly to yearly billing.

The discount amount configured in the Braintree control panel can be any value you wish, as Cashier will override the defined amount with our own custom amount each time we apply the coupon. This coupon is needed since Braintree does not natively support prorating subscriptions across subscription frequencies.

4.2.2.5 Database Migrations

Before using Cashier, we’ll need to prepare the database. We need to add several columns to your users table and create a new subscriptions table to hold all of our customer’s subscriptions:

Schema::table('users', function ($table) {
    $table->string('braintree_id')->nullable();
    $table->string('paypal_email')->nullable();
    $table->string('card_brand')->nullable();
    $table->string('card_last_four')->nullable();
    $table->timestamp('trial_ends_at')->nullable();
});

Schema::create('subscriptions', function ($table) {
    $table->increments('id');
    $table->integer('user_id');
    $table->string('name');
    $table->string('braintree_id');
    $table->string('braintree_plan');
    $table->integer('quantity');
    $table->timestamp('trial_ends_at')->nullable();
    $table->timestamp('ends_at')->nullable();
    $table->timestamps();
});

Once the migrations have been created, run the migrate Artisan command.

4.2.2.6 Billable Model

Next, add the Billable trait to your model definition:

use Laravel\Cashier\Billable;

class User extends Authenticatable
{
    use Billable;
}

4.2.2.7 API Keys

Next, you should configure the following options in your services.php file:

'braintree' => [
    'model'  => App\User::class,
    'environment' => env('BRAINTREE_ENV'),
    'merchant_id' => env('BRAINTREE_MERCHANT_ID'),
    'public_key' => env('BRAINTREE_PUBLIC_KEY'),
    'private_key' => env('BRAINTREE_PRIVATE_KEY'),
],

Then you should add the following Braintree SDK calls to your AppServiceProvider service provider’s boot method:

\Braintree_Configuration::environment(config('services.braintree.environment'));
\Braintree_Configuration::merchantId(config('services.braintree.merchant_id'));
\Braintree_Configuration::publicKey(config('services.braintree.public_key'));
\Braintree_Configuration::privateKey(config('services.braintree.private_key'));

<a name=“currency-configuration”></a>

4.2.3 Currency Configuration

The default Cashier currency is United States Dollars (USD). You can change the default currency by calling the Cashier::useCurrency method from within the boot method of one of your service providers. The useCurrency method accepts two string parameters: the currency and the currency’s symbol:

use Laravel\Cashier\Cashier;

Cashier::useCurrency('eur', '€');

<a name=“subscriptions”></a>

4.3 Subscriptions

<a name=“creating-subscriptions”></a>

4.3.1 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:

$user = User::find(1);

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

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 Stripe / Braintree plan the user is subscribing to. This value should correspond to the plan’s identifier in Stripe or Braintree.

The create method, which accepts a Stripe credit card / source token, will begin the subscription as well as update your database with the customer ID and other relevant billing information.

4.3.1.1 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:

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

To learn more about the additional fields supported by Stripe or Braintree, check out Stripe’s documentation on customer creation or the corresponding Braintree documentation.

4.3.1.2 Coupons

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

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

<a name=“checking-subscription-status”></a>

4.3.2 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:

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:

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:

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 / Braintree plan ID. In this example, we will determine if the user’s main subscription is actively subscribed to the monthly plan:

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

4.3.2.1 Cancelled Subscription Status

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

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:

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

<a name=“changing-plans”></a>

4.3.3 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:

$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:

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

<a name=“subscription-quantity”></a>

4.3.4 Subscription Quantity

{note} Subscription quantities are only supported by the Stripe edition of Cashier. Braintree does not have a feature that corresponds to Stripe’s “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:

$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:

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

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

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

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

<a name=“subscription-taxes”></a>

4.3.5 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.

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.

<a name=“cancelling-subscriptions”></a>

4.3.6 Cancelling Subscriptions

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

$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:

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

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

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

<a name=“resuming-subscriptions”></a>

4.3.7 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:

$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.

<a name=“updating-credit-cards”></a>

4.3.8 Updating Credit Cards

The updateCard method may be used to update a customer’s credit card information. This method accepts a Stripe token and will assign the new credit card as the default billing source:

$user->updateCard($stripeToken);

<a name=“subscription-trials”></a>

4.4 Subscription Trials

<a name=“with-credit-card-up-front”></a>

4.4.1 With Credit Card 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:

$user = User::find(1);

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

This method will set the trial period ending date on the subscription record within the database, as well as instruct Stripe / Braintree to not begin billing the customer until after this date.

{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.

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:

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

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

<a name=“without-credit-card-up-front”></a>

4.4.2 Without Credit Card 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:

$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:

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:

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:

$user = User::find(1);

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

<a name=“handling-stripe-webhooks”></a>

4.5 Handling Stripe Webhooks

Both Stripe and Braintree can notify your application of a variety of events via webhooks. To handle Stripe webhooks, define a route that points to Cashier’s webhook controller. This controller will handle all incoming webhook requests and dispatch them to the proper controller method:

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

{note} Once you have registered your route, be sure to configure the webhook URL in your Stripe control panel settings.

By default, this controller will automatically handle cancelling subscriptions that have too many failed charges (as defined by your Stripe settings); however, as we’ll soon discover, you can extend this controller to handle any webhook event you like.

4.5.0.1 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:

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

<a name=“defining-webhook-event-handlers”></a>

4.5.1 Defining Webhook Event Handlers

Cashier automatically handles subscription cancellation on failed charges, but if you have additional Stripe 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 Stripe 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:

<?php

namespace App\Http\Controllers;

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

class WebhookController extends CashierController
{
    /**
     * Handle a Stripe webhook.
     *
     * @param  array  $payload
     * @return Response
     */
    public function handleInvoicePaymentSucceeded($payload)
    {
        // Handle The Event
    }
}

<a name=“handling-failed-subscriptions”></a>

4.5.2 Failed Subscriptions

What if a customer’s credit card expires? No worries - Cashier includes a Webhook controller that can easily cancel the customer’s subscription for you. As noted above, all you need to do is point a route to the controller:

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

That’s it! Failed payments will 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).

<a name=“handling-braintree-webhooks”></a>

4.6 Handling Braintree Webhooks

Both Stripe and Braintree can notify your application of a variety of events via webhooks. To handle Braintree webhooks, define a route that points to Cashier’s webhook controller. This controller will handle all incoming webhook requests and dispatch them to the proper controller method:

Route::post(
    'braintree/webhook',
    '\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);

{note} Once you have registered your route, be sure to configure the webhook URL in your Braintree control panel settings.

By default, this controller will automatically handle cancelling subscriptions that have too many failed charges (as defined by your Braintree settings); however, as we’ll soon discover, you can extend this controller to handle any webhook event you like.

4.6.0.1 Webhooks & CSRF Protection

Since Braintree 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:

protected $except = [
    'braintree/*',
];

<a name=“defining-braintree-webhook-event-handlers”></a>

4.6.1 Defining Webhook Event Handlers

Cashier automatically handles subscription cancellation on failed charges, but if you have additional Braintree 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 Braintree webhook you wish to handle. For example, if you wish to handle the dispute_opened webhook, you should add a handleDisputeOpened method to the controller:

<?php

namespace App\Http\Controllers;

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

class WebhookController extends CashierController
{
    /**
     * Handle a Braintree webhook.
     *
     * @param  WebhookNotification  $webhook
     * @return Response
     */
    public function handleDisputeOpened(WebhookNotification $notification)
    {
        // Handle The Event
    }
}

<a name=“handling-braintree-failed-subscriptions”></a>

4.6.2 Failed Subscriptions

What if a customer’s credit card expires? No worries - Cashier includes a Webhook controller that can easily cancel the customer’s subscription for you. Just point a route to the controller:

Route::post(
    'braintree/webhook',
    '\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);

That’s it! Failed payments will be captured and handled by the controller. The controller will cancel the customer’s subscription when Braintree determines the subscription has failed (normally after three failed payment attempts). Don’t forget: you will need to configure the webhook URI in your Braintree control panel settings.

<a name=“single-charges”></a>

4.7 Single Charges

4.7.1 Simple Charge

{note} When using Stripe, the charge method accepts the amount you would like to charge in the lowest denominator of the currency used by your application. However, when using Braintree, you should pass the full dollar amount to the charge method:

If you would like to make a “one off” charge against a subscribed customer’s credit card, you may use the charge method on a billable model instance.

// Stripe Accepts Charges In Cents...
$user->charge(100);

// Braintree Accepts Charges In Dollars...
$user->charge(1);

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

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

The charge method will throw an exception if the charge fails. If the charge is successful, the full Stripe / Braintree response will be returned from the method:

try {
    $response = $user->charge(100);
} catch (Exception $e) {
    //
}

4.7.2 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”:

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

// Braintree Accepts Charges In Dollars...
$user->invoiceFor('One Time Fee', 5);

The invoice will be charged immediately against the user’s credit card. The invoiceFor method also accepts an array as its third argument, allowing you to pass any options you wish to the underlying Stripe / Braintree charge creation:

$user->invoiceFor('One Time Fee', 500, [
    'custom-option' => $value,
]);

{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.

<a name=“invoices”></a>

4.8 Invoices

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

$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:

<table>
    @foreach ($invoices as $invoice)
        <tr>
            <td>{{ $invoice->date()->toFormattedDateString() }}</td>
            <td>{{ $invoice->total() }}</td>
            <td><a href="/user/invoice/{{ $invoice->id }}">Download</a></td>
        </tr>
    @endforeach
</table>

<a name=“generating-invoice-pdfs”></a>

4.8.1 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:

use Illuminate\Http\Request;

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

5 Blade Templates

<a name=“introduction”></a>

5.1 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.

<a name=“template-inheritance”></a>

5.2 Template Inheritance

<a name=“defining-a-layout”></a>

5.2.1 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:

<!-- Stored in resources/views/layouts/app.blade.php -->

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

        <div class="container">
            @yield('content')
        </div>
    </body>
</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.

<a name=“extending-a-layout”></a>

5.2.2 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:

<!-- Stored in resources/views/child.blade.php -->

@extends('layouts.app')

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

@section('sidebar')
    @@parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
@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.

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

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

<a name=“components-and-slots”></a>

5.3 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:

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    {{ $slot }}
</div>

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:

@component('alert')
    <strong>Whoops!</strong> 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:

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    <div class="alert-title">{{ $title }}</div>

    {{ $slot }}
</div>

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:

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

    You are not allowed to access this resource!
@endcomponent

5.3.0.1 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:

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

<a name=“displaying-data”></a>

5.4 Displaying Data

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

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

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

Hello, {{ $name }}.

Of course, 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:

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

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

5.4.0.1 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:

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.

5.4.0.2 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:

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

However, instead of manually calling json_encode, you may use the @json Blade directive:

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

<a name=“blade-and-javascript-frameworks”></a>

5.4.1 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:

<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.

5.4.1.1 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:

@verbatim
    <div class="container">
        Hello, {{ name }}.
    </div>
@endverbatim

<a name=“control-structures”></a>

5.5 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.

<a name=“if-statements”></a>

5.5.1 If Statements

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

@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:

@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:

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

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

5.5.1.1 Authentication Directives

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

@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:

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

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

5.5.1.2 Section Directives

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

@hasSection('navigation')
    <div class="pull-right">
        @yield('navigation')
    </div>

    <div class="clearfix"></div>
@endif

<a name=“switch-statements”></a>

5.5.2 Switch Statements

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

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

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

    @default
        Default case...
@endswitch

<a name=“loops”></a>

5.5.3 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:

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

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

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

@while (true)
    <p>I'm looping forever.</p>
@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:

@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:

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

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

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

<a name=“the-loop-variable”></a>

5.5.4 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:

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

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

    <p>This is user {{ $user->id }}</p>
@endforeach

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

@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 iteration 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->depth The nesting level of the current loop.
$loop->parent When in a nested loop, the parent’s loop variable.

<a name=“comments”></a>

5.5.5 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:

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

<a name=“php”></a>

5.5.6 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:

@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.

<a name=“including-sub-views”></a>

5.6 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:

<div>
    @include('shared.errors')

    <form>
        <!-- Form Contents -->
    </form>
</div>

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:

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

Of course, 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:

@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:

@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:

@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.

<a name=“rendering-views-for-collections”></a>

5.6.1 Rendering Views For Collections

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

@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.

@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.

<a name=“stacks”></a>

5.7 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:

@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:

<head>
    <!-- Head Contents -->

    @stack('scripts')
</head>

<a name=“service-injection”></a>

5.8 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:

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

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

<a name=“extending-blade”></a>

5.9 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:

<?php

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('datetime', function ($expression) {
            return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
        });
    }

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

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:

<?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.

<a name=“custom-if-statements”></a>

5.9.1 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:

use Illuminate\Support\Facades\Blade;

/**
 * Perform post-registration booting of 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:

@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

6 Broadcasting

<a name=“introduction”></a>

6.1 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.

<a name=“configuration”></a>

6.1.1 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, 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.

6.1.1.1 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.

6.1.1.2 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:

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

<a name=“driver-prerequisites”></a>

6.1.2 Driver Prerequisites

6.1.2.1 Pusher

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

composer require pusher/pusher-php-server "~3.0"

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

'options' => [
    'cluster' => 'eu',
    'encrypted' => true
],

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

import Echo from "laravel-echo"

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

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

6.1.2.2 Redis

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

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).

6.1.2.3 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’s head HTML element. When the Socket.IO server is started, it will automatically expose the client JavaScript library at a standard URL. For example, if you are running the Socket.IO server on the same domain as your web application, you may access the client library like so:

<script src="//{{ Request::getHost() }}:6001/socket.io/socket.io.js"></script>

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

import Echo from "laravel-echo"

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.

6.1.2.4 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.

<a name=“concept-overview”></a>

6.2 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 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.

<a name=“using-example-application”></a>

6.2.1 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 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:

event(new ShippingStatusUpdated($update));

6.2.1.1 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:

<?php

namespace App\Events;

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

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:

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

6.2.1.2 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:

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.

6.2.1.3 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:

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

<a name=“defining-broadcast-events”></a>

6.3 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:

<?php

namespace App\Events;

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

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.

<a name=“broadcast-name”></a>

6.3.1 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:

/**
 * 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:

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

<a name=“broadcast-data”></a>

6.3.2 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:

{
    "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:

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

<a name=“broadcast-queue”></a>

6.3.3 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:

/**
 * 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:

<?php

use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;

class ShippingStatusUpdated implements ShouldBroadcastNow
{
    //
}

<a name=“broadcast-conditions”></a>

6.3.4 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:

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

<a name=“authorizing-channels”></a>

6.4 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.

<a name=“defining-authorization-routes”></a>

6.4.1 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:

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:

Broadcast::routes($attributes);

<a name=“defining-authorization-callbacks”></a>

6.4.2 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:

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.

6.4.2.1 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:

use App\Order;

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

<a name=“broadcasting-events”></a>

6.5 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:

event(new ShippingStatusUpdated($update));

<a name=“only-to-others”></a>

6.5.1 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:

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:

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:

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.

6.5.1.1 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:

var socketId = Echo.socketId();

<a name=“receiving-broadcasts”></a>

6.6 Receiving Broadcasts

<a name=“installing-laravel-echo”></a>

6.6.1 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 broadcaster:

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/assets/js/bootstrap.js file that is included with the Laravel framework:

import Echo from "laravel-echo"

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

When creating an Echo instance that uses the pusher connector, you may also specify a cluster as well as whether the connection should be encrypted:

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-key',
    cluster: 'eu',
    encrypted: true
});

<a name=“listening-for-events”></a>

6.6.2 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:

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:

Echo.private('orders')
    .listen(...)
    .listen(...)
    .listen(...);

<a name=“leaving-a-channel”></a>

6.6.3 Leaving A Channel

To leave a channel, you may call the leave method on your Echo instance:

Echo.leave('orders');

<a name=“namespaces”></a>

6.6.4 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:

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-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:

Echo.channel('orders')
    .listen('.Namespace.Event.Class', (e) => {
        //
    });

<a name=“presence-channels”></a>

6.7 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.

<a name=“authorizing-presence-channels”></a>

6.7.1 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:

Broadcast::channel('chat.{roomId}', function ($user, $roomId) {
    if ($user->canJoinRoom($roomId)) {
        return ['id' => $user->id, 'name' => $user->name];
    }
});

<a name=“joining-presence-channels”></a>

6.7.2 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.

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.

<a name=“broadcasting-to-presence-channels”></a>

6.7.3 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:

/**
 * 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:

broadcast(new NewMessage($message));

broadcast(new NewMessage($message))->toOthers();

You may listen for the join event via Echo’s listen method:

Echo.join(`chat.${roomId}`)
    .here(...)
    .joining(...)
    .leaving(...)
    .listen('NewMessage', (e) => {
        //
    });

<a name=“client-events”></a>

6.8 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:

Echo.private('chat')
    .whisper('typing', {
        name: this.user.name
    });

To listen for client events, you may use the listenForWhisper method:

Echo.private('chat')
    .listenForWhisper('typing', (e) => {
        console.log(e.name);
    });

<a name=“notifications”></a>

6.9 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:

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.

7 Cache

<a name=“configuration”></a>

7.1 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.

<a name=“driver-prerequisites”></a>

7.1.1 Driver Prerequisites

7.1.1.1 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:

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.

7.1.1.2 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:

'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:

'memcached' => [
    [
        'host' => '/var/run/memcached/memcached.sock',
        'port' => 0,
        'weight' => 100
    ],
],

7.1.1.3 Redis

Before using a Redis cache with Laravel, you will need to either install the predis/predis package (~1.0) via Composer or install the PhpRedis PHP extension via PECL.

For more information on configuring Redis, consult its Laravel documentation page.

<a name=“cache-usage”></a>

7.2 Cache Usage

<a name=“obtaining-a-cache-instance”></a>

7.2.1 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:

<?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');

        //
    }
}

7.2.1.1 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:

$value = Cache::store('file')->get('foo');

Cache::store('redis')->put('bar', 'baz', 10);

<a name=“retrieving-items-from-the-cache”></a>

7.2.2 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:

$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:

$value = Cache::get('key', function () {
    return DB::table(...)->get();
});

7.2.2.1 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 or false:

if (Cache::has('key')) {
    //
}

7.2.2.2 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:

Cache::increment('key');
Cache::increment('key', $amount);
Cache::decrement('key');
Cache::decrement('key', $amount);

7.2.2.3 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:

$value = Cache::remember('users', $minutes, 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:

$value = Cache::rememberForever('users', function() {
    return DB::table('users')->get();
});

7.2.2.4 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:

$value = Cache::pull('key');

<a name=“storing-items-in-the-cache”></a>

7.2.3 Storing Items In The Cache

You may use the put method on the Cache facade to store items in the cache. When you place an item in the cache, you need to specify the number of minutes for which the value should be cached:

Cache::put('key', 'value', $minutes);

Instead of passing the number of minutes as an integer, you may also pass a DateTime instance representing the expiration time of the cached item:

$expiresAt = now()->addMinutes(10);

Cache::put('key', 'value', $expiresAt);

7.2.3.1 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:

Cache::add('key', 'value', $minutes);

7.2.3.2 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:

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.

<a name=“removing-items-from-the-cache”></a>

7.2.4 Removing Items From The Cache

You may remove items from the cache using the forget method:

Cache::forget('key');

You may clear the entire cache using the flush method:

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.

<a name=“the-cache-helper”></a>

7.2.5 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:

$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:

cache(['key' => 'value'], $minutes);

cache(['key' => 'value'], now()->addSeconds(10));

{tip} When testing call to the global cache function, you may use the Cache::shouldReceive method just as if you were testing a facade.

<a name=“cache-tags”></a>

7.3 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.

<a name=“storing-tagged-cache-items”></a>

7.3.1 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:

Cache::tags(['people', 'artists'])->put('John', $john, $minutes);

Cache::tags(['people', 'authors'])->put('Anne', $anne, $minutes);

<a name=“accessing-tagged-cache-items”></a>

7.3.2 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:

$john = Cache::tags(['people', 'artists'])->get('John');

$anne = Cache::tags(['people', 'authors'])->get('Anne');

<a name=“removing-tagged-cache-items”></a>

7.3.3 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:

Cache::tags(['people', 'authors'])->flush();

In contrast, this statement would remove only caches tagged with authors, so Anne would be removed, but not John:

Cache::tags('authors')->flush();

<a name=“adding-custom-cache-drivers”></a>

7.4 Adding Custom Cache Drivers

<a name=“writing-the-driver”></a>

7.4.1 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:

<?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, $minutes) {}
    public function putMany(array $values, $minutes);
    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.

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.

<a name=“registering-the-driver”></a>

7.4.2 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:

<?php

namespace App\Providers;

use App\Extensions\MongoStore;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;

class CacheServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Cache::extend('mongo', function ($app) {
            return Cache::repository(new MongoStore);
        });
    }

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

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.

<a name=“events”></a>

7.5 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:

/**
 * 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',
    ],
];

8 Collections

<a name=“introduction”></a>

8.1 Introduction

The Illuminate\Support\Collection class provides a fluent, convenient wrapper for working with arrays of data. For example, check out the following code. We’ll use the collect helper to create a new collection instance from the array, run the strtoupper function on each element, and then remove all empty elements:

$collection = collect(['taylor', 'abigail', null])->map(function ($name) {
    return strtoupper($name);
})
->reject(function ($name) {
    return empty($name);
});

As you can see, the Collection class allows you to chain its methods to perform fluent mapping and reducing of the underlying array. In general, collections are immutable, meaning every Collection method returns an entirely new Collection instance.

<a name=“creating-collections”></a>

8.1.1 Creating Collections

As mentioned above, the collect helper returns a new Illuminate\Support\Collection instance for the given array. So, creating a collection is as simple as:

$collection = collect([1, 2, 3]);

{tip} The results of Eloquent queries are always returned as Collection instances.

<a name=“extending-collections”></a>

8.1.2 Extending Collections

Collections are “macroable”, which allows you to add additional methods to the Collection class at run time. For example, the following code adds a toUpper method to the Collection class:

use Illuminate\Support\Str;

Collection::macro('toUpper', function () {
    return $this->map(function ($value) {
        return Str::upper($value);
    });
});

$collection = collect(['first', 'second']);

$upper = $collection->toUpper();

// ['FIRST', 'SECOND']

Typically, you should declare collection macros in a service provider.

<a name=“available-methods”></a>

8.2 Available Methods

For the remainder of this documentation, we’ll discuss each method available on the Collection class. Remember, all of these methods may be chained to fluently manipulating the underlying array. Furthermore, almost every method returns a new Collection instance, allowing you to preserve the original copy of the collection when necessary:

<style>
#collection-method-list > p {
column-count: 3; -moz-column-count: 3; -webkit-column-count: 3;
column-gap: 2em; -moz-column-gap: 2em; -webkit-column-gap: 2em;
}

#collection-method-list a {
    display: block;
}

</style>

<div id=“collection-method-list” markdown=“1”>

all
average
avg
chunk
collapse
combine
concat
contains
containsStrict
count
crossJoin
dd
diff
diffAssoc
diffKeys
dump
each
eachSpread
every
except
filter
first
firstWhere
flatMap
flatten
flip
forget
forPage
get
groupBy
has
implode
intersect
intersectByKeys
isEmpty
isNotEmpty
keyBy
keys
last
macro
make
map
mapInto
mapSpread
mapToGroups
mapWithKeys
max
median
merge
min
mode
nth
only
pad
partition
pipe
pluck
pop
prepend
pull
push
put
random
reduce
reject
reverse
search
shift
shuffle
slice
sort
sortBy
sortByDesc
splice
split
sum
take
tap
times
toArray
toJson
transform
union
unique
uniqueStrict
unless
unwrap
values
when
where
whereStrict
whereIn
whereInStrict
whereNotIn
whereNotInStrict
wrap
zip

</div>

<a name=“method-listing”></a>

8.3 Method Listing

<style>
#collection-method code {
font-size: 14px;
}

#collection-method:not(.first-collection-method) {
    margin-top: 50px;
}

</style>

<a name=“method-all”></a>

8.3.0.1 all() {#collection-method .first-collection-method}

The all method returns the underlying array represented by the collection:

collect([1, 2, 3])->all();

// [1, 2, 3]

<a name=“method-average”></a>

8.3.0.2 average() {#collection-method}

Alias for the avg method.

<a name=“method-avg”></a>

8.3.0.3 avg() {#collection-method}

The avg method returns the average value of a given key:

$average = collect([['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40]])->avg('foo');

// 20

$average = collect([1, 1, 2, 4])->avg();

// 2

<a name=“method-chunk”></a>

8.3.0.4 chunk() {#collection-method}

The chunk method breaks the collection into multiple, smaller collections of a given size:

$collection = collect([1, 2, 3, 4, 5, 6, 7]);

$chunks = $collection->chunk(4);

$chunks->toArray();

// [[1, 2, 3, 4], [5, 6, 7]]

This method is especially useful in views when working with a grid system such as Bootstrap. Imagine you have a collection of Eloquent models you want to display in a grid:

@foreach ($products->chunk(3) as $chunk)
    <div class="row">
        @foreach ($chunk as $product)
            <div class="col-xs-4">{{ $product->name }}</div>
        @endforeach
    </div>
@endforeach

<a name=“method-collapse”></a>

8.3.0.5 collapse() {#collection-method}

The collapse method collapses a collection of arrays into a single, flat collection:

$collection = collect([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);

$collapsed = $collection->collapse();

$collapsed->all();

// [1, 2, 3, 4, 5, 6, 7, 8, 9]

<a name=“method-combine”></a>

8.3.0.6 combine() {#collection-method}

The combine method combines the keys of the collection with the values of another array or collection:

$collection = collect(['name', 'age']);

$combined = $collection->combine(['George', 29]);

$combined->all();

// ['name' => 'George', 'age' => 29]

<a name=“method-concat”></a>

8.3.0.7 concat() {#collection-method}

The concat method appends the given array or collection values onto the end of the collection:

$collection = collect(['John Doe']);

$concatenated = $collection->concat(['Jane Doe'])->concat(['name' => 'Johnny Doe']);

$concatenated->all();

// ['John Doe', 'Jane Doe', 'Johnny Doe']

<a name=“method-contains”></a>

8.3.0.8 contains() {#collection-method}

The contains method determines whether the collection contains a given item:

$collection = collect(['name' => 'Desk', 'price' => 100]);

$collection->contains('Desk');

// true

$collection->contains('New York');

// false

You may also pass a key / value pair to the contains method, which will determine if the given pair exists in the collection:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
]);

$collection->contains('product', 'Bookcase');

// false

Finally, you may also pass a callback to the contains method to perform your own truth test:

$collection = collect([1, 2, 3, 4, 5]);

$collection->contains(function ($value, $key) {
    return $value > 5;
});

// false

The contains method uses “loose” comparisons when checking item values, meaning a string with an integer value will be considered equal to an integer of the same value. Use the containsStrict method to filter using “strict” comparisons.

<a name=“method-containsstrict”></a>

8.3.0.9 containsStrict() {#collection-method}

This method has the same signature as the contains method; however, all values are compared using “strict” comparisons.

<a name=“method-count”></a>

8.3.0.10 count() {#collection-method}

The count method returns the total number of items in the collection:

$collection = collect([1, 2, 3, 4]);

$collection->count();

// 4

<a name=“method-crossjoin”></a>

8.3.0.11 crossJoin() {#collection-method}

The crossJoin method cross joins the collection’s values among the given arrays or collections, returning a Cartesian product with all possible permutations:

$collection = collect([1, 2]);

$matrix = $collection->crossJoin(['a', 'b']);

$matrix->all();

/*
    [
        [1, 'a'],
        [1, 'b'],
        [2, 'a'],
        [2, 'b'],
    ]
*/

$collection = collect([1, 2]);

$matrix = $collection->crossJoin(['a', 'b'], ['I', 'II']);

$matrix->all();

/*
    [
        [1, 'a', 'I'],
        [1, 'a', 'II'],
        [1, 'b', 'I'],
        [1, 'b', 'II'],
        [2, 'a', 'I'],
        [2, 'a', 'II'],
        [2, 'b', 'I'],
        [2, 'b', 'II'],
    ]
*/

<a name=“method-dd”></a>

8.3.0.12 dd() {#collection-method}

The dd method dumps the collection’s items and ends execution of the script:

$collection = collect(['John Doe', 'Jane Doe']);

$collection->dd();

/*
    Collection {
        #items: array:2 [
            0 => "John Doe"
            1 => "Jane Doe"
        ]
    }
*/

If you do not want to stop executing the script, use the dump method instead.

<a name=“method-diff”></a>

8.3.0.13 diff() {#collection-method}

The diff method compares the collection against another collection or a plain PHP array based on its values. This method will return the values in the original collection that are not present in the given collection:

$collection = collect([1, 2, 3, 4, 5]);

$diff = $collection->diff([2, 4, 6, 8]);

$diff->all();

// [1, 3, 5]

<a name=“method-diffassoc”></a>

8.3.0.14 diffAssoc() {#collection-method}

The diffAssoc method compares the collection against another collection or a plain PHP array based on its keys and values. This method will return the key / value pairs in the original collection that are not present in the given collection:

$collection = collect([
    'color' => 'orange',
    'type' => 'fruit',
    'remain' => 6
]);

$diff = $collection->diffAssoc([
    'color' => 'yellow',
    'type' => 'fruit',
    'remain' => 3,
    'used' => 6
]);

$diff->all();

// ['color' => 'orange', 'remain' => 6]

<a name=“method-diffkeys”></a>

8.3.0.15 diffKeys() {#collection-method}

The diffKeys method compares the collection against another collection or a plain PHP array based on its keys. This method will return the key / value pairs in the original collection that are not present in the given collection:

$collection = collect([
    'one' => 10,
    'two' => 20,
    'three' => 30,
    'four' => 40,
    'five' => 50,
]);

$diff = $collection->diffKeys([
    'two' => 2,
    'four' => 4,
    'six' => 6,
    'eight' => 8,
]);

$diff->all();

// ['one' => 10, 'three' => 30, 'five' => 50]

<a name=“method-dump”></a>

8.3.0.16 dump() {#collection-method}

The dump method dumps the collection’s items:

$collection = collect(['John Doe', 'Jane Doe']);

$collection->dump();

/*
    Collection {
        #items: array:2 [
            0 => "John Doe"
            1 => "Jane Doe"
        ]
    }
*/

If you want to stop executing the script after dumping the collection, use the dd method instead.

<a name=“method-each”></a>

8.3.0.17 each() {#collection-method}

The each method iterates over the items in the collection and passes each item to a callback:

$collection = $collection->each(function ($item, $key) {
    //
});

If you would like to stop iterating through the items, you may return false from your callback:

$collection = $collection->each(function ($item, $key) {
    if (/* some condition */) {
        return false;
    }
});

<a name=“method-eachspread”></a>

8.3.0.18 eachSpread() {#collection-method}

The eachSpread method iterates over the collection’s items, passing each nested item value into the given callback:

$collection = collect([['John Doe', 35], ['Jane Doe', 33]]);

$collection->eachSpread(function ($name, $age) {
    //
});

You may stop iterating through the items by returning false from the callback:

$collection->eachSpread(function ($name, $age) {
    return false;
});

<a name=“method-every”></a>

8.3.0.19 every() {#collection-method}

The every method may be used to verify that all elements of a collection pass a given truth test:

collect([1, 2, 3, 4])->every(function ($value, $key) {
    return $value > 2;
});

// false

<a name=“method-except”></a>

8.3.0.20 except() {#collection-method}

The except method returns all items in the collection except for those with the specified keys:

$collection = collect(['product_id' => 1, 'price' => 100, 'discount' => false]);

$filtered = $collection->except(['price', 'discount']);

$filtered->all();

// ['product_id' => 1]

For the inverse of except, see the only method.

<a name=“method-filter”></a>

8.3.0.21 filter() {#collection-method}

The filter method filters the collection using the given callback, keeping only those items that pass a given truth test:

$collection = collect([1, 2, 3, 4]);

$filtered = $collection->filter(function ($value, $key) {
    return $value > 2;
});

$filtered->all();

// [3, 4]

If no callback is supplied, all entries of the collection that are equivalent to false will be removed:

$collection = collect([1, 2, 3, null, false, '', 0, []]);

$collection->filter()->all();

// [1, 2, 3]

For the inverse of filter, see the reject method.

<a name=“method-first”></a>

8.3.0.22 first() {#collection-method}

The first method returns the first element in the collection that passes a given truth test:

collect([1, 2, 3, 4])->first(function ($value, $key) {
    return $value > 2;
});

// 3

You may also call the first method with no arguments to get the first element in the collection. If the collection is empty, null is returned:

collect([1, 2, 3, 4])->first();

// 1

<a name=“method-first-where”></a>

8.3.0.23 firstWhere() {#collection-method}

The firstWhere method returns the first element in the collection with the given key / value pair:

$collection = collect([
    ['name' => 'Regena', 'age' => 12],
    ['name' => 'Linda', 'age' => 14],
    ['name' => 'Diego', 'age' => 23],
    ['name' => 'Linda', 'age' => 84],
]);

$collection->firstWhere('name', 'Linda');

// ['name' => 'Linda', 'age' => 14]

You may also call the firstWhere method with an operator:

$collection->firstWhere('age', '>=', 18);

// ['name' => 'Diego', 'age' => 23]

<a name=“method-flatmap”></a>

8.3.0.24 flatMap() {#collection-method}

The flatMap method iterates through the collection and passes each value to the given callback. The callback is free to modify the item and return it, thus forming a new collection of modified items. Then, the array is flattened by a level:

$collection = collect([
    ['name' => 'Sally'],
    ['school' => 'Arkansas'],
    ['age' => 28]
]);

$flattened = $collection->flatMap(function ($values) {
    return array_map('strtoupper', $values);
});

$flattened->all();

// ['name' => 'SALLY', 'school' => 'ARKANSAS', 'age' => '28'];

<a name=“method-flatten”></a>

8.3.0.25 flatten() {#collection-method}

The flatten method flattens a multi-dimensional collection into a single dimension:

$collection = collect(['name' => 'taylor', 'languages' => ['php', 'javascript']]);

$flattened = $collection->flatten();

$flattened->all();

// ['taylor', 'php', 'javascript'];

You may optionally pass the function a “depth” argument:

$collection = collect([
    'Apple' => [
        ['name' => 'iPhone 6S', 'brand' => 'Apple'],
    ],
    'Samsung' => [
        ['name' => 'Galaxy S7', 'brand' => 'Samsung']
    ],
]);

$products = $collection->flatten(1);

$products->values()->all();

/*
    [
        ['name' => 'iPhone 6S', 'brand' => 'Apple'],
        ['name' => 'Galaxy S7', 'brand' => 'Samsung'],
    ]
*/

In this example, calling flatten without providing the depth would have also flattened the nested arrays, resulting in ['iPhone 6S', 'Apple', 'Galaxy S7', 'Samsung']. Providing a depth allows you to restrict the levels of nested arrays that will be flattened.

<a name=“method-flip”></a>

8.3.0.26 flip() {#collection-method}

The flip method swaps the collection’s keys with their corresponding values:

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$flipped = $collection->flip();

$flipped->all();

// ['taylor' => 'name', 'laravel' => 'framework']

<a name=“method-forget”></a>

8.3.0.27 forget() {#collection-method}

The forget method removes an item from the collection by its key:

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$collection->forget('name');

$collection->all();

// ['framework' => 'laravel']

{note} Unlike most other collection methods, forget does not return a new modified collection; it modifies the collection it is called on.

<a name=“method-forpage”></a>

8.3.0.28 forPage() {#collection-method}

The forPage method returns a new collection containing the items that would be present on a given page number. The method accepts the page number as its first argument and the number of items to show per page as its second argument:

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);

$chunk = $collection->forPage(2, 3);

$chunk->all();

// [4, 5, 6]

<a name=“method-get”></a>

8.3.0.29 get() {#collection-method}

The get method returns the item at a given key. If the key does not exist, null is returned:

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$value = $collection->get('name');

// taylor

You may optionally pass a default value as the second argument:

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$value = $collection->get('foo', 'default-value');

// default-value

You may even pass a callback as the default value. The result of the callback will be returned if the specified key does not exist:

$collection->get('email', function () {
    return 'default-value';
});

// default-value

<a name=“method-groupby”></a>

8.3.0.30 groupBy() {#collection-method}

The groupBy method groups the collection’s items by a given key:

$collection = collect([
    ['account_id' => 'account-x10', 'product' => 'Chair'],
    ['account_id' => 'account-x10', 'product' => 'Bookcase'],
    ['account_id' => 'account-x11', 'product' => 'Desk'],
]);

$grouped = $collection->groupBy('account_id');

$grouped->toArray();

/*
    [
        'account-x10' => [
            ['account_id' => 'account-x10', 'product' => 'Chair'],
            ['account_id' => 'account-x10', 'product' => 'Bookcase'],
        ],
        'account-x11' => [
            ['account_id' => 'account-x11', 'product' => 'Desk'],
        ],
    ]
*/

In addition to passing a string key, you may also pass a callback. The callback should return the value you wish to key the group by:

$grouped = $collection->groupBy(function ($item, $key) {
    return substr($item['account_id'], -3);
});

$grouped->toArray();

/*
    [
        'x10' => [
            ['account_id' => 'account-x10', 'product' => 'Chair'],
            ['account_id' => 'account-x10', 'product' => 'Bookcase'],
        ],
        'x11' => [
            ['account_id' => 'account-x11', 'product' => 'Desk'],
        ],
    ]
*/

Multiple grouping criteria may be passed as an array. Each array element will applied for the corresponding level within a multi-dimensional array:

$data = new Collection([
    10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
    20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
    30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']],
    40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']],
]);

$result = $data->groupBy([
    'skill',
    function ($item) {
        return $item['roles'];
    },
], $preserveKeys = true);

/*
[
    1 => [
        'Role_1' => [
            10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
            20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
        ],
        'Role_2' => [
            20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
        ],
        'Role_3' => [
            10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
        ],
    ],
    2 => [
        'Role_1' => [
            30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']],
        ],
        'Role_2' => [
            40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']],
        ],
    ],
];
*/

<a name=“method-has”></a>

8.3.0.31 has() {#collection-method}

The has method determines if a given key exists in the collection:

$collection = collect(['account_id' => 1, 'product' => 'Desk']);

$collection->has('product');

// true

<a name=“method-implode”></a>

8.3.0.32 implode() {#collection-method}

The implode method joins the items in a collection. Its arguments depend on the type of items in the collection. If the collection contains arrays or objects, you should pass the key of the attributes you wish to join, and the “glue” string you wish to place between the values:

$collection = collect([
    ['account_id' => 1, 'product' => 'Desk'],
    ['account_id' => 2, 'product' => 'Chair'],
]);

$collection->implode('product', ', ');

// Desk, Chair

If the collection contains simple strings or numeric values, pass the “glue” as the only argument to the method:

collect([1, 2, 3, 4, 5])->implode('-');

// '1-2-3-4-5'

<a name=“method-intersect”></a>

8.3.0.33 intersect() {#collection-method}

The intersect method removes any values from the original collection that are not present in the given array or collection. The resulting collection will preserve the original collection’s keys:

$collection = collect(['Desk', 'Sofa', 'Chair']);

$intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']);

$intersect->all();

// [0 => 'Desk', 2 => 'Chair']

<a name=“method-intersectbykeys”></a>

8.3.0.34 intersectByKeys() {#collection-method}

The intersectByKeys method removes any keys from the original collection that are not present in the given array or collection:

$collection = collect([
    'serial' => 'UX301', 'type' => 'screen', 'year' => 2009
]);

$intersect = $collection->intersectByKeys([
    'reference' => 'UX404', 'type' => 'tab', 'year' => 2011
]);

$intersect->all();

// ['type' => 'screen', 'year' => 2009]

<a name=“method-isempty”></a>

8.3.0.35 isEmpty() {#collection-method}

The isEmpty method returns true if the collection is empty; otherwise, false is returned:

collect([])->isEmpty();

// true

<a name=“method-isnotempty”></a>

8.3.0.36 isNotEmpty() {#collection-method}

The isNotEmpty method returns true if the collection is not empty; otherwise, false is returned:

collect([])->isNotEmpty();

// false

<a name=“method-keyby”></a>

8.3.0.37 keyBy() {#collection-method}

The keyBy method keys the collection by the given key. If multiple items have the same key, only the last one will appear in the new collection:

$collection = collect([
    ['product_id' => 'prod-100', 'name' => 'Desk'],
    ['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$keyed = $collection->keyBy('product_id');

$keyed->all();

/*
    [
        'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
        'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
    ]
*/

You may also pass a callback to the method. The callback should return the value to key the collection by:

$keyed = $collection->keyBy(function ($item) {
    return strtoupper($item['product_id']);
});

$keyed->all();

/*
    [
        'PROD-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
        'PROD-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
    ]
*/

<a name=“method-keys”></a>

8.3.0.38 keys() {#collection-method}

The keys method returns all of the collection’s keys:

$collection = collect([
    'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
    'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$keys = $collection->keys();

$keys->all();

// ['prod-100', 'prod-200']

<a name=“method-last”></a>

8.3.0.39 last() {#collection-method}

The last method returns the last element in the collection that passes a given truth test:

collect([1, 2, 3, 4])->last(function ($value, $key) {
    return $value < 3;
});

// 2

You may also call the last method with no arguments to get the last element in the collection. If the collection is empty, null is returned:

collect([1, 2, 3, 4])->last();

// 4

<a name=“method-macro”></a>

8.3.0.40 macro() {#collection-method}

The static macro method allows you to add methods to the Collection class at run time. Refer to the documentation on extending collections for more information.

<a name=“method-make”></a>

8.3.0.41 make() {#collection-method}

The static make method creates a new collection instance. See the Creating Collections section.

<a name=“method-map”></a>

8.3.0.42 map() {#collection-method}

The map method iterates through the collection and passes each value to the given callback. The callback is free to modify the item and return it, thus forming a new collection of modified items:

$collection = collect([1, 2, 3, 4, 5]);

$multiplied = $collection->map(function ($item, $key) {
    return $item * 2;
});

$multiplied->all();

// [2, 4, 6, 8, 10]

{note} Like most other collection methods, map returns a new collection instance; it does not modify the collection it is called on. If you want to transform the original collection, use the transform method.

<a name=“method-mapinto”></a>

8.3.0.43 mapInto() {#collection-method}

The mapInto() method iterates over the collection, creating a new instance of the given class by passing the value into the constructor:

class Currency
{
    /**
     * Create a new currency instance.
     *
     * @param  string  $code
     * @return void
     */
    function __construct(string $code)
    {
        $this->code = $code;
    }
}

$collection = collect(['USD', 'EUR', 'GBP']);

$currencies = $collection->mapInto(Currency::class);

$currencies->all();

// [Currency('USD'), Currency('EUR'), Currency('GBP')]

<a name=“method-mapspread”></a>

8.3.0.44 mapSpread() {#collection-method}

The mapSpread method iterates over the collection’s items, passing each nested item value into the given callback. The callback is free to modify the item and return it, thus forming a new collection of modified items:

$collection = collect([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

$chunks = $collection->chunk(2);

$sequence = $chunks->mapSpread(function ($odd, $even) {
    return $odd + $even;
});

$sequence->all();

// [1, 5, 9, 13, 17]

<a name=“method-maptogroups”></a>

8.3.0.45 mapToGroups() {#collection-method}

The mapToGroups method groups the collection’s items by the given callback. The callback should return an associative array containing a single key / value pair, thus forming a new collection of grouped values:

$collection = collect([
    [
        'name' => 'John Doe',
        'department' => 'Sales',
    ],
    [
        'name' => 'Jane Doe',
        'department' => 'Sales',
    ],
    [
        'name' => 'Johnny Doe',
        'department' => 'Marketing',
    ]
]);

$grouped = $collection->mapToGroups(function ($item, $key) {
    return [$item['department'] => $item['name']];
});

$grouped->toArray();

/*
    [
        'Sales' => ['John Doe', 'Jane Doe'],
        'Marketing' => ['Johhny Doe'],
    ]
*/

$grouped->get('Sales')->all();

// ['John Doe', 'Jane Doe']

<a name=“method-mapwithkeys”></a>

8.3.0.46 mapWithKeys() {#collection-method}

The mapWithKeys method iterates through the collection and passes each value to the given callback. The callback should return an associative array containing a single key / value pair:

$collection = collect([
    [
        'name' => 'John',
        'department' => 'Sales',
        'email' => 'john@example.com'
    ],
    [
        'name' => 'Jane',
        'department' => 'Marketing',
        'email' => 'jane@example.com'
    ]
]);

$keyed = $collection->mapWithKeys(function ($item) {
    return [$item['email'] => $item['name']];
});

$keyed->all();

/*
    [
        'john@example.com' => 'John',
        'jane@example.com' => 'Jane',
    ]
*/

<a name=“method-max”></a>

8.3.0.47 max() {#collection-method}

The max method returns the maximum value of a given key:

$max = collect([['foo' => 10], ['foo' => 20]])->max('foo');

// 20

$max = collect([1, 2, 3, 4, 5])->max();

// 5

<a name=“method-median”></a>

8.3.0.48 median() {#collection-method}

The median method returns the median value of a given key:

$median = collect([['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40]])->median('foo');

// 15

$median = collect([1, 1, 2, 4])->median();

// 1.5

<a name=“method-merge”></a>

8.3.0.49 merge() {#collection-method}

The merge method merges the given array or collection with the original collection. If a string key in the given items matches a string key in the original collection, the given items’s value will overwrite the value in the original collection:

$collection = collect(['product_id' => 1, 'price' => 100]);

$merged = $collection->merge(['price' => 200, 'discount' => false]);

$merged->all();

// ['product_id' => 1, 'price' => 200, 'discount' => false]

If the given items’s keys are numeric, the values will be appended to the end of the collection:

$collection = collect(['Desk', 'Chair']);

$merged = $collection->merge(['Bookcase', 'Door']);

$merged->all();

// ['Desk', 'Chair', 'Bookcase', 'Door']

<a name=“method-min”></a>

8.3.0.50 min() {#collection-method}

The min method returns the minimum value of a given key:

$min = collect([['foo' => 10], ['foo' => 20]])->min('foo');

// 10

$min = collect([1, 2, 3, 4, 5])->min();

// 1

<a name=“method-mode”></a>

8.3.0.51 mode() {#collection-method}

The mode method returns the mode value of a given key:

$mode = collect([['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40]])->mode('foo');

// [10]

$mode = collect([1, 1, 2, 4])->mode();

// [1]

<a name=“method-nth”></a>

8.3.0.52 nth() {#collection-method}

The nth method creates a new collection consisting of every n-th element:

$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']);

$collection->nth(4);

// ['a', 'e']

You may optionally pass an offset as the second argument:

$collection->nth(4, 1);

// ['b', 'f']

<a name=“method-only”></a>

8.3.0.53 only() {#collection-method}

The only method returns the items in the collection with the specified keys:

$collection = collect(['product_id' => 1, 'name' => 'Desk', 'price' => 100, 'discount' => false]);

$filtered = $collection->only(['product_id', 'name']);

$filtered->all();

// ['product_id' => 1, 'name' => 'Desk']

For the inverse of only, see the except method.

<a name=“method-pad”></a>

8.3.0.54 pad() {#collection-method}

The pad method will fill the array with the given value until the array reaches the specified size. This method behaves like the array_pad PHP function.

To pad to the left, you should specify a negative size. No padding will take place if the absolute value of the given size is less than or equal to the length of the array:

$collection = collect(['A', 'B', 'C']);

$filtered = $collection->pad(5, 0);

$filtered->all();

// ['A', 'B', 'C', 0, 0]

$filtered = $collection->pad(-5, 0);

$filtered->all();

// [0, 0, 'A', 'B', 'C']

<a name=“method-partition”></a>

8.3.0.55 partition() {#collection-method}

The partition method may be combined with the list PHP function to separate elements that pass a given truth test from those that do not:

$collection = collect([1, 2, 3, 4, 5, 6]);

list($underThree, $aboveThree) = $collection->partition(function ($i) {
    return $i < 3;
});

<a name=“method-pipe”></a>

8.3.0.56 pipe() {#collection-method}

The pipe method passes the collection to the given callback and returns the result:

$collection = collect([1, 2, 3]);

$piped = $collection->pipe(function ($collection) {
    return $collection->sum();
});

// 6

<a name=“method-pluck”></a>

8.3.0.57 pluck() {#collection-method}

The pluck method retrieves all of the values for a given key:

$collection = collect([
    ['product_id' => 'prod-100', 'name' => 'Desk'],
    ['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$plucked = $collection->pluck('name');

$plucked->all();

// ['Desk', 'Chair']

You may also specify how you wish the resulting collection to be keyed:

$plucked = $collection->pluck('name', 'product_id');

$plucked->all();

// ['prod-100' => 'Desk', 'prod-200' => 'Chair']

<a name=“method-pop”></a>

8.3.0.58 pop() {#collection-method}

The pop method removes and returns the last item from the collection:

$collection = collect([1, 2, 3, 4, 5]);

$collection->pop();

// 5

$collection->all();

// [1, 2, 3, 4]

<a name=“method-prepend”></a>

8.3.0.59 prepend() {#collection-method}

The prepend method adds an item to the beginning of the collection:

$collection = collect([1, 2, 3, 4, 5]);

$collection->prepend(0);

$collection->all();

// [0, 1, 2, 3, 4, 5]

You may also pass a second argument to set the key of the prepended item:

$collection = collect(['one' => 1, 'two' => 2]);

$collection->prepend(0, 'zero');

$collection->all();

// ['zero' => 0, 'one' => 1, 'two' => 2]

<a name=“method-pull”></a>

8.3.0.60 pull() {#collection-method}

The pull method removes and returns an item from the collection by its key:

$collection = collect(['product_id' => 'prod-100', 'name' => 'Desk']);

$collection->pull('name');

// 'Desk'

$collection->all();

// ['product_id' => 'prod-100']

<a name=“method-push”></a>

8.3.0.61 push() {#collection-method}

The push method appends an item to the end of the collection:

$collection = collect([1, 2, 3, 4]);

$collection->push(5);

$collection->all();

// [1, 2, 3, 4, 5]

<a name=“method-put”></a>

8.3.0.62 put() {#collection-method}

The put method sets the given key and value in the collection:

$collection = collect(['product_id' => 1, 'name' => 'Desk']);

$collection->put('price', 100);

$collection->all();

// ['product_id' => 1, 'name' => 'Desk', 'price' => 100]

<a name=“method-random”></a>

8.3.0.63 random() {#collection-method}

The random method returns a random item from the collection:

$collection = collect([1, 2, 3, 4, 5]);

$collection->random();

// 4 - (retrieved randomly)

You may optionally pass an integer to random to specify how many items you would like to randomly retrieve. A collection of items is always returned when explicitly passing the number of items you wish to receive:

$random = $collection->random(3);

$random->all();

// [2, 4, 5] - (retrieved randomly)

<a name=“method-reduce”></a>

8.3.0.64 reduce() {#collection-method}

The reduce method reduces the collection to a single value, passing the result of each iteration into the subsequent iteration:

$collection = collect([1, 2, 3]);

$total = $collection->reduce(function ($carry, $item) {
    return $carry + $item;
});

// 6

The value for $carry on the first iteration is null; however, you may specify its initial value by passing a second argument to reduce:

$collection->reduce(function ($carry, $item) {
    return $carry + $item;
}, 4);

// 10

<a name=“method-reject”></a>

8.3.0.65 reject() {#collection-method}

The reject method filters the collection using the given callback. The callback should return true if the item should be removed from the resulting collection:

$collection = collect([1, 2, 3, 4]);

$filtered = $collection->reject(function ($value, $key) {
    return $value > 2;
});

$filtered->all();

// [1, 2]

For the inverse of the reject method, see the filter method.

<a name=“method-reverse”></a>

8.3.0.66 reverse() {#collection-method}

The reverse method reverses the order of the collection’s items, preserving the original keys:

$collection = collect(['a', 'b', 'c', 'd', 'e']);

$reversed = $collection->reverse();

$reversed->all();

/*
    [
        4 => 'e',
        3 => 'd',
        2 => 'c',
        1 => 'b',
        0 => 'a',
    ]
*/

<a name=“method-search”></a>

8.3.0.67 search() {#collection-method}

The search method searches the collection for the given value and returns its key if found. If the item is not found, false is returned.

$collection = collect([2, 4, 6, 8]);

$collection->search(4);

// 1

The search is done using a “loose” comparison, meaning a string with an integer value will be considered equal to an integer of the same value. To use “strict” comparison, pass true as the second argument to the method:

$collection->search('4', true);

// false

Alternatively, you may pass in your own callback to search for the first item that passes your truth test:

$collection->search(function ($item, $key) {
    return $item > 5;
});

// 2

<a name=“method-shift”></a>

8.3.0.68 shift() {#collection-method}

The shift method removes and returns the first item from the collection:

$collection = collect([1, 2, 3, 4, 5]);

$collection->shift();

// 1

$collection->all();

// [2, 3, 4, 5]

<a name=“method-shuffle”></a>

8.3.0.69 shuffle() {#collection-method}

The shuffle method randomly shuffles the items in the collection:

$collection = collect([1, 2, 3, 4, 5]);

$shuffled = $collection->shuffle();

$shuffled->all();

// [3, 2, 5, 1, 4] - (generated randomly)

<a name=“method-slice”></a>

8.3.0.70 slice() {#collection-method}

The slice method returns a slice of the collection starting at the given index:

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

$slice = $collection->slice(4);

$slice->all();

// [5, 6, 7, 8, 9, 10]

If you would like to limit the size of the returned slice, pass the desired size as the second argument to the method:

$slice = $collection->slice(4, 2);

$slice->all();

// [5, 6]

The returned slice will preserve keys by default. If you do not wish to preserve the original keys, you can use the values method to reindex them.

<a name=“method-sort”></a>

8.3.0.71 sort() {#collection-method}

The sort method sorts the collection. The sorted collection keeps the original array keys, so in this example we’ll use the values method to reset the keys to consecutively numbered indexes:

$collection = collect([5, 3, 1, 2, 4]);

$sorted = $collection->sort();

$sorted->values()->all();

// [1, 2, 3, 4, 5]

If your sorting needs are more advanced, you may pass a callback to sort with your own algorithm. Refer to the PHP documentation on uasort, which is what the collection’s sort method calls under the hood.

{tip} If you need to sort a collection of nested arrays or objects, see the sortBy and sortByDesc methods.

<a name=“method-sortby”></a>

8.3.0.72 sortBy() {#collection-method}

The sortBy method sorts the collection by the given key. The sorted collection keeps the original array keys, so in this example we’ll use the values method to reset the keys to consecutively numbered indexes:

$collection = collect([
    ['name' => 'Desk', 'price' => 200],
    ['name' => 'Chair', 'price' => 100],
    ['name' => 'Bookcase', 'price' => 150],
]);

$sorted = $collection->sortBy('price');

$sorted->values()->all();

/*
    [
        ['name' => 'Chair', 'price' => 100],
        ['name' => 'Bookcase', 'price' => 150],
        ['name' => 'Desk', 'price' => 200],
    ]
*/

You can also pass your own callback to determine how to sort the collection values:

$collection = collect([
    ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
    ['name' => 'Chair', 'colors' => ['Black']],
    ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);

$sorted = $collection->sortBy(function ($product, $key) {
    return count($product['colors']);
});

$sorted->values()->all();

/*
    [
        ['name' => 'Chair', 'colors' => ['Black']],
        ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
        ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
    ]
*/

<a name=“method-sortbydesc”></a>

8.3.0.73 sortByDesc() {#collection-method}

This method has the same signature as the sortBy method, but will sort the collection in the opposite order.

<a name=“method-splice”></a>

8.3.0.74 splice() {#collection-method}

The splice method removes and returns a slice of items starting at the specified index:

$collection = collect([1, 2, 3, 4, 5]);

$chunk = $collection->splice(2);

$chunk->all();

// [3, 4, 5]

$collection->all();

// [1, 2]

You may pass a second argument to limit the size of the resulting chunk:

$collection = collect([1, 2, 3, 4, 5]);

$chunk = $collection->splice(2, 1);

$chunk->all();

// [3]

$collection->all();

// [1, 2, 4, 5]

In addition, you can pass a third argument containing the new items to replace the items removed from the collection:

$collection = collect([1, 2, 3, 4, 5]);

$chunk = $collection->splice(2, 1, [10, 11]);

$chunk->all();

// [3]

$collection->all();

// [1, 2, 10, 11, 4, 5]

<a name=“method-split”></a>

8.3.0.75 split() {#collection-method}

The split method breaks a collection into the given number of groups:

$collection = collect([1, 2, 3, 4, 5]);

$groups = $collection->split(3);

$groups->toArray();

// [[1, 2], [3, 4], [5]]

<a name=“method-sum”></a>

8.3.0.76 sum() {#collection-method}

The sum method returns the sum of all items in the collection:

collect([1, 2, 3, 4, 5])->sum();

// 15

If the collection contains nested arrays or objects, you should pass a key to use for determining which values to sum:

$collection = collect([
    ['name' => 'JavaScript: The Good Parts', 'pages' => 176],
    ['name' => 'JavaScript: The Definitive Guide', 'pages' => 1096],
]);

$collection->sum('pages');

// 1272

In addition, you may pass your own callback to determine which values of the collection to sum:

$collection = collect([
    ['name' => 'Chair', 'colors' => ['Black']],
    ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
    ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);

$collection->sum(function ($product) {
    return count($product['colors']);
});

// 6

<a name=“method-take”></a>

8.3.0.77 take() {#collection-method}

The take method returns a new collection with the specified number of items:

$collection = collect([0, 1, 2, 3, 4, 5]);

$chunk = $collection->take(3);

$chunk->all();

// [0, 1, 2]

You may also pass a negative integer to take the specified amount of items from the end of the collection:

$collection = collect([0, 1, 2, 3, 4, 5]);

$chunk = $collection->take(-2);

$chunk->all();

// [4, 5]

<a name=“method-tap”></a>

8.3.0.78 tap() {#collection-method}

The tap method passes the collection to the given callback, allowing you to “tap” into the collection at a specific point and do something with the items while not affecting the collection itself:

collect([2, 4, 3, 1, 5])
    ->sort()
    ->tap(function ($collection) {
        Log::debug('Values after sorting', $collection->values()->toArray());
    })
    ->shift();

// 1

<a name=“method-times”></a>

8.3.0.79 times() {#collection-method}

The static times method creates a new collection by invoking the callback a given amount of times:

$collection = Collection::times(10, function ($number) {
    return $number * 9;
});

$collection->all();

// [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]

This method can be useful when combined with factories to create Eloquent models:

$categories = Collection::times(3, function ($number) {
    return factory(Category::class)->create(['name' => 'Category #'.$number]);
});

$categories->all();

/*
    [
        ['id' => 1, 'name' => 'Category #1'],
        ['id' => 2, 'name' => 'Category #2'],
        ['id' => 3, 'name' => 'Category #3'],
    ]
*/

<a name=“method-toarray”></a>

8.3.0.80 toArray() {#collection-method}

The toArray method converts the collection into a plain PHP array. If the collection’s values are Eloquent models, the models will also be converted to arrays:

$collection = collect(['name' => 'Desk', 'price' => 200]);

$collection->toArray();

/*
    [
        ['name' => 'Desk', 'price' => 200],
    ]
*/

{note} toArray also converts all of the collection’s nested objects to an array. If you want to get the raw underlying array, use the all method instead.

<a name=“method-tojson”></a>

8.3.0.81 toJson() {#collection-method}

The toJson method converts the collection into a JSON serialized string:

$collection = collect(['name' => 'Desk', 'price' => 200]);

$collection->toJson();

// '{"name":"Desk", "price":200}'

<a name=“method-transform”></a>

8.3.0.82 transform() {#collection-method}

The transform method iterates over the collection and calls the given callback with each item in the collection. The items in the collection will be replaced by the values returned by the callback:

$collection = collect([1, 2, 3, 4, 5]);

$collection->transform(function ($item, $key) {
    return $item * 2;
});

$collection->all();

// [2, 4, 6, 8, 10]

{note} Unlike most other collection methods, transform modifies the collection itself. If you wish to create a new collection instead, use the map method.

<a name=“method-union”></a>

8.3.0.83 union() {#collection-method}

The union method adds the given array to the collection. If the given array contains keys that are already in the original collection, the original collection’s values will be preferred:

$collection = collect([1 => ['a'], 2 => ['b']]);

$union = $collection->union([3 => ['c'], 1 => ['b']]);

$union->all();

// [1 => ['a'], 2 => ['b'], 3 => ['c']]

<a name=“method-unique”></a>

8.3.0.84 unique() {#collection-method}

The unique method returns all of the unique items in the collection. The returned collection keeps the original array keys, so in this example we’ll use the values method to reset the keys to consecutively numbered indexes:

$collection = collect([1, 1, 2, 2, 3, 4, 2]);

$unique = $collection->unique();

$unique->values()->all();

// [1, 2, 3, 4]

When dealing with nested arrays or objects, you may specify the key used to determine uniqueness:

$collection = collect([
    ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
    ['name' => 'iPhone 5', 'brand' => 'Apple', 'type' => 'phone'],
    ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
    ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
    ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
]);

$unique = $collection->unique('brand');

$unique->values()->all();

/*
    [
        ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
        ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
    ]
*/

You may also pass your own callback to determine item uniqueness:

$unique = $collection->unique(function ($item) {
    return $item['brand'].$item['type'];
});

$unique->values()->all();

/*
    [
        ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
        ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
        ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
        ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
    ]
*/

The unique method uses “loose” comparisons when checking item values, meaning a string with an integer value will be considered equal to an integer of the same value. Use the uniqueStrict method to filter using “strict” comparisons.

<a name=“method-uniquestrict”></a>

8.3.0.85 uniqueStrict() {#collection-method}

This method has the same signature as the unique method; however, all values are compared using “strict” comparisons.

<a name=“method-unless”></a>

8.3.0.86 unless() {#collection-method}

The unless method will execute the given callback unless the first argument given to the method evaluates to true:

$collection = collect([1, 2, 3]);

$collection->unless(true, function ($collection) {
    return $collection->push(4);
});

$collection->unless(false, function ($collection) {
    return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 5]

For the inverse of unless, see the when method.

<a name=“method-unwrap”></a>

8.3.0.87 unwrap() {#collection-method}

The static unwrap method returns the collection’s underlying items from the given value when applicable:

Collection::unwrap(collect('John Doe'));

// ['John Doe']

Collection::unwrap(['John Doe']);

// ['John Doe']

Collection::unwrap('John Doe');

// 'John Doe'

<a name=“method-values”></a>

8.3.0.88 values() {#collection-method}

The values method returns a new collection with the keys reset to consecutive integers:

$collection = collect([
    10 => ['product' => 'Desk', 'price' => 200],
    11 => ['product' => 'Desk', 'price' => 200]
]);

$values = $collection->values();

$values->all();

/*
    [
        0 => ['product' => 'Desk', 'price' => 200],
        1 => ['product' => 'Desk', 'price' => 200],
    ]
*/

<a name=“method-when”></a>

8.3.0.89 when() {#collection-method}

The when method will execute the given callback when the first argument given to the method evaluates to true:

$collection = collect([1, 2, 3]);

$collection->when(true, function ($collection) {
    return $collection->push(4);
});

$collection->when(false, function ($collection) {
    return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 4]

For the inverse of when, see the unless method.

<a name=“method-where”></a>

8.3.0.90 where() {#collection-method}

The where method filters the collection by a given key / value pair:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
    ['product' => 'Bookcase', 'price' => 150],
    ['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->where('price', 100);

$filtered->all();

/*
    [
        ['product' => 'Chair', 'price' => 100],
        ['product' => 'Door', 'price' => 100],
    ]
*/

The where method uses “loose” comparisons when checking item values, meaning a string with an integer value will be considered equal to an integer of the same value. Use the whereStrict method to filter using “strict” comparisons.

<a name=“method-wherestrict”></a>

8.3.0.91 whereStrict() {#collection-method}

This method has the same signature as the where method; however, all values are compared using “strict” comparisons.

<a name=“method-wherein”></a>

8.3.0.92 whereIn() {#collection-method}

The whereIn method filters the collection by a given key / value contained within the given array:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
    ['product' => 'Bookcase', 'price' => 150],
    ['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->whereIn('price', [150, 200]);

$filtered->all();

/*
    [
        ['product' => 'Bookcase', 'price' => 150],
        ['product' => 'Desk', 'price' => 200],
    ]
*/

The whereIn method uses “loose” comparisons when checking item values, meaning a string with an integer value will be considered equal to an integer of the same value. Use the whereInStrict method to filter using “strict” comparisons.

<a name=“method-whereinstrict”></a>

8.3.0.93 whereInStrict() {#collection-method}

This method has the same signature as the whereIn method; however, all values are compared using “strict” comparisons.

<a name=“method-wherenotin”></a>

8.3.0.94 whereNotIn() {#collection-method}

The whereNotIn method filters the collection by a given key / value not contained within the given array:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
    ['product' => 'Bookcase', 'price' => 150],
    ['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->whereNotIn('price', [150, 200]);

$filtered->all();

/*
    [
        ['product' => 'Chair', 'price' => 100],
        ['product' => 'Door', 'price' => 100],
    ]
*/

The whereNotIn method uses “loose” comparisons when checking item values, meaning a string with an integer value will be considered equal to an integer of the same value. Use the whereNotInStrict method to filter using “strict” comparisons.

<a name=“method-wherenotinstrict”></a>

8.3.0.95 whereNotInStrict() {#collection-method}

This method has the same signature as the whereNotIn method; however, all values are compared using “strict” comparisons.

<a name=“method-wrap”></a>

8.3.0.96 wrap() {#collection-method}

The static wrap method wraps the given value in a collection when applicable:

$collection = Collection::wrap('John Doe');

$collection->all();

// ['John Doe']

$collection = Collection::wrap(['John Doe']);

$collection->all();

// ['John Doe']

$collection = Collection::wrap(collect('John Doe'));

$collection->all();

// ['John Doe']

<a name=“method-zip”></a>

8.3.0.97 zip() {#collection-method}

The zip method merges together the values of the given array with the values of the original collection at the corresponding index:

$collection = collect(['Chair', 'Desk']);

$zipped = $collection->zip([100, 200]);

$zipped->all();

// [['Chair', 100], ['Desk', 200]]

<a name=“higher-order-messages”></a>

8.4 Higher Order Messages

Collections also provide support for “higher order messages”, which are short-cuts for performing common actions on collections. The collection methods that provide higher order messages are: average, avg, contains, each, every, filter, first, flatMap, map, partition, reject, sortBy, sortByDesc, sum, and unique.

Each higher order message can be accessed as a dynamic property on a collection instance. For instance, let’s use the each higher order message to call a method on each object within a collection:

$users = User::where('votes', '>', 500)->get();

$users->each->markAsVip();

Likewise, we can use the sum higher order message to gather the total number of “votes” for a collection of users:

$users = User::where('group', 'Development')->get();

return $users->sum->votes;

9 Configuration

<a name=“introduction”></a>

9.1 Introduction

All of the configuration files for the Laravel framework are stored in the config directory. Each option is documented, so feel free to look through the files and get familiar with the options available to you.

<a name=“environment-configuration”></a>

9.2 Environment Configuration

It is often helpful to have different configuration values based on the environment where the application is running. For example, you may wish to use a different cache driver locally than you do on your production server.

To make this a cinch, Laravel utilizes the DotEnv PHP library by Vance Lucas. In a fresh Laravel installation, the root directory of your application will contain a .env.example file. If you install Laravel via Composer, this file will automatically be renamed to .env. Otherwise, you should rename the file manually.

Your .env file should not be committed to your application’s source control, since each developer / server using your application could require a different environment configuration. Furthermore, this would be a security risk in the event an intruder gain access to your source control repository, since any sensitive credentials would get exposed.

If you are developing with a team, you may wish to continue including a .env.example file with your application. By putting place-holder values in the example configuration file, other developers on your team can clearly see which environment variables are needed to run your application. You may also create a .env.testing file. This file will override the .env file when running PHPUnit tests or executing Artisan commands with the --env=testing option.

{tip} Any variable in your .env file can be overridden by external environment variables such as server-level or system-level environment variables.

<a name=“retrieving-environment-configuration”></a>

9.2.1 Retrieving Environment Configuration

All of the variables listed in this file will be loaded into the $_ENV PHP super-global when your application receives a request. However, you may use the env helper to retrieve values from these variables in your configuration files. In fact, if you review the Laravel configuration files, you will notice several of the options already using this helper:

'debug' => env('APP_DEBUG', false),

The second value passed to the env function is the “default value”. This value will be used if no environment variable exists for the given key.

<a name=“determining-the-current-environment”></a>

9.2.2 Determining The Current Environment

The current application environment is determined via the APP_ENV variable from your .env file. You may access this value via the environment method on the App facade:

$environment = App::environment();

You may also pass arguments to the environment method to check if the environment matches a given value. The method will return true if the environment matches any of the given values:

if (App::environment('local')) {
    // The environment is local
}

if (App::environment(['local', 'staging'])) {
    // The environment is either local OR staging...
}

{tip} The current application environment detection can be overridden by a server-level APP_ENV environment variable. This can be useful when you need to share the same application for different environment configurations, so you can set up a given host to match a given environment in your server’s configurations.

<a name=“accessing-configuration-values”></a>

9.3 Accessing Configuration Values

You may easily access your configuration values using the global config helper function from anywhere in your application. The configuration values may be accessed using “dot” syntax, which includes the name of the file and option you wish to access. A default value may also be specified and will be returned if the configuration option does not exist:

$value = config('app.timezone');

To set configuration values at runtime, pass an array to the config helper:

config(['app.timezone' => 'America/Chicago']);

<a name=“configuration-caching”></a>

9.4 Configuration Caching

To give your application a speed boost, you should cache all of your configuration files into a single file using the config:cache Artisan command. This will combine all of the configuration options for your application into a single file which will be loaded quickly by the framework.

You should typically run the php artisan config:cache command as part of your production deployment routine. The command should not be run during local development as configuration options will frequently need to be changed during the course of your application’s development.

{note} If you execute the config:cache command during your deployment process, you should be sure that you are only calling the env function from within your configuration files. Once the configuration has been cached, the .env file will not be loaded and all calls to the env function will return null.

<a name=“maintenance-mode”></a>

9.5 Maintenance Mode

When your application is in maintenance mode, a custom view will be displayed for all requests into your application. This makes it easy to “disable” your application while it is updating or when you are performing maintenance. A maintenance mode check is included in the default middleware stack for your application. If the application is in maintenance mode, a MaintenanceModeException will be thrown with a status code of 503.

To enable maintenance mode, execute the down Artisan command:

php artisan down

You may also provide message and retry options to the down command. The message value may be used to display or log a custom message, while the retry value will be set as the Retry-After HTTP header’s value:

php artisan down --message="Upgrading Database" --retry=60

To disable maintenance mode, use the up command:

php artisan up

{tip} You may customize the default maintenance mode template by defining your own template at resources/views/errors/503.blade.php.

9.5.0.1 Maintenance Mode & Queues

While your application is in maintenance mode, no queued jobs will be handled. The jobs will continue to be handled as normal once the application is out of maintenance mode.

9.5.0.2 Alternatives To Maintenance Mode

Since maintenance mode requires your application to have several seconds of downtime, consider alternatives like Envoyer to accomplish zero-downtime deployment with Laravel.

10 Service Container

<a name=“introduction”></a>

10.1 Introduction

The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection. Dependency injection is a fancy phrase that essentially means this: class dependencies are “injected” into the class via the constructor or, in some cases, “setter” methods.

Let’s look at a simple example:

<?php

namespace App\Http\Controllers;

use App\User;
use App\Repositories\UserRepository;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * The user repository implementation.
     *
     * @var UserRepository
     */
    protected $users;

    /**
     * Create a new controller instance.
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }

    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        $user = $this->users->find($id);

        return view('user.profile', ['user' => $user]);
    }
}

In this example, the UserController needs to retrieve users from a data source. So, we will inject a service that is able to retrieve users. In this context, our UserRepository most likely uses Eloquent to retrieve user information from the database. However, since the repository is injected, we are able to easily swap it out with another implementation. We are also able to easily “mock”, or create a dummy implementation of the UserRepository when testing our application.

A deep understanding of the Laravel service container is essential to building a powerful, large application, as well as for contributing to the Laravel core itself.

<a name=“binding”></a>

10.2 Binding

<a name=“binding-basics”></a>

10.2.1 Binding Basics

Almost all of your service container bindings will be registered within service providers, so most of these examples will demonstrate using the container in that context.

{tip} There is no need to bind classes into the container if they do not depend on any interfaces. The container does not need to be instructed on how to build these objects, since it can automatically resolve these objects using reflection.

10.2.1.1 Simple Bindings

Within a service provider, you always have access to the container via the $this->app property. We can register a binding using the bind method, passing the class or interface name that we wish to register along with a Closure that returns an instance of the class:

$this->app->bind('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app->make('HttpClient'));
});

Note that we receive the container itself as an argument to the resolver. We can then use the container to resolve sub-dependencies of the object we are building.

10.2.1.2 Binding A Singleton

The singleton method binds a class or interface into the container that should only be resolved one time. Once a singleton binding is resolved, the same object instance will be returned on subsequent calls into the container:

$this->app->singleton('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app->make('HttpClient'));
});

10.2.1.3 Binding Instances

You may also bind an existing object instance into the container using the instance method. The given instance will always be returned on subsequent calls into the container:

$api = new HelpSpot\API(new HttpClient);

$this->app->instance('HelpSpot\API', $api);

10.2.1.4 Binding Primitives

Sometimes you may have a class that receives some injected classes, but also needs an injected primitive value such as an integer. You may easily use contextual binding to inject any value your class may need:

$this->app->when('App\Http\Controllers\UserController')
          ->needs('$variableName')
          ->give($value);

<a name=“binding-interfaces-to-implementations”></a>

10.2.2 Binding Interfaces To Implementations

A very powerful feature of the service container is its ability to bind an interface to a given implementation. For example, let’s assume we have an EventPusher interface and a RedisEventPusher implementation. Once we have coded our RedisEventPusher implementation of this interface, we can register it with the service container like so:

$this->app->bind(
    'App\Contracts\EventPusher',
    'App\Services\RedisEventPusher'
);

This statement tells the container that it should inject the RedisEventPusher when a class needs an implementation of EventPusher. Now we can type-hint the EventPusher interface in a constructor, or any other location where dependencies are injected by the service container:

use App\Contracts\EventPusher;

/**
 * Create a new class instance.
 *
 * @param  EventPusher  $pusher
 * @return void
 */
public function __construct(EventPusher $pusher)
{
    $this->pusher = $pusher;
}

<a name=“contextual-binding”></a>

10.2.3 Contextual Binding

Sometimes you may have two classes that utilize the same interface, but you wish to inject different implementations into each class. For example, two controllers may depend on different implementations of the Illuminate\Contracts\Filesystem\Filesystem contract. Laravel provides a simple, fluent interface for defining this behavior:

use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\PhotoController;
use App\Http\Controllers\VideoController;
use Illuminate\Contracts\Filesystem\Filesystem;

$this->app->when(PhotoController::class)
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk('local');
          });

$this->app->when(VideoController::class)
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk('s3');
          });

<a name=“tagging”></a>

10.2.4 Tagging

Occasionally, you may need to resolve all of a certain “category” of binding. For example, perhaps you are building a report aggregator that receives an array of many different Report interface implementations. After registering the Report implementations, you can assign them a tag using the tag method:

$this->app->bind('SpeedReport', function () {
    //
});

$this->app->bind('MemoryReport', function () {
    //
});

$this->app->tag(['SpeedReport', 'MemoryReport'], 'reports');

Once the services have been tagged, you may easily resolve them all via the tagged method:

$this->app->bind('ReportAggregator', function ($app) {
    return new ReportAggregator($app->tagged('reports'));
});

<a name=“extending-bindings”></a>

10.2.5 Extending Bindings

The extend method allows the modification of resolved services. For example, when a service is resolved, you may run additional code to decorate or configure the service. The extend method accepts a Closure, which should return the modified service, as its only argument:

$this->app->extend(Service::class, function($service) {
    return new DecoratedService($service);
});

<a name=“resolving”></a>

10.3 Resolving

<a name=“the-make-method”></a>

10.3.0.1 The make Method

You may use the make method to resolve a class instance out of the container. The make method accepts the name of the class or interface you wish to resolve:

$api = $this->app->make('HelpSpot\API');

If you are in a location of your code that does not have access to the $app variable, you may use the global resolve helper:

$api = resolve('HelpSpot\API');

If some of your class’ dependencies are not resolvable via the container, you may inject them by passing them as an associative array into the makeWith method:

$api = $this->app->makeWith('HelpSpot\API', ['id' => 1]);

<a name=“automatic-injection”></a>

10.3.0.2 Automatic Injection

Alternatively, and importantly, you may “type-hint” the dependency in the constructor of a class that is resolved by the container, including controllers, event listeners, queue jobs, middleware, and more. In practice, this is how most of your objects should be resolved by the container.

For example, you may type-hint a repository defined by your application in a controller’s constructor. The repository will automatically be resolved and injected into the class:

<?php

namespace App\Http\Controllers;

use App\Users\Repository as UserRepository;

class UserController extends Controller
{
    /**
     * The user repository instance.
     */
    protected $users;

    /**
     * Create a new controller instance.
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }

    /**
     * Show the user with the given ID.
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        //
    }
}

<a name=“container-events”></a>

10.4 Container Events

The service container fires an event each time it resolves an object. You may listen to this event using the resolving method:

$this->app->resolving(function ($object, $app) {
    // Called when container resolves object of any type...
});

$this->app->resolving(HelpSpot\API::class, function ($api, $app) {
    // Called when container resolves objects of type "HelpSpot\API"...
});

As you can see, the object being resolved will be passed to the callback, allowing you to set any additional properties on the object before it is given to its consumer.

<a name=“psr-11”></a>

10.5 PSR-11

Laravel’s service container implements the PSR-11 interface. Therefore, you may type-hint the PSR-11 container interface to obtain an instance of the Laravel container:

use Psr\Container\ContainerInterface;

Route::get('/', function (ContainerInterface $container) {
    $service = $container->get('Service');

    //
});

{note} Calling the get method will throw an exception if the identifier has not been explicitly bound into the container.

11 Contracts

<a name=“introduction”></a>

11.1 Introduction

Laravel’s Contracts are a set of interfaces that define the core services provided by the framework. For example, a Illuminate\Contracts\Queue\Queue contract defines the methods needed for queueing jobs, while the Illuminate\Contracts\Mail\Mailer contract defines the methods needed for sending e-mail.

Each contract has a corresponding implementation provided by the framework. For example, Laravel provides a queue implementation with a variety of drivers, and a mailer implementation that is powered by SwiftMailer.

All of the Laravel contracts live in their own GitHub repository. This provides a quick reference point for all available contracts, as well as a single, decoupled package that may be utilized by package developers.

<a name=“contracts-vs-facades”></a>

11.1.1 Contracts Vs. Facades

Laravel’s facades and helper functions provide a simple way of utilizing Laravel’s services without needing to type-hint and resolve contracts out of the service container. In most cases, each facade has an equivalent contract.

Unlike facades, which do not require you to require them in your class’ constructor, contracts allow you to define explicit dependencies for your classes. Some developers prefer to explicitly define their dependencies in this way and therefore prefer to use contracts, while other developers enjoy the convenience of facades.

{tip} Most applications will be fine regardless of whether you prefer facades or contracts. However, if you are building a package, you should strongly consider using contracts since they will be easier to test in a package context.

<a name=“when-to-use-contracts”></a>

11.2 When To Use Contracts

As discussed elsewhere, much of the decision to use contracts or facades will come down to personal taste and the tastes of your development team. Both contracts and facades can be used to create robust, well-tested Laravel applications. As long as you are keeping your class’ responsibilities focused, you will notice very few practical differences between using contracts and facades.

However, you may still have several questions regarding contracts. For example, why use interfaces at all? Isn’t using interfaces more complicated? Let’s distill the reasons for using interfaces to the following headings: loose coupling and simplicity.

<a name=“loose-coupling”></a>

11.2.1 Loose Coupling

First, let’s review some code that is tightly coupled to a cache implementation. Consider the following:

<?php

namespace App\Orders;

class Repository
{
    /**
     * The cache instance.
     */
    protected $cache;

    /**
     * Create a new repository instance.
     *
     * @param  \SomePackage\Cache\Memcached  $cache
     * @return void
     */
    public function __construct(\SomePackage\Cache\Memcached $cache)
    {
        $this->cache = $cache;
    }

    /**
     * Retrieve an Order by ID.
     *
     * @param  int  $id
     * @return Order
     */
    public function find($id)
    {
        if ($this->cache->has($id))    {
            //
        }
    }
}

In this class, the code is tightly coupled to a given cache implementation. It is tightly coupled because we are depending on a concrete Cache class from a package vendor. If the API of that package changes our code must change as well.

Likewise, if we want to replace our underlying cache technology (Memcached) with another technology (Redis), we again will have to modify our repository. Our repository should not have so much knowledge regarding who is providing them data or how they are providing it.

Instead of this approach, we can improve our code by depending on a simple, vendor agnostic interface:

<?php

namespace App\Orders;

use Illuminate\Contracts\Cache\Repository as Cache;

class Repository
{
    /**
     * The cache instance.
     */
    protected $cache;

    /**
     * Create a new repository instance.
     *
     * @param  Cache  $cache
     * @return void
     */
    public function __construct(Cache $cache)
    {
        $this->cache = $cache;
    }
}

Now the code is not coupled to any specific vendor, or even Laravel. Since the contracts package contains no implementation and no dependencies, you may easily write an alternative implementation of any given contract, allowing you to replace your cache implementation without modifying any of your cache consuming code.

<a name=“simplicity”></a>

11.2.2 Simplicity

When all of Laravel’s services are neatly defined within simple interfaces, it is very easy to determine the functionality offered by a given service. The contracts serve as succinct documentation to the framework’s features.

In addition, when you depend on simple interfaces, your code is easier to understand and maintain. Rather than tracking down which methods are available to you within a large, complicated class, you can refer to a simple, clean interface.

<a name=“how-to-use-contracts”></a>

11.3 How To Use Contracts

So, how do you get an implementation of a contract? It’s actually quite simple.

Many types of classes in Laravel are resolved through the service container, including controllers, event listeners, middleware, queued jobs, and even route Closures. So, to get an implementation of a contract, you can just “type-hint” the interface in the constructor of the class being resolved.

For example, take a look at this event listener:

<?php

namespace App\Listeners;

use App\User;
use App\Events\OrderWasPlaced;
use Illuminate\Contracts\Redis\Database;

class CacheOrderInformation
{
    /**
     * The Redis database implementation.
     */
    protected $redis;

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

    /**
     * Handle the event.
     *
     * @param  OrderWasPlaced  $event
     * @return void
     */
    public function handle(OrderWasPlaced $event)
    {
        //
    }
}

When the event listener is resolved, the service container will read the type-hints on the constructor of the class, and inject the appropriate value. To learn more about registering things in the service container, check out its documentation.

<a name=“contract-reference”></a>

11.4 Contract Reference

This table provides a quick reference to all of the Laravel contracts and their equivalent facades:

Contract References Facade
Illuminate\Contracts\Auth\Access\Authorizable   
Illuminate\Contracts\Auth\Access\Gate Gate
Illuminate\Contracts\Auth\Authenticatable   
Illuminate\Contracts\Auth\CanResetPassword  
Illuminate\Contracts\Auth\Factory Auth
Illuminate\Contracts\Auth\Guard Auth::guard()
Illuminate\Contracts\Auth\PasswordBroker Password::broker()
Illuminate\Contracts\Auth\PasswordBrokerFactory Password
Illuminate\Contracts\Auth\StatefulGuard  
Illuminate\Contracts\Auth\SupportsBasicAuth  
Illuminate\Contracts\Auth\UserProvider  
Illuminate\Contracts\Bus\Dispatcher Bus
Illuminate\Contracts\Bus\QueueingDispatcher Bus::dispatchToQueue()
Illuminate\Contracts\Broadcasting\Factory Broadcast
Illuminate\Contracts\Broadcasting\Broadcaster Broadcast::connection()
Illuminate\Contracts\Broadcasting\ShouldBroadcast  
Illuminate\Contracts\Broadcasting\ShouldBroadcastNow  
Illuminate\Contracts\Cache\Factory Cache
Illuminate\Contracts\Cache\Lock  
Illuminate\Contracts\Cache\LockProvider  
Illuminate\Contracts\Cache\Repository Cache::driver()
Illuminate\Contracts\Cache\Store  
Illuminate\Contracts\Config\Repository Config
Illuminate\Contracts\Console\Application  
Illuminate\Contracts\Console\Kernel Artisan
Illuminate\Contracts\Container\Container App
Illuminate\Contracts\Cookie\Factory Cookie
Illuminate\Contracts\Cookie\QueueingFactory Cookie::queue()
Illuminate\Contracts\Database\ModelIdentifier  
Illuminate\Contracts\Debug\ExceptionHandler  
Illuminate\Contracts\Encryption\Encrypter Crypt
Illuminate\Contracts\Events\Dispatcher Event
Illuminate\Contracts\Filesystem\Cloud Storage::cloud()
Illuminate\Contracts\Filesystem\Factory Storage
Illuminate\Contracts\Filesystem\Filesystem Storage::disk()
Illuminate\Contracts\Foundation\Application App
Illuminate\Contracts\Hashing\Hasher Hash
Illuminate\Contracts\Http\Kernel  
Illuminate\Contracts\Logging\Log Log
Illuminate\Contracts\Mail\MailQueue Mail::queue()
Illuminate\Contracts\Mail\Mailable  
Illuminate\Contracts\Mail\Mailer Mail
Illuminate\Contracts\Notifications\Dispatcher Notification
Illuminate\Contracts\Notifications\Factory Notification
Illuminate\Contracts\Pagination\LengthAwarePaginator  
Illuminate\Contracts\Pagination\Paginator  
Illuminate\Contracts\Pipeline\Hub  
Illuminate\Contracts\Pipeline\Pipeline  
Illuminate\Contracts\Queue\EntityResolver  
Illuminate\Contracts\Queue\Factory Queue
Illuminate\Contracts\Queue\Job  
Illuminate\Contracts\Queue\Monitor Queue
Illuminate\Contracts\Queue\Queue Queue::connection()
Illuminate\Contracts\Queue\QueueableCollection  
Illuminate\Contracts\Queue\QueueableEntity  
Illuminate\Contracts\Queue\ShouldQueue  
Illuminate\Contracts\Redis\Factory Redis
Illuminate\Contracts\Routing\BindingRegistrar Route
Illuminate\Contracts\Routing\Registrar Route
Illuminate\Contracts\Routing\ResponseFactory Response
Illuminate\Contracts\Routing\UrlGenerator URL
Illuminate\Contracts\Routing\UrlRoutable  
Illuminate\Contracts\Session\Session Session::driver()
Illuminate\Contracts\Support\Arrayable  
Illuminate\Contracts\Support\Htmlable  
Illuminate\Contracts\Support\Jsonable  
Illuminate\Contracts\Support\MessageBag  
Illuminate\Contracts\Support\MessageProvider  
Illuminate\Contracts\Support\Renderable  
Illuminate\Contracts\Support\Responsable  
Illuminate\Contracts\Translation\Loader  
Illuminate\Contracts\Translation\Translator Lang
Illuminate\Contracts\Validation\Factory Validator
Illuminate\Contracts\Validation\ImplicitRule  
Illuminate\Contracts\Validation\Rule  
Illuminate\Contracts\Validation\ValidatesWhenResolved  
Illuminate\Contracts\Validation\Validator Validator::make()
Illuminate\Contracts\View\Engine  
Illuminate\Contracts\View\Factory View
Illuminate\Contracts\View\View View::make()

12 Contribution Guidelines

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

13 Contribution Guide

<a name=“bug-reports”></a>

13.1 Bug Reports

To encourage active collaboration, Laravel strongly encourages pull requests, not just bug reports. “Bug reports” may also be sent in the form of a pull request containing a failing test.

However, if you file a bug report, your issue should contain a title and a clear description of the issue. You should also include as much relevant information as possible and a code sample that demonstrates the issue. The goal of a bug report is to make it easy for yourself - and others - to replicate the bug and develop a fix.

Remember, bug reports are created in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the bug report will automatically see any activity or that others will jump to fix it. Creating a bug report serves to help yourself and others start on the path of fixing the problem.

The Laravel source code is managed on GitHub, and there are repositories for each of the Laravel projects:

<div class=“content-list” markdown=“1”>

<a name=“core-development-discussion”></a>

13.2 Core Development Discussion

You may propose new features or improvements of existing Laravel behavior in the Laravel Internals issue board. If you propose a new feature, please be willing to implement at least some of the code that would be needed to complete the feature.

Informal discussion regarding bugs, new features, and implementation of existing features takes place in the #internals channel of the LaraChat Slack team. Taylor Otwell, the maintainer of Laravel, is typically present in the channel on weekdays from 8am-5pm (UTC-06:00 or America/Chicago), and sporadically present in the channel at other times.

<a name=“which-branch”></a>

13.3 Which Branch?

All bug fixes should be sent to the latest stable branch or to the current LTS branch (5.5). Bug fixes should never be sent to the master branch unless they fix features that exist only in the upcoming release.

Minor features that are fully backwards compatible with the current Laravel release may be sent to the latest stable branch.

Major new features should always be sent to the master branch, which contains the upcoming Laravel release.

If you are unsure if your feature qualifies as a major or minor, please ask Taylor Otwell in the #internals channel of the LaraChat Slack team.

<a name=“security-vulnerabilities”></a>

13.4 Security Vulnerabilities

If you discover a security vulnerability within Laravel, please send an email to Taylor Otwell at <a href=“”>taylor@laravel.com</a>. All security vulnerabilities will be promptly addressed.

<a name=“coding-style”></a>

13.5 Coding Style

Laravel follows the PSR-2 coding standard and the PSR-4 autoloading standard.

<a name=“phpdoc”></a>

13.5.1 PHPDoc

Below is an example of a valid Laravel documentation block. Note that the @param attribute is followed by two spaces, the argument type, two more spaces, and finally the variable name:

/**
 * Register a binding with the container.
 *
 * @param  string|array  $abstract
 * @param  \Closure|string|null  $concrete
 * @param  bool  $shared
 * @return void
 */
public function bind($abstract, $concrete = null, $shared = false)
{
    //
}

<a name=“styleci”></a>

13.5.2 StyleCI

Don’t worry if your code styling isn’t perfect! StyleCI will automatically merge any style fixes into the Laravel repository after pull requests are merged. This allows us to focus on the content of the contribution and not the code style.

14 Controllers

<a name=“introduction”></a>

14.1 Introduction

Instead of defining all of your request handling logic as Closures in route files, you may wish to organize this behavior using Controller classes. Controllers can group related request handling logic into a single class. Controllers are stored in the app/Http/Controllers directory.

<a name=“basic-controllers”></a>

14.2 Basic Controllers

<a name=“defining-controllers”></a>

14.2.1 Defining Controllers

Below is an example of a basic controller class. Note that the controller extends the base controller class included with Laravel. The base class provides a few convenience methods such as the middleware method, which may be used to attach middleware to controller actions:

<?php

namespace App\Http\Controllers;

use App\User;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

You can define a route to this controller action like so:

Route::get('user/{id}', 'UserController@show');

Now, when a request matches the specified route URI, the show method on the UserController class will be executed. Of course, the route parameters will also be passed to the method.

{tip} Controllers are not required to extend a base class. However, you will not have access to convenience features such as the middleware, validate, and dispatch methods.

<a name=“controllers-and-namespaces”></a>

14.2.2 Controllers & Namespaces

It is very important to note that we did not need to specify the full controller namespace when defining the controller route. Since the RouteServiceProvider loads your route files within a route group that contains the namespace, we only specified the portion of the class name that comes after the App\Http\Controllers portion of the namespace.

If you choose to nest your controllers deeper into the App\Http\Controllers directory, use the specific class name relative to the App\Http\Controllers root namespace. So, if your full controller class is App\Http\Controllers\Photos\AdminController, you should register routes to the controller like so:

Route::get('foo', 'Photos\AdminController@method');

<a name=“single-action-controllers”></a>

14.2.3 Single Action Controllers

If you would like to define a controller that only handles a single action, you may place a single __invoke method on the controller:

<?php

namespace App\Http\Controllers;

use App\User;
use App\Http\Controllers\Controller;

class ShowProfile extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function __invoke($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

When registering routes for single action controllers, you do not need to specify a method:

Route::get('user/{id}', 'ShowProfile');

<a name=“controller-middleware”></a>

14.3 Controller Middleware

Middleware may be assigned to the controller’s routes in your route files:

Route::get('profile', 'UserController@show')->middleware('auth');

However, it is more convenient to specify middleware within your controller’s constructor. Using the middleware method from your controller’s constructor, you may easily assign middleware to the controller’s action. You may even restrict the middleware to only certain methods on the controller class:

class UserController extends Controller
{
    /**
     * Instantiate a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');

        $this->middleware('log')->only('index');

        $this->middleware('subscribed')->except('store');
    }
}

Controllers also allow you to register middleware using a Closure. This provides a convenient way to define a middleware for a single controller without defining an entire middleware class:

$this->middleware(function ($request, $next) {
    // ...

    return $next($request);
});

{tip} You may assign middleware to a subset of controller actions; however, it may indicate your controller is growing too large. Instead, consider breaking your controller into multiple, smaller controllers.

<a name=“resource-controllers”></a>

14.4 Resource Controllers

Laravel resource routing assigns the typical “CRUD” routes to a controller with a single line of code. For example, you may wish to create a controller that handles all HTTP requests for “photos” stored by your application. Using the make:controller Artisan command, we can quickly create such a controller:

php artisan make:controller PhotoController --resource

This command will generate a controller at app/Http/Controllers/PhotoController.php. The controller will contain a method for each of the available resource operations.

Next, you may register a resourceful route to the controller:

Route::resource('photos', 'PhotoController');

This single route declaration creates multiple routes to handle a variety of actions on the resource. The generated controller will already have methods stubbed for each of these actions, including notes informing you of the HTTP verbs and URIs they handle.

You may register many resource controllers at once by passing an array to the resources method:

Route::resources([
    'photos' => 'PhotoController',
    'posts' => 'PostController'
]);

14.4.0.1 Actions Handled By Resource Controller

Verb URI Action Route Name
GET /photos index photos.index
GET /photos/create create photos.create
POST /photos store photos.store
GET /photos/{photo} show photos.show
GET /photos/{photo}/edit edit photos.edit
PUT/PATCH /photos/{photo} update photos.update
DELETE /photos/{photo} destroy photos.destroy

14.4.0.2 Specifying The Resource Model

If you are using route model binding and would like the resource controller’s methods to type-hint a model instance, you may use the --model option when generating the controller:

php artisan make:controller PhotoController --resource --model=Photo

14.4.0.3 Spoofing Form Methods

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_field helper can create this field for you:

{{ method_field('PUT') }}

<a name=“restful-partial-resource-routes”></a>

14.4.1 Partial Resource Routes

When declaring a resource route, you may specify a subset of actions the controller should handle instead of the full set of default actions:

Route::resource('photo', 'PhotoController', ['only' => [
    'index', 'show'
]]);

Route::resource('photo', 'PhotoController', ['except' => [
    'create', 'store', 'update', 'destroy'
]]);

14.4.1.1 API Resource Routes

When declaring resource routes that will be consumed by APIs, you will commonly want to exclude routes that present HTML templates such as create and edit. For convenience, you may use the apiResource method to automatically exclude these two routes:

Route::apiResource('photo', 'PhotoController');

You may register many API resource controllers at once by passing an array to the apiResources method:

Route::apiResources([
    'photos' => 'PhotoController',
    'posts' => 'PostController'
]);

<a name=“restful-naming-resource-routes”></a>

14.4.2 Naming Resource Routes

By default, all resource controller actions have a route name; however, you can override these names by passing a names array with your options:

Route::resource('photo', 'PhotoController', ['names' => [
    'create' => 'photo.build'
]]);

<a name=“restful-naming-resource-route-parameters”></a>

14.4.3 Naming Resource Route Parameters

By default, Route::resource will create the route parameters for your resource routes based on the “singularized” version of the resource name. You can easily override this on a per resource basis by passing parameters in the options array. The parameters array should be an associative array of resource names and parameter names:

Route::resource('user', 'AdminUserController', ['parameters' => [
    'user' => 'admin_user'
]]);

The example above generates the following URIs for the resource’s show route:

/user/{admin_user}

<a name=“restful-localizing-resource-uris”></a>

14.4.4 Localizing Resource URIs

By default, Route::resource will create resource URIs using English verbs. If you need to localize the create and edit action verbs, you may use the Route::resourceVerbs method. This may be done in the boot method of your AppServiceProvider:

use Illuminate\Support\Facades\Route;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Route::resourceVerbs([
        'create' => 'crear',
        'edit' => 'editar',
    ]);
}

Once the verbs have been customized, a resource route registration such as Route::resource('fotos', 'PhotoController') will produce the following URIs:

/fotos/crear

/fotos/{foto}/editar

<a name=“restful-supplementing-resource-controllers”></a>

14.4.5 Supplementing Resource Controllers

If you need to add additional routes to a resource controller beyond the default set of resource routes, you should define those routes before your call to Route::resource; otherwise, the routes defined by the resource method may unintentionally take precedence over your supplemental routes:

Route::get('photos/popular', 'PhotoController@method');

Route::resource('photos', 'PhotoController');

{tip} Remember to keep your controllers focused. If you find yourself routinely needing methods outside of the typical set of resource actions, consider splitting your controller into two, smaller controllers.

<a name=“dependency-injection-and-controllers”></a>

14.5 Dependency Injection & Controllers

14.5.0.1 Constructor Injection

The Laravel service container is used to resolve all Laravel controllers. As a result, you are able to type-hint any dependencies your controller may need in its constructor. The declared dependencies will automatically be resolved and injected into the controller instance:

<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;

class UserController extends Controller
{
    /**
     * The user repository instance.
     */
    protected $users;

    /**
     * Create a new controller instance.
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }
}

Of course, you may also type-hint any Laravel contract. If the container can resolve it, you can type-hint it. Depending on your application, injecting your dependencies into your controller may provide better testability.

14.5.0.2 Method Injection

In addition to constructor injection, you may also type-hint dependencies on your controller’s methods. A common use-case for method injection is injecting the Illuminate\Http\Request instance into your controller methods:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Store a new user.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $name = $request->name;

        //
    }
}

If your controller method is also expecting input from a route parameter, list your route arguments after your other dependencies. For example, if your route is defined like so:

Route::put('user/{id}', 'UserController@update');

You may still type-hint the Illuminate\Http\Request and access your id parameter by defining your controller method as follows:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Update the given user.
     *
     * @param  Request  $request
     * @param  string  $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        //
    }
}

<a name=“route-caching”></a>

14.6 Route Caching

{note} Closure based routes cannot be cached. To use route caching, you must convert any Closure routes to controller classes.

If your application is exclusively using controller based routes, you should take advantage of Laravel’s route cache. Using the route cache will drastically decrease the amount of time it takes to register all of your application’s routes. In some cases, your route registration may even be up to 100x faster. To generate a route cache, just execute the route:cache Artisan command:

php artisan route:cache

After running this command, your cached routes file will be loaded on every request. Remember, if you add any new routes you will need to generate a fresh route cache. Because of this, you should only run the route:cache command during your project’s deployment.

You may use the route:clear command to clear the route cache:

php artisan route:clear

15 CSRF Protection

<a name=“csrf-introduction”></a>

15.1 Introduction

Laravel makes it easy to protect your application from cross-site request forgery (CSRF) attacks. Cross-site request forgeries are a type of malicious exploit whereby unauthorized commands are performed on behalf of an authenticated user.

Laravel automatically generates a CSRF “token” for each active user session managed by the application. This token is used to verify that the authenticated user is the one actually making the requests to the application.

Anytime you define a 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_field helper to generate the token field:

<form method="POST" action="/profile">
    {{ csrf_field() }}
    ...
</form>

The VerifyCsrfToken middleware, which is included in the web middleware group, will automatically verify that the token in the request input matches the token stored in the session.

15.1.0.1 CSRF Tokens & JavaScript

When building JavaScript driven applications, it is convenient to have your JavaScript HTTP library automatically attach the CSRF token to every outgoing request. By default, the resources/assets/js/bootstrap.js file registers the value of the csrf-token meta tag with the Axios HTTP library. If you are not using this library, you will need to manually configure this behavior for your application.

<a name=“csrf-excluding-uris”></a>

15.2 Excluding URIs From CSRF Protection

Sometimes you may wish to exclude a set of URIs from CSRF protection. For example, if you are using Stripe to process payments and are utilizing their webhook system, you will need to exclude your Stripe webhook handler route from CSRF protection since Stripe will not know what CSRF token to send to your routes.

Typically, you should place these kinds of routes outside of the web middleware group that the RouteServiceProvider applies to all routes in the routes/web.php file. However, you may also exclude the routes by adding their URIs to the $except property of the VerifyCsrfToken middleware:

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

class VerifyCsrfToken extends Middleware
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        'stripe/*',
        'http://example.com/foo/bar',
        'http://example.com/foo/*',
    ];
}

<a name=“csrf-x-csrf-token”></a>

15.3 X-CSRF-TOKEN

In addition to checking for the CSRF token as a POST parameter, the VerifyCsrfToken middleware will also check for the X-CSRF-TOKEN request header. You could, for example, store the token in a HTML meta tag:

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

Then, once you have created the meta tag, you can instruct a library like jQuery to automatically add the token to all request headers. This provides simple, convenient CSRF protection for your AJAX based applications:

$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});

{tip} By default, the resources/assets/js/bootstrap.js file registers the value of the csrf-token meta tag with the Axios HTTP library. If you are not using this library, you will need to manually configure this behavior for your application.

<a name=“csrf-x-xsrf-token”></a>

15.4 X-XSRF-TOKEN

Laravel stores the current CSRF token in a XSRF-TOKEN cookie that is included with each response generated by the framework. You can use the cookie value to set the X-XSRF-TOKEN request header.

This cookie is primarily sent as a convenience since some JavaScript frameworks and libraries, like Angular and Axios, automatically place its value in the X-XSRF-TOKEN header.

16 Database Testing

<a name=“introduction”></a>

16.1 Introduction

Laravel provides a variety of helpful tools to make it easier to test your database driven applications. First, you may use the assertDatabaseHas helper to assert that data exists in the database matching a given set of criteria. For example, if you would like to verify that there is a record in the users table with the email value of sally@example.com, you can do the following:

public function testDatabase()
{
    // Make call to application...

    $this->assertDatabaseHas('users', [
        'email' => 'sally@example.com'
    ]);
}

You can also use the assertDatabaseMissing helper to assert that data does not exist in the database.

Of course, the assertDatabaseHas method and other helpers like it are for convenience. You are free to use any of PHPUnit’s built-in assertion methods to supplement your tests.

<a name=“generating-factories”></a>

16.2 Generating Factories

To create a factory, use the make:factory Artisan command:

php artisan make:factory PostFactory

The new factory will be placed in your database/factories directory.

The --model option may be used to indicate the name of the model created by the factory. This option will pre-fill the generated factory file with the given model:

php artisan make:factory PostFactory --model=Post

<a name=“resetting-the-database-after-each-test”></a>

16.3 Resetting The Database After Each Test

It is often useful to reset your database after each test so that data from a previous test does not interfere with subsequent tests. The RefreshDatabase trait takes the most optimal approach to migrating your test database depending on if you are using an in-memory database or a traditional database. Use the trait on your test class and everything will be handled for you:

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->get('/');

        // ...
    }
}

<a name=“writing-factories”></a>

16.4 Writing Factories

When testing, you may need to insert a few records into your database before executing your test. Instead of manually specifying the value of each column when you create this test data, Laravel allows you to define a default set of attributes for each of your Eloquent models using model factories. To get started, take a look at the database/factories/UserFactory.php file in your application. Out of the box, this file contains one factory definition:

use Faker\Generator as Faker;

$factory->define(App\User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret
        'remember_token' => str_random(10),
    ];
});

Within the Closure, which serves as the factory definition, you may return the default test values of all attributes on the model. The Closure will receive an instance of the Faker PHP library, which allows you to conveniently generate various kinds of random data for testing.

You may also create additional factory files for each model for better organization. For example, you could create UserFactory.php and CommentFactory.php files within your database/factories directory. All of the files within the factories directory will automatically be loaded by Laravel.

<a name=“factory-states”></a>

16.4.1 Factory States

States allow you to define discrete modifications that can be applied to your model factories in any combination. For example, your User model might have a delinquent state that modifies one of its default attribute values. You may define your state transformations using the state method. For simple states, you may pass an array of attribute modifications:

$factory->state(App\User::class, 'delinquent', [
    'account_status' => 'delinquent',
]);

If your state requires calculation or a $faker instance, you may use a Closure to calculate the state’s attribute modifications:

$factory->state(App\User::class, 'address', function ($faker) {
    return [
        'address' => $faker->address,
    ];
});

<a name=“using-factories”></a>

16.5 Using Factories

<a name=“creating-models”></a>

16.5.1 Creating Models

Once you have defined your factories, you may use the global factory function in your tests or seed files to generate model instances. So, let’s take a look at a few examples of creating models. First, we’ll use the make method to create models but not save them to the database:

public function testDatabase()
{
    $user = factory(App\User::class)->make();

    // Use model in tests...
}

You may also create a Collection of many models or create models of a given type:

// Create three App\User instances...
$users = factory(App\User::class, 3)->make();

16.5.1.1 Applying States

You may also apply any of your states to the models. If you would like to apply multiple state transformations to the models, you should specify the name of each state you would like to apply:

$users = factory(App\User::class, 5)->states('delinquent')->make();

$users = factory(App\User::class, 5)->states('premium', 'delinquent')->make();

16.5.1.2 Overriding Attributes

If you would like to override some of the default values of your models, you may pass an array of values to the make method. Only the specified values will be replaced while the rest of the values remain set to their default values as specified by the factory:

$user = factory(App\User::class)->make([
    'name' => 'Abigail',
]);

<a name=“persisting-models”></a>

16.5.2 Persisting Models

The create method not only creates the model instances but also saves them to the database using Eloquent’s save method:

public function testDatabase()
{
    // Create a single App\User instance...
    $user = factory(App\User::class)->create();

    // Create three App\User instances...
    $users = factory(App\User::class, 3)->create();

    // Use model in tests...
}

You may override attributes on the model by passing an array to the create method:

$user = factory(App\User::class)->create([
    'name' => 'Abigail',
]);

<a name=“relationships”></a>

16.5.3 Relationships

In this example, we’ll attach a relation to some created models. When using the create method to create multiple models, an Eloquent collection instance is returned, allowing you to use any of the convenient functions provided by the collection, such as each:

$users = factory(App\User::class, 3)
           ->create()
           ->each(function ($u) {
                $u->posts()->save(factory(App\Post::class)->make());
            });

16.5.3.1 Relations & Attribute Closures

You may also attach relationships to models using Closure attributes in your factory definitions. For example, if you would like to create a new User instance when creating a Post, you may do the following:

$factory->define(App\Post::class, function ($faker) {
    return [
        'title' => $faker->title,
        'content' => $faker->paragraph,
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        }
    ];
});

These Closures also receive the evaluated attribute array of the factory that defines them:

$factory->define(App\Post::class, function ($faker) {
    return [
        'title' => $faker->title,
        'content' => $faker->paragraph,
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        },
        'user_type' => function (array $post) {
            return App\User::find($post['user_id'])->type;
        }
    ];
});

<a name=“available-assertions”></a>

16.6 Available Assertions

Laravel provides several database assertions for your PHPUnit tests:

Method Description
$this->assertDatabaseHas($table, array $data); Assert that a table in the database contains the given data.
$this->assertDatabaseMissing($table, array $data); Assert that a table in the database does not contain the given data.
$this->assertSoftDeleted($table, array $data); Assert that the given record has been soft deleted.

17 Database: Getting Started

<a name=“introduction”></a>

17.1 Introduction

Laravel makes interacting with databases extremely simple across a variety of database backends using either raw SQL, the fluent query builder, and the Eloquent ORM. Currently, Laravel supports four databases:

<div class=“content-list” markdown=“1”>

  • MySQL
  • PostgreSQL
  • SQLite
  • SQL Server
    </div>

<a name=“configuration”></a>

17.1.1 Configuration

The database configuration for your application is located at config/database.php. In this file you may define all of your database connections, as well as specify which connection should be used by default. Examples for most of the supported database systems are provided in this file.

By default, Laravel’s sample environment configuration is ready to use with Laravel Homestead, which is a convenient virtual machine for doing Laravel development on your local machine. Of course, you are free to modify this configuration as needed for your local database.

17.1.1.1 SQLite Configuration

After creating a new SQLite database using a command such as touch database/database.sqlite, you can easily configure your environment variables to point to this newly created database by using the database’s absolute path:

DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite

<a name=“read-and-write-connections”></a>

17.1.2 Read & Write Connections

Sometimes you may wish to use one database connection for SELECT statements, and another for INSERT, UPDATE, and DELETE statements. Laravel makes this a breeze, and the proper connections will always be used whether you are using raw queries, the query builder, or the Eloquent ORM.

To see how read / write connections should be configured, let’s look at this example:

'mysql' => [
    'read' => [
        'host' => '192.168.1.1',
    ],
    'write' => [
        'host' => '196.168.1.2'
    ],
    'sticky'    => true,
    'driver'    => 'mysql',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => '',
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix'    => '',
],

Note that three keys have been added to the configuration array: read, write and sticky. The read and write keys have array values containing a single key: host. The rest of the database options for the read and write connections will be merged from the main mysql array.

You only need to place items in the read and write arrays if you wish to override the values from the main array. So, in this case, 192.168.1.1 will be used as the host for the “read” connection, while 192.168.1.2 will be used for the “write” connection. The database credentials, prefix, character set, and all other options in the main mysql array will be shared across both connections.

17.1.2.1 The sticky Option

The sticky option is an optional value that can be used to allow the immediate reading of records that have been written to the database during the current request cycle. If the sticky option is enabled and a “write” operation has been performed against the database during the current request cycle, any further “read” operations will use the “write” connection. This ensures that any data written during the request cycle can be immediately read back from the database during that same request. It is up to you to decide if this is the desired behavior for your application.

<a name=“using-multiple-database-connections”></a>

17.1.3 Using Multiple Database Connections

When using multiple connections, you may access each connection via the connection method on the DB facade. The name passed to the connection method should correspond to one of the connections listed in your config/database.php configuration file:

$users = DB::connection('foo')->select(...);

You may also access the raw, underlying PDO instance using the getPdo method on a connection instance:

$pdo = DB::connection()->getPdo();

<a name=“running-queries”></a>

17.2 Running Raw SQL Queries

Once you have configured your database connection, you may run queries using the DB facade. The DB facade provides methods for each type of query: select, update, insert, delete, and statement.

17.2.0.1 Running A Select Query

To run a basic query, you may use the select method on the DB facade:

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * Show a list of all of the application's users.
     *
     * @return Response
     */
    public function index()
    {
        $users = DB::select('select * from users where active = ?', [1]);

        return view('user.index', ['users' => $users]);
    }
}

The first argument passed to the select method is the raw SQL query, while the second argument is any parameter bindings that need to be bound to the query. Typically, these are the values of the where clause constraints. Parameter binding provides protection against SQL injection.

The select method will always return an array of results. Each result within the array will be a PHP StdClass object, allowing you to access the values of the results:

foreach ($users as $user) {
    echo $user->name;
}

17.2.0.2 Using Named Bindings

Instead of using ? to represent your parameter bindings, you may execute a query using named bindings:

$results = DB::select('select * from users where id = :id', ['id' => 1]);

17.2.0.3 Running An Insert Statement

To execute an insert statement, you may use the insert method on the DB facade. Like select, this method takes the raw SQL query as its first argument and bindings as its second argument:

DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);

17.2.0.4 Running An Update Statement

The update method should be used to update existing records in the database. The number of rows affected by the statement will be returned:

$affected = DB::update('update users set votes = 100 where name = ?', ['John']);

17.2.0.5 Running A Delete Statement

The delete method should be used to delete records from the database. Like update, the number of rows affected will be returned:

$deleted = DB::delete('delete from users');

17.2.0.6 Running A General Statement

Some database statements do not return any value. For these types of operations, you may use the statement method on the DB facade:

DB::statement('drop table users');

<a name=“listening-for-query-events”></a>

17.2.1 Listening For Query Events

If you would like to receive each SQL query executed by your application, you may use the listen method. This method is useful for logging queries or debugging. You may register your query listener in a service provider:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        DB::listen(function ($query) {
            // $query->sql
            // $query->bindings
            // $query->time
        });
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

<a name=“database-transactions”></a>

17.3 Database Transactions

You may use the transaction method on the DB facade to run a set of operations within a database transaction. If an exception is thrown within the transaction Closure, the transaction will automatically be rolled back. If the Closure executes successfully, the transaction will automatically be committed. You don’t need to worry about manually rolling back or committing while using the transaction method:

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);

    DB::table('posts')->delete();
});

17.3.0.1 Handling Deadlocks

The transaction method accepts an optional second argument which defines the number of times a transaction should be reattempted when a deadlock occurs. Once these attempts have been exhausted, an exception will be thrown:

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);

    DB::table('posts')->delete();
}, 5);

17.3.0.2 Manually Using Transactions

If you would like to begin a transaction manually and have complete control over rollbacks and commits, you may use the beginTransaction method on the DB facade:

DB::beginTransaction();

You can rollback the transaction via the rollBack method:

DB::rollBack();

Lastly, you can commit a transaction via the commit method:

DB::commit();

{tip} The DB facade’s transaction methods control the transactions for both the query builder and Eloquent ORM.

18 Deployment

<a name=“introduction”></a>

18.1 Introduction

When you’re ready to deploy your Laravel application to production, there are some important things you can do to make sure your application is running as efficiently as possible. In this document, we’ll cover some great starting points for making sure your Laravel application is deployed properly.

<a name=“server-configuration”></a>

18.2 Server Configuration

<a name=“nginx”></a>

18.2.1 Nginx

If you are deploying your application to a server that is running Nginx, you may use the following configuration file as a starting point for configuring your web server. Most likely, this file will need to be customized depending on your server’s configuration. If you would like assistance in managing your server, consider using a service such as Laravel Forge:

server {
    listen 80;
    server_name example.com;
    root /example.com/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.html index.htm index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

<a name=“optimization”></a>

18.3 Optimization

<a name=“autoloader-optimization”></a>

18.3.1 Autoloader Optimization

When deploying to production, make sure that you are optimizing Composer’s class autoloader map so Composer can quickly find the proper file to load for a given class:

composer install --optimize-autoloader

{tip} In addition to optimizing the autoloader, you should always be sure to include a composer.lock file in your project’s source control repository. Your project’s dependencies can be installed much faster when a composer.lock file is present.

<a name=“optimizing-configuration-loading”></a>

18.3.2 Optimizing Configuration Loading

When deploying your application to production, you should make sure that you run the config:cache Artisan command during your deployment process:

php artisan config:cache

This command will combine all of Laravel’s configuration files into a single, cached file, which greatly reduces the number of trips the framework must make to the filesystem when loading your configuration values.

<a name=“optimizing-route-loading”></a>

18.3.3 Optimizing Route Loading

If you are building a large application with many routes, you should make sure that you are running the route:cache Artisan command during your deployment process:

php artisan route:cache

This command reduces all of your route registrations into a single method call within a cached file, improving the performance of route registration when registering hundreds of routes.

{note} Since this feature uses PHP serialization, you may only cache the routes for applications that exclusively use controller based routes. PHP is not able to serialize Closures.

<a name=“deploying-with-forge”></a>

18.4 Deploying With Forge

If you aren’t quite ready to manage your own server configuration or aren’t comfortable configuring all of the various services needed to run a robust Laravel application, Laravel Forge is a wonderful alternative.

Laravel Forge can create servers on various infrastructure providers such as DigitalOcean, Linode, AWS, and more. In addition, Forge installs and manages all of the tools needed to build robust Laravel applications, such as Nginx, MySQL, Redis, Memcached, Beanstalk, and more.

19 Browser Tests (Laravel Dusk)

<a name=“introduction”></a>

19.1 Introduction

Laravel Dusk provides an expressive, easy-to-use browser automation and testing API. By default, Dusk does not require you to install JDK or Selenium on your machine. Instead, Dusk uses a standalone ChromeDriver installation. However, you are free to utilize any other Selenium compatible driver you wish.

<a name=“installation”></a>

19.2 Installation

To get started, you should add the laravel/dusk Composer dependency to your project:

composer require --dev laravel/dusk

Once Dusk is installed, you should register the Laravel\Dusk\DuskServiceProvider service provider. Typically, this will be done automatically via Laravel’s automatic service provider registration.

{note} If you are manually registering Dusk’s service provider, you should never register it in your production environment, as doing so could lead to arbitrary users being able to authenticate with your application.

After installing the Dusk package, run the dusk:install Artisan command:

php artisan dusk:install

A Browser directory will be created within your tests directory and will contain an example test. Next, set the APP_URL environment variable in your .env file. This value should match the URL you use to access your application in a browser.

To run your tests, use the dusk Artisan command. The dusk command accepts any argument that is also accepted by the phpunit command:

php artisan dusk

<a name=“using-other-browsers”></a>

19.2.1 Using Other Browsers

By default, Dusk uses Google Chrome and a standalone ChromeDriver installation to run your browser tests. However, you may start your own Selenium server and run your tests against any browser you wish.

To get started, open your tests/DuskTestCase.php file, which is the base Dusk test case for your application. Within this file, you can remove the call to the startChromeDriver method. This will stop Dusk from automatically starting the ChromeDriver:

/**
 * Prepare for Dusk test execution.
 *
 * @beforeClass
 * @return void
 */
public static function prepare()
{
    // static::startChromeDriver();
}

Next, you may modify the driver method to connect to the URL and port of your choice. In addition, you may modify the “desired capabilities” that should be passed to the WebDriver:

/**
 * Create the RemoteWebDriver instance.
 *
 * @return \Facebook\WebDriver\Remote\RemoteWebDriver
 */
protected function driver()
{
    return RemoteWebDriver::create(
        'http://localhost:4444/wd/hub', DesiredCapabilities::phantomjs()
    );
}

<a name=“getting-started”></a>

19.3 Getting Started

<a name=“generating-tests”></a>

19.3.1 Generating Tests

To generate a Dusk test, use the dusk:make Artisan command. The generated test will be placed in the tests/Browser directory:

php artisan dusk:make LoginTest

<a name=“running-tests”></a>

19.3.2 Running Tests

To run your browser tests, use the dusk Artisan command:

php artisan dusk

The dusk command accepts any argument that is normally accepted by the PHPUnit test runner, allowing you to only run the tests for a given group, etc:

php artisan dusk --group=foo

19.3.2.1 Manually Starting ChromeDriver

By default, Dusk will automatically attempt to start ChromeDriver. If this does not work for your particular system, you may manually start ChromeDriver before running the dusk command. If you choose to start ChromeDriver manually, you should comment out the following line of your tests/DuskTestCase.php file:

/**
 * Prepare for Dusk test execution.
 *
 * @beforeClass
 * @return void
 */
public static function prepare()
{
    // static::startChromeDriver();
}

In addition, if you start ChromeDriver on a port other than 9515, you should modify the driver method of the same class:

/**
 * Create the RemoteWebDriver instance.
 *
 * @return \Facebook\WebDriver\Remote\RemoteWebDriver
 */
protected function driver()
{
    return RemoteWebDriver::create(
        'http://localhost:9515', DesiredCapabilities::chrome()
    );
}

<a name=“environment-handling”></a>

19.3.3 Environment Handling

To force Dusk to use its own environment file when running tests, create a .env.dusk.{environment} file in the root of your project. For example, if you will be initiating the dusk command from your local environment, you should create a .env.dusk.local file.

When running tests, Dusk will back-up your .env file and rename your Dusk environment to .env. Once the tests have completed, your .env file will be restored.

<a name=“creating-browsers”></a>

19.3.4 Creating Browsers

To get started, let’s write a test that verifies we can log into our application. After generating a test, we can modify it to navigate to the login page, enter some credentials, and click the “Login” button. To create a browser instance, call the browse method:

<?php

namespace Tests\Browser;

use App\User;
use Tests\DuskTestCase;
use Laravel\Dusk\Chrome;
use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends DuskTestCase
{
    use DatabaseMigrations;

    /**
     * A basic browser test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $user = factory(User::class)->create([
            'email' => 'taylor@laravel.com',
        ]);

        $this->browse(function ($browser) use ($user) {
            $browser->visit('/login')
                    ->type('email', $user->email)
                    ->type('password', 'secret')
                    ->press('Login')
                    ->assertPathIs('/home');
        });
    }
}

As you can see in the example above, the browse method accepts a callback. A browser instance will automatically be passed to this callback by Dusk and is the main object used to interact with and make assertions against your application.

{tip} This test can be used to test the login screen generated by the make:auth Artisan command.

19.3.4.1 Creating Multiple Browsers

Sometimes you may need multiple browsers in order to properly carry out a test. For example, multiple browsers may be needed to test a chat screen that interacts with websockets. To create multiple browsers, “ask” for more than one browser in the signature of the callback given to the browse method:

$this->browse(function ($first, $second) {
    $first->loginAs(User::find(1))
          ->visit('/home')
          ->waitForText('Message');

    $second->loginAs(User::find(2))
           ->visit('/home')
           ->waitForText('Message')
           ->type('message', 'Hey Taylor')
           ->press('Send');

    $first->waitForText('Hey Taylor')
          ->assertSee('Jeffrey Way');
});

19.3.4.2 Resizing Browser Windows

You may use the resize method to adjust the size of the browser window:

$browser->resize(1920, 1080);

The maximize method may be used to maximize the browser window:

$browser->maximize();

<a name=“authentication”></a>

19.3.5 Authentication

Often, you will be testing pages that require authentication. You can use Dusk’s loginAs method in order to avoid interacting with the login screen during every test. The loginAs method accepts a user ID or user model instance:

$this->browse(function ($first, $second) {
    $first->loginAs(User::find(1))
          ->visit('/home');
});

{note} After using the loginAs method, the user session will be maintained for all tests within the file.

<a name=“migrations”></a>

19.3.6 Database Migrations

When your test requires migrations, like the authentication example above, you should never use the RefreshDatabase trait. The RefreshDatabase trait leverages database transactions which will not be applicable across HTTP requests. Instead, use the DatabaseMigrations trait:

<?php

namespace Tests\Browser;

use App\User;
use Tests\DuskTestCase;
use Laravel\Dusk\Chrome;
use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends DuskTestCase
{
    use DatabaseMigrations;
}

<a name=“interacting-with-elements”></a>

19.4 Interacting With Elements

<a name=“dusk-selectors”></a>

19.4.1 Dusk Selectors

Choosing good CSS selectors for interacting with elements is one of the hardest parts of writing Dusk tests. Over time, frontend changes can cause CSS selectors like the following to break your tests:

// HTML...

<button>Login</button>

// Test...

$browser->click('.login-page .container div > button');

Dusk selectors allow you to focus on writing effective tests rather than remembering CSS selectors. To define a selector, add a dusk attribute to your HTML element. Then, prefix the selector with @ to manipulate the attached element within a Dusk test:

// HTML...

<button dusk="login-button">Login</button>

// Test...

$browser->click('@login-button');

<a name=“clicking-links”></a>

To click a link, you may use the clickLink method on the browser instance. The clickLink method will click the link that has the given display text:

$browser->clickLink($linkText);

{note} This method interacts with jQuery. If jQuery is not available on the page, Dusk will automatically inject it into the page so it is available for the test’s duration.

<a name=“text-values-and-attributes”></a>

19.4.3 Text, Values, & Attributes

19.4.3.1 Retrieving & Setting Values

Dusk provides several methods for interacting with the current display text, value, and attributes of elements on the page. For example, to get the “value” of an element that matches a given selector, use the value method:

// Retrieve the value...
$value = $browser->value('selector');

// Set the value...
$browser->value('selector', 'value');

19.4.3.2 Retrieving Text

The text method may be used to retrieve the display text of an element that matches the given selector:

$text = $browser->text('selector');

19.4.3.3 Retrieving Attributes

Finally, the attribute method may be used to retrieve an attribute of an element matching the given selector:

$attribute = $browser->attribute('selector', 'value');

<a name=“using-forms”></a>

19.4.4 Using Forms

19.4.4.1 Typing Values

Dusk provides a variety of methods for interacting with forms and input elements. First, let’s take a look at an example of typing text into an input field:

$browser->type('email', 'taylor@laravel.com');

Note that, although the method accepts one if necessary, we are not required to pass a CSS selector into the type method. If a CSS selector is not provided, Dusk will search for an input field with the given name attribute. Finally, Dusk will attempt to find a textarea with the given name attribute.

To append text to a field without clearing its content, you may use the append method:

$browser->type('tags', 'foo')
        ->append('tags', ', bar, baz');

You may clear the value of an input using the clear method:

$browser->clear('email');

To select a value in a dropdown selection box, you may use the select method. Like the type method, the select method does not require a full CSS selector. When passing a value to the select method, you should pass the underlying option value instead of the display text:

$browser->select('size', 'Large');

You may select a random option by omitting the second parameter:

$browser->select('size');

19.4.4.3 Checkboxes

To “check” a checkbox field, you may use the check method. Like many other input related methods, a full CSS selector is not required. If an exact selector match can’t be found, Dusk will search for a checkbox with a matching name attribute:

$browser->check('terms');

$browser->uncheck('terms');

19.4.4.4 Radio Buttons

To “select” a radio button option, you may use the radio method. Like many other input related methods, a full CSS selector is not required. If an exact selector match can’t be found, Dusk will search for a radio with matching name and value attributes:

$browser->radio('version', 'php7');

<a name=“attaching-files”></a>

19.4.5 Attaching Files

The attach method may be used to attach a file to a file input element. Like many other input related methods, a full CSS selector is not required. If an exact selector match can’t be found, Dusk will search for a file input with matching name attribute:

$browser->attach('photo', __DIR__.'/photos/me.png');

<a name=“using-the-keyboard”></a>

19.4.6 Using The Keyboard

The keys method allows you to provide more complex input sequences to a given element than normally allowed by the type method. For example, you may hold modifier keys entering values. In this example, the shift key will be held while taylor is entered into the element matching the given selector. After taylor is typed, otwell will be typed without any modifier keys:

$browser->keys('selector', ['{shift}', 'taylor'], 'otwell');

You may even send a “hot key” to the primary CSS selector that contains your application:

$browser->keys('.app', ['{command}', 'j']);

{tip} All modifier keys are wrapped in {} characters, and match the constants defined in the Facebook\WebDriver\WebDriverKeys class, which can be found on GitHub.

<a name=“using-the-mouse”></a>

19.4.7 Using The Mouse

19.4.7.1 Clicking On Elements

The click method may be used to “click” on an element matching the given selector:

$browser->click('.selector');

19.4.7.2 Mouseover

The mouseover method may be used when you need to move the mouse over an element matching the given selector:

$browser->mouseover('.selector');

19.4.7.3 Drag & Drop

The drag method may be used to drag an element matching the given selector to another element:

$browser->drag('.from-selector', '.to-selector');

Or, you may drag an element in a single direction:

$browser->dragLeft('.selector', 10);
$browser->dragRight('.selector', 10);
$browser->dragUp('.selector', 10);
$browser->dragDown('.selector', 10);

<a name=“scoping-selectors”></a>

19.4.8 Scoping Selectors

Sometimes you may wish to perform several operations while scoping all of the operations within a given selector. For example, you may wish to assert that some text exists only within a table and then click a button within that table. You may use the with method to accomplish this. All operations performed within the callback given to the with method will be scoped to the original selector:

$browser->with('.table', function ($table) {
    $table->assertSee('Hello World')
          ->clickLink('Delete');
});

<a name=“waiting-for-elements”></a>

19.4.9 Waiting For Elements

When testing applications that use JavaScript extensively, it often becomes necessary to “wait” for certain elements or data to be available before proceeding with a test. Dusk makes this a cinch. Using a variety of methods, you may wait for elements to be visible on the page or even wait until a given JavaScript expression evaluates to true.

19.4.9.1 Waiting

If you need to pause the test for a given number of milliseconds, use the pause method:

$browser->pause(1000);

19.4.9.2 Waiting For Selectors

The waitFor method may be used to pause the execution of the test until the element matching the given CSS selector is displayed on the page. By default, this will pause the test for a maximum of five seconds before throwing an exception. If necessary, you may pass a custom timeout threshold as the second argument to the method:

// Wait a maximum of five seconds for the selector...
$browser->waitFor('.selector');

// Wait a maximum of one second for the selector...
$browser->waitFor('.selector', 1);

You may also wait until the given selector is missing from the page:

$browser->waitUntilMissing('.selector');

$browser->waitUntilMissing('.selector', 1);

19.4.9.3 Scoping Selectors When Available

Occasionally, you may wish to wait for a given selector and then interact with the element matching the selector. For example, you may wish to wait until a modal window is available and then press the “OK” button within the modal. The whenAvailable method may be used in this case. All element operations performed within the given callback will be scoped to the original selector:

$browser->whenAvailable('.modal', function ($modal) {
    $modal->assertSee('Hello World')
          ->press('OK');
});

19.4.9.4 Waiting For Text

The waitForText method may be used to wait until the given text is displayed on the page:

// Wait a maximum of five seconds for the text...
$browser->waitForText('Hello World');

// Wait a maximum of one second for the text...
$browser->waitForText('Hello World', 1);

The waitForLink method may be used to wait until the given link text is displayed on the page:

// Wait a maximum of five seconds for the link...
$browser->waitForLink('Create');

// Wait a maximum of one second for the link...
$browser->waitForLink('Create', 1);

19.4.9.6 Waiting On The Page Location

When making a path assertion such as $browser->assertPathIs('/home'), the assertion can fail if window.location.pathname is being updated asynchronously. You may use the waitForLocation method to wait for the location to be a given value:

$browser->waitForLocation('/secret');

19.4.9.7 Waiting for Page Reloads

If you need to make assertions after a page has been reloaded, use the waitForReload method:

$browser->click('.some-action')
        ->waitForReload()
        ->assertSee('something');

19.4.9.8 Waiting On JavaScript Expressions

Sometimes you may wish to pause the execution of a test until a given JavaScript expression evaluates to true. You may easily accomplish this using the waitUntil method. When passing an expression to this method, you do not need to include the return keyword or an ending semi-colon:

// Wait a maximum of five seconds for the expression to be true...
$browser->waitUntil('App.dataLoaded');

$browser->waitUntil('App.data.servers.length > 0');

// Wait a maximum of one second for the expression to be true...
$browser->waitUntil('App.data.servers.length > 0', 1);

19.4.9.9 Waiting With A Callback

Many of the “wait” methods in Dusk rely on the underlying waitUsing method. You may use this method directly to wait for a given callback to return true. The waitUsing method accepts the maximum number of seconds to wait, the interval at which the Closure should be evaluated, the Closure, and an optional failure message:

$browser->waitUsing(10, 1, function () use ($something) {
    return $something->isReady();
}, "Something wasn't ready in time.");

<a name=“making-vue-assertions”></a>

19.4.10 Making Vue Assertions

Dusk even allows you to make assertions on the state of Vue component data. For example, imagine your application contains the following Vue component:

// HTML...

<profile dusk="profile-component"></profile>

// Component Definition...

Vue.component('profile', {
    template: '<div>{{ user.name }}</div>',

    data: function () {
        return {
            user: {
              name: 'Taylor'
            }
        };
    }
});

You may assert on the state of the Vue component like so:

/**
 * A basic Vue test example.
 *
 * @return void
 */
public function testVue()
{
    $this->browse(function (Browser $browser) {
        $browser->visit('/')
                ->assertVue('user.name', 'Taylor', '@profile-component');
    });
}

<a name=“available-assertions”></a>

19.5 Available Assertions

Dusk provides a variety of assertions that you may make against your application. All of the available assertions are documented in the table below:

Assertion Description
$browser->assertTitle($title) Assert the page title matches the given text.
$browser->assertTitleContains($title) Assert the page title contains the given text.
$browser->assertUrlIs($url) Assert that the current URL (without the query string) matches the given string.
$browser->assertPathBeginsWith($path) Assert that the current URL path begins with given path.
$browser->assertPathIs('/home') Assert the current path matches the given path.
$browser->assertPathIsNot('/home') Assert the current path does not match the given path.
$browser->assertRouteIs($name, $parameters) Assert the current URL matches the given named route’s URL.
$browser->assertQueryStringHas($name, $value) Assert the given query string parameter is present and has a given value.
$browser->assertQueryStringMissing($name) Assert the given query string parameter is missing.
$browser->assertHasQueryStringParameter($name) Assert that the given query string parameter is present.
$browser->assertHasCookie($name) Assert the given cookie is present.
$browser->assertCookieMissing($name) Assert that the given cookie is not present.
$browser->assertCookieValue($name, $value) Assert a cookie has a given value.
$browser->assertPlainCookieValue($name, $value) Assert an unencrypted cookie has a given value.
$browser->assertSee($text) Assert the given text is present on the page.
$browser->assertDontSee($text) Assert the given text is not present on the page.
$browser->assertSeeIn($selector, $text) Assert the given text is present within the selector.
$browser->assertDontSeeIn($selector, $text) Assert the given text is not present within the selector.
$browser->assertSourceHas($code) Assert that the given source code is present on the page.
$browser->assertSourceMissing($code) Assert that the given source code is not present on the page.
$browser->assertSeeLink($linkText) Assert the given link is present on the page.
$browser->assertDontSeeLink($linkText) Assert the given link is not present on the page.
$browser->assertInputValue($field, $value) Assert the given input field has the given value.
$browser->assertInputValueIsNot($field, $value) Assert the given input field does not have the given value.
$browser->assertChecked($field) Assert the given checkbox is checked.
$browser->assertNotChecked($field) Assert the given checkbox is not checked.
$browser->assertRadioSelected($field, $value) Assert the given radio field is selected.
$browser->assertRadioNotSelected($field, $value) Assert the given radio field is not selected.
$browser->assertSelected($field, $value) Assert the given dropdown has the given value selected.
$browser->assertNotSelected($field, $value) Assert the given dropdown does not have the given value selected.
$browser->assertSelectHasOptions($field, $values) Assert that the given array of values are available to be selected.
$browser->assertSelectMissingOptions($field, $values) Assert that the given array of values are not available to be selected.
$browser->assertSelectHasOption($field, $value) Assert that the given value is available to be selected on the given field.
$browser->assertValue($selector, $value) Assert the element matching the given selector has the given value.
$browser->assertVisible($selector) Assert the element matching the given selector is visible.
$browser->assertMissing($selector) Assert the element matching the given selector is not visible.
$browser->assertDialogOpened($message) Assert that a JavaScript dialog with given message has been opened.
$browser->assertVue($property, $value, $component) Assert that a given Vue component data property matches the given value.
$browser->assertVueIsNot($property, $value, $component) Assert that a given Vue component data property does not match the given value.

<a name=“pages”></a>

19.6 Pages

Sometimes, tests require several complicated actions to be performed in sequence. This can make your tests harder to read and understand. Pages allow you to define expressive actions that may then be performed on a given page using a single method. Pages also allow you to define short-cuts to common selectors for your application or a single page.

<a name=“generating-pages”></a>

19.6.1 Generating Pages

To generate a page object, use the dusk:page Artisan command. All page objects will be placed in the tests/Browser/Pages directory:

php artisan dusk:page Login

<a name=“configuring-pages”></a>

19.6.2 Configuring Pages

By default, pages have three methods: url, assert, and elements. We will discuss the url and assert methods now. The elements method will be discussed in more detail below.

19.6.2.1 The url Method

The url method should return the path of the URL that represents the page. Dusk will use this URL when navigating to the page in the browser:

/**
 * Get the URL for the page.
 *
 * @return string
 */
public function url()
{
    return '/login';
}

19.6.2.2 The assert Method

The assert method may make any assertions necessary to verify that the browser is actually on the given page. Completing this method is not necessary; however, you are free to make these assertions if you wish. These assertions will be run automatically when navigating to the page:

/**
 * Assert that the browser is on the page.
 *
 * @return void
 */
public function assert(Browser $browser)
{
    $browser->assertPathIs($this->url());
}

<a name=“navigating-to-pages”></a>

Once a page has been configured, you may navigate to it using the visit method:

use Tests\Browser\Pages\Login;

$browser->visit(new Login);

Sometimes you may already be on a given page and need to “load” the page’s selectors and methods into the current test context. This is common when pressing a button and being redirected to a given page without explicitly navigating to it. In this situation, you may use the on method to load the page:

use Tests\Browser\Pages\CreatePlaylist;

$browser->visit('/dashboard')
        ->clickLink('Create Playlist')
        ->on(new CreatePlaylist)
        ->assertSee('@create');

<a name=“shorthand-selectors”></a>

19.6.4 Shorthand Selectors

The elements method of pages allows you to define quick, easy-to-remember shortcuts for any CSS selector on your page. For example, let’s define a shortcut for the “email” input field of the application’s login page:

/**
 * Get the element shortcuts for the page.
 *
 * @return array
 */
public function elements()
{
    return [
        '@email' => 'input[name=email]',
    ];
}

Now, you may use this shorthand selector anywhere you would use a full CSS selector:

$browser->type('@email', 'taylor@laravel.com');

19.6.4.1 Global Shorthand Selectors

After installing Dusk, a base Page class will be placed in your tests/Browser/Pages directory. This class contains a siteElements method which may be used to define global shorthand selectors that should be available on every page throughout your application:

/**
 * Get the global element shortcuts for the site.
 *
 * @return array
 */
public static function siteElements()
{
    return [
        '@element' => '#selector',
    ];
}

<a name=“page-methods”></a>

19.6.5 Page Methods

In addition to the default methods defined on pages, you may define additional methods which may be used throughout your tests. For example, let’s imagine we are building a music management application. A common action for one page of the application might be to create a playlist. Instead of re-writing the logic to create a playlist in each test, you may define a createPlaylist method on a page class:

<?php

namespace Tests\Browser\Pages;

use Laravel\Dusk\Browser;

class Dashboard extends Page
{
    // Other page methods...

    /**
     * Create a new playlist.
     *
     * @param  \Laravel\Dusk\Browser  $browser
     * @param  string  $name
     * @return void
     */
    public function createPlaylist(Browser $browser, $name)
    {
        $browser->type('name', $name)
                ->check('share')
                ->press('Create Playlist');
    }
}

Once the method has been defined, you may use it within any test that utilizes the page. The browser instance will automatically be passed to the page method:

use Tests\Browser\Pages\Dashboard;

$browser->visit(new Dashboard)
        ->createPlaylist('My Playlist')
        ->assertSee('My Playlist');

<a name=“components”></a>

19.7 Components

Components are similar to Dusk’s “page objects”, but are intended for pieces of UI and functionality that are re-used throughout your application, such as a navigation bar or notification window. As such, components are not bound to specific URLs.

<a name=“generating-components”></a>

19.7.1 Generating Components

To generate a component, use the dusk:component Artisan command. New components are placed in the test/Browser/Components directory:

php artisan dusk:component DatePicker

As shown above, a “date picker” is an example of a component that might exist throughout your application on a variety of pages. It can become cumbersome to manually write the browser automation logic to select a date in dozens of tests throughout your test suite. Instead, we can define a Dusk component to represent the date picker, allowing us to encapsulate that logic within the component:

<?php

namespace Tests\Browser\Components;

use Laravel\Dusk\Browser;
use Laravel\Dusk\Component as BaseComponent;

class DatePicker extends BaseComponent
{
    /**
     * Get the root selector for the component.
     *
     * @return string
     */
    public function selector()
    {
        return '.date-picker';
    }

    /**
     * Assert that the browser page contains the component.
     *
     * @param  Browser  $browser
     * @return void
     */
    public function assert(Browser $browser)
    {
        $browser->assertVisible($this->selector());
    }

    /**
     * Get the element shortcuts for the component.
     *
     * @return array
     */
    public function elements()
    {
        return [
            '@date-field' => 'input.datepicker-input',
            '@month-list' => 'div > div.datepicker-months',
            '@day-list' => 'div > div.datepicker-days',
        ];
    }

    /**
     * Select the given date.
     *
     * @param  \Laravel\Dusk\Browser  $browser
     * @param  int  $month
     * @param  int  $year
     * @return void
     */
    public function selectDate($browser, $month, $year)
    {
        $browser->click('@date-field')
                ->within('@month-list', function ($browser) use ($month) {
                    $browser->click($month);
                })
                ->within('@day-list', function ($browser) use ($day) {
                    $browser->click($day);
                });
    }
}

<a name=“using-components”></a>

19.7.2 Using Components

Once the component has been defined, we can easily select a date within the date picker from any test. And, if the logic necessary to select a date changes, we only need to update the component:

<?php

namespace Tests\Browser;

use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Tests\Browser\Components\DatePicker;
use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends DuskTestCase
{
    /**
     * A basic component test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->browse(function (Browser $browser) {
            $browser->visit('/')
                    ->within(new DatePicker, function ($browser) {
                        $browser->selectDate(1, 2018);
                    })
                    ->assertSee('January');
        });
    }
}

<a name=“continuous-integration”></a>

19.8 Continuous Integration

<a name=“running-tests-on-travis-ci”></a>

19.8.1 Travis CI

To run your Dusk tests on Travis CI, we will need to use the “sudo-enabled” Ubuntu 14.04 (Trusty) environment. Since Travis CI is not a graphical environment, we will need to take some extra steps in order to launch a Chrome browser. In addition, we will use php artisan serve to launch PHP’s built-in web server:

sudo: required
dist: trusty

addons:
   chrome: stable

install:
   - cp .env.testing .env
   - travis_retry composer install --no-interaction --prefer-dist --no-suggest

before_script:
   - google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost &
   - php artisan serve &

script:
   - php artisan dusk

<a name=“running-tests-on-circle-ci”></a>

19.8.2 CircleCI

19.8.2.1 CircleCI 1.0

If you are using CircleCI 1.0 to run your Dusk tests, you may use this configuration file as a starting point. Like TravisCI, we will use the php artisan serve command to launch PHP’s built-in web server:

dependencies:
  pre:
      - curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
      - sudo dpkg -i google-chrome.deb
      - sudo sed -i 's|HERE/chrome\"|HERE/chrome\" --disable-setuid-sandbox|g' /opt/google/chrome/google-chrome
      - rm google-chrome.deb

test:
    pre:
        - "./vendor/laravel/dusk/bin/chromedriver-linux":
            background: true
        - cp .env.testing .env
        - "php artisan serve":
            background: true

    override:
        - php artisan dusk

#### CircleCI 2.0

If you are using CircleCI 2.0 to run your Dusk tests, you may add these steps to your build:

 version: 2
 jobs:
     build:
         steps:
            - run: sudo apt-get install -y libsqlite3-dev
            - run: cp .env.testing .env
            - run: composer install -n --ignore-platform-reqs
            - run: npm install
            - run: npm run production
            - run: vendor/bin/phpunit

            - run:
               name: Start Chrome Driver
               command: ./vendor/laravel/dusk/bin/chromedriver-linux
               background: true

            - run:
               name: Run Laravel Server
               command: php artisan serve
               background: true

            - run:
               name: Run Laravel Dusk Tests
               command: php artisan dusk

<a name=“running-tests-on-codeship”></a>

19.8.3 Codeship

To run Dusk tests on Codeship, add the following commands to your Codeship project. Of course, these commands are a starting point and you are free to add additional commands as needed:

phpenv local 7.1
cp .env.testing .env
composer install --no-interaction
nohup bash -c "./vendor/laravel/dusk/bin/chromedriver-linux 2>&1 &"
nohup bash -c "php artisan serve 2>&1 &" && sleep 5
php artisan dusk

20 Eloquent: Collections

<a name=“introduction”></a>

20.1 Introduction

All multi-result sets returned by Eloquent are instances of the Illuminate\Database\Eloquent\Collection object, including results retrieved via the get method or accessed via a relationship. The Eloquent collection object extends the Laravel base collection, so it naturally inherits dozens of methods used to fluently work with the underlying array of Eloquent models.

Of course, all collections also serve as iterators, allowing you to loop over them as if they were simple PHP arrays:

$users = App\User::where('active', 1)->get();

foreach ($users as $user) {
    echo $user->name;
}

However, collections are much more powerful than arrays and expose a variety of map / reduce operations that may be chained using an intuitive interface. For example, let’s remove all inactive models and gather the first name for each remaining user:

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

$names = $users->reject(function ($user) {
    return $user->active === false;
})
->map(function ($user) {
    return $user->name;
});

{note} While most Eloquent collection methods return a new instance of an Eloquent collection, the pluck, keys, zip, collapse, flatten and flip methods return a base collection instance. Likewise, if a map operation returns a collection that does not contain any Eloquent models, it will be automatically cast to a base collection.

<a name=“available-methods”></a>

20.2 Available Methods

20.2.1 The Base Collection

All Eloquent collections extend the base Laravel collection object; therefore, they inherit all of the powerful methods provided by the base collection class:

<style>
#collection-method-list > p {
column-count: 3; -moz-column-count: 3; -webkit-column-count: 3;
column-gap: 2em; -moz-column-gap: 2em; -webkit-column-gap: 2em;
}

#collection-method-list a {
    display: block;
}

</style>

<div id=“collection-method-list” markdown=“1”>

all
average
avg
chunk
collapse
combine
concat
contains
containsStrict
count
crossJoin
dd
diff
diffKeys
dump
each
eachSpread
every
except
filter
first
flatMap
flatten
flip
forget
forPage
get
groupBy
has
implode
intersect
isEmpty
isNotEmpty
keyBy
keys
last
map
mapInto
mapSpread
mapToGroups
mapWithKeys
max
median
merge
min
mode
nth
only
pad
partition
pipe
pluck
pop
prepend
pull
push
put
random
reduce
reject
reverse
search
shift
shuffle
slice
sort
sortBy
sortByDesc
splice
split
sum
take
tap
toArray
toJson
transform
union
unique
uniqueStrict
unless
values
when
where
whereStrict
whereIn
whereInStrict
whereNotIn
whereNotInStrict
zip

</div>

<a name=“custom-collections”></a>

20.3 Custom Collections

If you need to use a custom Collection object with your own extension methods, you may override the newCollection method on your model:

<?php

namespace App;

use App\CustomCollection;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Create a new Eloquent Collection instance.
     *
     * @param  array  $models
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function newCollection(array $models = [])
    {
        return new CustomCollection($models);
    }
}

Once you have defined a newCollection method, you will receive an instance of your custom collection anytime Eloquent returns a Collection instance of that model. If you would like to use a custom collection for every model in your application, you should override the newCollection method on a base model class that is extended by all of your models.

21 Eloquent: Mutators

<a name=“introduction”></a>

21.1 Introduction

Accessors and mutators allow you to format Eloquent attribute values when you retrieve or set them on model instances. For example, you may want to use the Laravel encrypter to encrypt a value while it is stored in the database, and then automatically decrypt the attribute when you access it on an Eloquent model.

In addition to custom accessors and mutators, Eloquent can also automatically cast date fields to Carbon instances or even cast text fields to JSON.

<a name=“accessors-and-mutators”></a>

21.2 Accessors & Mutators

<a name=“defining-an-accessor”></a>

21.2.1 Defining An Accessor

To define an accessor, create a getFooAttribute method on your model where Foo is the “studly” cased name of the column you wish to access. In this example, we’ll define an accessor for the first_name attribute. The accessor will automatically be called by Eloquent when attempting to retrieve the value of the first_name attribute:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Get the user's first name.
     *
     * @param  string  $value
     * @return string
     */
    public function getFirstNameAttribute($value)
    {
        return ucfirst($value);
    }
}

As you can see, the original value of the column is passed to the accessor, allowing you to manipulate and return the value. To access the value of the accessor, you may access the first_name attribute on a model instance:

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

$firstName = $user->first_name;

Of course, you may also use accessors to return new, computed values from existing attributes:

/**
 * Get the user's full name.
 *
 * @return string
 */
public function getFullNameAttribute()
{
    return "{$this->first_name} {$this->last_name}";
}

<a name=“defining-a-mutator”></a>

21.2.2 Defining A Mutator

To define a mutator, define a setFooAttribute method on your model where Foo is the “studly” cased name of the column you wish to access. So, again, let’s define a mutator for the first_name attribute. This mutator will be automatically called when we attempt to set the value of the first_name attribute on the model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Set the user's first name.
     *
     * @param  string  $value
     * @return void
     */
    public function setFirstNameAttribute($value)
    {
        $this->attributes['first_name'] = strtolower($value);
    }
}

The mutator will receive the value that is being set on the attribute, allowing you to manipulate the value and set the manipulated value on the Eloquent model’s internal $attributes property. So, for example, if we attempt to set the first_name attribute to Sally:

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

$user->first_name = 'Sally';

In this example, the setFirstNameAttribute function will be called with the value Sally. The mutator will then apply the strtolower function to the name and set its resulting value in the internal $attributes array.

<a name=“date-mutators”></a>

21.3 Date Mutators

By default, Eloquent will convert the created_at and updated_at columns to instances of Carbon, which extends the PHP DateTime class to provide an assortment of helpful methods. You may customize which dates are automatically mutated, and even completely disable this mutation, by overriding the $dates property of your model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be mutated to dates.
     *
     * @var array
     */
    protected $dates = [
        'created_at',
        'updated_at',
        'deleted_at'
    ];
}

When a column is considered a date, you may set its value to a UNIX timestamp, date string (Y-m-d), date-time string, and of course a DateTime / Carbon instance, and the date’s value will automatically be correctly stored in your database:

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

$user->deleted_at = now();

$user->save();

As noted above, when retrieving attributes that are listed in your $dates property, they will automatically be cast to Carbon instances, allowing you to use any of Carbon’s methods on your attributes:

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

return $user->deleted_at->getTimestamp();

21.3.0.1 Date Formats

By default, timestamps are formatted as 'Y-m-d H:i:s'. If you need to customize the timestamp format, set the $dateFormat property on your model. This property determines how date attributes are stored in the database, as well as their format when the model is serialized to an array or JSON:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The storage format of the model's date columns.
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

<a name=“attribute-casting”></a>

21.4 Attribute Casting

The $casts property on your model provides a convenient method of converting attributes to common data types. The $casts property should be an array where the key is the name of the attribute being cast and the value is the type you wish to cast the column to. The supported cast types are: integer, real, float, double, string, boolean, object, array, collection, date, datetime, and timestamp.

For example, let’s cast the is_admin attribute, which is stored in our database as an integer (0 or 1) to a boolean value:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'is_admin' => 'boolean',
    ];
}

Now the is_admin attribute will always be cast to a boolean when you access it, even if the underlying value is stored in the database as an integer:

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

if ($user->is_admin) {
    //
}

<a name=“array-and-json-casting”></a>

21.4.1 Array & JSON Casting

The array cast type is particularly useful when working with columns that are stored as serialized JSON. For example, if your database has a JSON or TEXT field type that contains serialized JSON, adding the array cast to that attribute will automatically deserialize the attribute to a PHP array when you access it on your Eloquent model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'options' => 'array',
    ];
}

Once the cast is defined, you may access the options attribute and it will automatically be deserialized from JSON into a PHP array. When you set the value of the options attribute, the given array will automatically be serialized back into JSON for storage:

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

$options = $user->options;

$options['key'] = 'value';

$user->options = $options;

$user->save();

22 Eloquent: Relationships

<a name=“introduction”></a>

22.1 Introduction

Database tables are often related to one another. For example, a blog post may have many comments, or an order could be related to the user who placed it. Eloquent makes managing and working with these relationships easy, and supports several different types of relationships:

<a name=“defining-relationships”></a>

22.2 Defining Relationships

Eloquent relationships are defined as methods on your Eloquent model classes. Since, like Eloquent models themselves, relationships also serve as powerful query builders, defining relationships as methods provides powerful method chaining and querying capabilities. For example, we may chain additional constraints on this posts relationship:

$user->posts()->where('active', 1)->get();

But, before diving too deep into using relationships, let’s learn how to define each type.

<a name=“one-to-one”></a>

22.2.1 One To One

A one-to-one relationship is a very basic relation. For example, a User model might be associated with one Phone. To define this relationship, we place a phone method on the User model. The phone method should call the hasOne method and return its result:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Get the phone record associated with the user.
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

The first argument passed to the hasOne method is the name of the related model. Once the relationship is defined, we may retrieve the related record using Eloquent’s dynamic properties. Dynamic properties allow you to access relationship methods as if they were properties defined on the model:

$phone = User::find(1)->phone;

Eloquent determines the foreign key of the relationship based on the model name. In this case, the Phone model is automatically assumed to have a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method:

return $this->hasOne('App\Phone', 'foreign_key');

Additionally, Eloquent assumes that the foreign key should have a value matching the id (or the custom $primaryKey) column of the parent. In other words, Eloquent will look for the value of the user’s id column in the user_id column of the Phone record. If you would like the relationship to use a value other than id, you may pass a third argument to the hasOne method specifying your custom key:

return $this->hasOne('App\Phone', 'foreign_key', 'local_key');

22.2.1.1 Defining The Inverse Of The Relationship

So, we can access the Phone model from our User. Now, let’s define a relationship on the Phone model that will let us access the User that owns the phone. We can define the inverse of a hasOne relationship using the belongsTo method:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Phone extends Model
{
    /**
     * Get the user that owns the phone.
     */
    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

In the example above, Eloquent will try to match the user_id from the Phone model to an id on the User model. Eloquent determines the default foreign key name by examining the name of the relationship method and suffixing the method name with _id. However, if the foreign key on the Phone model is not user_id, you may pass a custom key name as the second argument to the belongsTo method:

/**
 * Get the user that owns the phone.
 */
public function user()
{
    return $this->belongsTo('App\User', 'foreign_key');
}

If your parent model does not use id as its primary key, or you wish to join the child model to a different column, you may pass a third argument to the belongsTo method specifying your parent table’s custom key:

/**
 * Get the user that owns the phone.
 */
public function user()
{
    return $this->belongsTo('App\User', 'foreign_key', 'other_key');
}

<a name=“default-models”></a>

22.2.1.2 Default Models

The belongsTo relationship allows you to define a default model that will be returned if the given relationship is null. This pattern is often referred to as the Null Object pattern and can help remove conditional checks in your code. In the following example, the user relation will return an empty App\User model if no user is attached to the post:

/**
 * Get the author of the post.
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault();
}

To populate the default model with attributes, you may pass an array or Closure to the withDefault method:

/**
 * Get the author of the post.
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault([
        'name' => 'Guest Author',
    ]);
}

/**
 * Get the author of the post.
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault(function ($user) {
        $user->name = 'Guest Author';
    });
}

<a name=“one-to-many”></a>

22.2.2 One To Many

A “one-to-many” relationship is used to define relationships where a single model owns any amount of other models. For example, a blog post may have an infinite number of comments. Like all other Eloquent relationships, one-to-many relationships are defined by placing a function on your Eloquent model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    /**
     * Get the comments for the blog post.
     */
    public function comments()
    {
        return $this->hasMany('App\Comment');
    }
}

Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the “snake case” name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.

Once the relationship has been defined, we can access the collection of comments by accessing the comments property. Remember, since Eloquent provides “dynamic properties”, we can access relationship methods as if they were defined as properties on the model:

$comments = App\Post::find(1)->comments;

foreach ($comments as $comment) {
    //
}

Of course, since all relationships also serve as query builders, you can add further constraints to which comments are retrieved by calling the comments method and continuing to chain conditions onto the query:

$comments = App\Post::find(1)->comments()->where('title', 'foo')->first();

Like the hasOne method, you may also override the foreign and local keys by passing additional arguments to the hasMany method:

return $this->hasMany('App\Comment', 'foreign_key');

return $this->hasMany('App\Comment', 'foreign_key', 'local_key');

<a name=“one-to-many-inverse”></a>

22.2.3 One To Many (Inverse)

Now that we can access all of a post’s comments, let’s define a relationship to allow a comment to access its parent post. To define the inverse of a hasMany relationship, define a relationship function on the child model which calls the belongsTo method:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    /**
     * Get the post that owns the comment.
     */
    public function post()
    {
        return $this->belongsTo('App\Post');
    }
}

Once the relationship has been defined, we can retrieve the Post model for a Comment by accessing the post “dynamic property”:

$comment = App\Comment::find(1);

echo $comment->post->title;

In the example above, Eloquent will try to match the post_id from the Comment model to an id on the Post model. Eloquent determines the default foreign key name by examining the name of the relationship method and suffixing the method name with _id. However, if the foreign key on the Comment model is not post_id, you may pass a custom key name as the second argument to the belongsTo method:

/**
 * Get the post that owns the comment.
 */
public function post()
{
    return $this->belongsTo('App\Post', 'foreign_key');
}

If your parent model does not use id as its primary key, or you wish to join the child model to a different column, you may pass a third argument to the belongsTo method specifying your parent table’s custom key:

/**
 * Get the post that owns the comment.
 */
public function post()
{
    return $this->belongsTo('App\Post', 'foreign_key', 'other_key');
}

<a name=“many-to-many”></a>

22.2.4 Many To Many

Many-to-many relations are slightly more complicated than hasOne and hasMany relationships. An example of such a relationship is a user with many roles, where the roles are also shared by other users. For example, many users may have the role of “Admin”. To define this relationship, three database tables are needed: users, roles, and role_user. The role_user table is derived from the alphabetical order of the related model names, and contains the user_id and role_id columns.

Many-to-many relationships are defined by writing a method that returns the result of the belongsToMany method. For example, let’s define the roles method on our User model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The roles that belong to the user.
     */
    public function roles()
    {
        return $this->belongsToMany('App\Role');
    }
}

Once the relationship is defined, you may access the user’s roles using the roles dynamic property:

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

foreach ($user->roles as $role) {
    //
}

Of course, like all other relationship types, you may call the roles method to continue chaining query constraints onto the relationship:

$roles = App\User::find(1)->roles()->orderBy('name')->get();

As mentioned previously, to determine the table name of the relationship’s joining table, Eloquent will join the two related model names in alphabetical order. However, you are free to override this convention. You may do so by passing a second argument to the belongsToMany method:

return $this->belongsToMany('App\Role', 'role_user');

In addition to customizing the name of the joining table, you may also customize the column names of the keys on the table by passing additional arguments to the belongsToMany method. The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to:

return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');

22.2.4.1 Defining The Inverse Of The Relationship

To define the inverse of a many-to-many relationship, you place another call to belongsToMany on your related model. To continue our user roles example, let’s define the users method on the Role model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    /**
     * The users that belong to the role.
     */
    public function users()
    {
        return $this->belongsToMany('App\User');
    }
}

As you can see, the relationship is defined exactly the same as its User counterpart, with the exception of referencing the App\User model. Since we’re reusing the belongsToMany method, all of the usual table and key customization options are available when defining the inverse of many-to-many relationships.

22.2.4.2 Retrieving Intermediate Table Columns

As you have already learned, working with many-to-many relations requires the presence of an intermediate table. Eloquent provides some very helpful ways of interacting with this table. For example, let’s assume our User object has many Role objects that it is related to. After accessing this relationship, we may access the intermediate table using the pivot attribute on the models:

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

foreach ($user->roles as $role) {
    echo $role->pivot->created_at;
}

Notice that each Role model we retrieve is automatically assigned a pivot attribute. This attribute contains a model representing the intermediate table, and may be used like any other Eloquent model.

By default, only the model keys will be present on the pivot object. If your pivot table contains extra attributes, you must specify them when defining the relationship:

return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');

If you want your pivot table to have automatically maintained created_at and updated_at timestamps, use the withTimestamps method on the relationship definition:

return $this->belongsToMany('App\Role')->withTimestamps();

22.2.4.3 Customizing The pivot Attribute Name

As noted earlier, attributes from the intermediate table may be accessed on models using the pivot attribute. However, you are free to customize the name of this attribute to better reflect its purpose within your application.

For example, if your application contains users that may subscribe to podcasts, you probably have a many-to-many relationship between users and podcasts. If this is the case, you may wish to rename your intermediate table accessor to subscription instead of pivot. This can be done using the as method when defining the relationship:

return $this->belongsToMany('App\Podcast')
                ->as('subscription')
                ->withTimestamps();

Once this is done, you may access the intermediate table data using the customized name:

$users = User::with('podcasts')->get();

foreach ($users->flatMap->podcasts as $podcast) {
    echo $podcast->subscription->created_at;
}

22.2.4.4 Filtering Relationships Via Intermediate Table Columns

You can also filter the results returned by belongsToMany using the wherePivot and wherePivotIn methods when defining the relationship:

return $this->belongsToMany('App\Role')->wherePivot('approved', 1);

return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);

22.2.4.5 Defining Custom Intermediate Table Models

If you would like to define a custom model to represent the intermediate table of your relationship, you may call the using method when defining the relationship. All custom models used to represent intermediate tables of relationships must extend the Illuminate\Database\Eloquent\Relations\Pivot class. For example, we may define a Role which uses a custom UserRole pivot model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    /**
     * The users that belong to the role.
     */
    public function users()
    {
        return $this->belongsToMany('App\User')->using('App\UserRole');
    }
}

When defining the UserRole model, we will extend the Pivot class:

<?php

namespace App;

use Illuminate\Database\Eloquent\Relations\Pivot;

class UserRole extends Pivot
{
    //
}

<a name=“has-many-through”></a>

22.2.5 Has Many Through

The “has-many-through” relationship provides a convenient shortcut for accessing distant relations via an intermediate relation. For example, a Country model might have many Post models through an intermediate User model. In this example, you could easily gather all blog posts for a given country. Let’s look at the tables required to define this relationship:

countries
    id - integer
    name - string

users
    id - integer
    country_id - integer
    name - string

posts
    id - integer
    user_id - integer
    title - string

Though posts does not contain a country_id column, the hasManyThrough relation provides access to a country’s posts via $country->posts. To perform this query, Eloquent inspects the country_id on the intermediate users table. After finding the matching user IDs, they are used to query the posts table.

Now that we have examined the table structure for the relationship, let’s define it on the Country model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Country extends Model
{
    /**
     * Get all of the posts for the country.
     */
    public function posts()
    {
        return $this->hasManyThrough('App\Post', 'App\User');
    }
}

The first argument passed to the hasManyThrough method is the name of the final model we wish to access, while the second argument is the name of the intermediate model.

Typical Eloquent foreign key conventions will be used when performing the relationship’s queries. If you would like to customize the keys of the relationship, you may pass them as the third and fourth arguments to the hasManyThrough method. The third argument is the name of the foreign key on the intermediate model. The fourth argument is the name of the foreign key on the final model. The fifth argument is the local key, while the sixth argument is the local key of the intermediate model:

class Country extends Model
{
    public function posts()
    {
        return $this->hasManyThrough(
            'App\Post',
            'App\User',
            'country_id', // Foreign key on users table...
            'user_id', // Foreign key on posts table...
            'id', // Local key on countries table...
            'id' // Local key on users table...
        );
    }
}

<a name=“polymorphic-relations”></a>

22.2.6 Polymorphic Relations

22.2.6.1 Table Structure

Polymorphic relations allow a model to belong to more than one other model on a single association. For example, imagine users of your application can “comment” both posts and videos. Using polymorphic relationships, you can use a single comments table for both of these scenarios. First, let’s examine the table structure required to build this relationship:

posts
    id - integer
    title - string
    body - text

videos
    id - integer
    title - string
    url - string

comments
    id - integer
    body - text
    commentable_id - integer
    commentable_type - string

Two important columns to note are the commentable_id and commentable_type columns on the comments table. The commentable_id column will contain the ID value of the post or video, while the commentable_type column will contain the class name of the owning model. The commentable_type column is how the ORM determines which “type” of owning model to return when accessing the commentable relation.

22.2.6.2 Model Structure

Next, let’s examine the model definitions needed to build this relationship:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    /**
     * Get all of the owning commentable models.
     */
    public function commentable()
    {
        return $this->morphTo();
    }
}

class Post extends Model
{
    /**
     * Get all of the post's comments.
     */
    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }
}

class Video extends Model
{
    /**
     * Get all of the video's comments.
     */
    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }
}

22.2.6.3 Retrieving Polymorphic Relations

Once your database table and models are defined, you may access the relationships via your models. For example, to access all of the comments for a post, we can use the comments dynamic property:

$post = App\Post::find(1);

foreach ($post->comments as $comment) {
    //
}

You may also retrieve the owner of a polymorphic relation from the polymorphic model by accessing the name of the method that performs the call to morphTo. In our case, that is the commentable method on the Comment model. So, we will access that method as a dynamic property:

$comment = App\Comment::find(1);

$commentable = $comment->commentable;

The commentable relation on the Comment model will return either a Post or Video instance, depending on which type of model owns the comment.

22.2.6.4 Custom Polymorphic Types

By default, Laravel will use the fully qualified class name to store the type of the related model. For instance, given the example above where a Comment may belong to a Post or a Video, the default commentable_type would be either App\Post or App\Video, respectively. However, you may wish to decouple your database from your application’s internal structure. In that case, you may define a relationship “morph map” to instruct Eloquent to use a custom name for each model instead of the class name:

use Illuminate\Database\Eloquent\Relations\Relation;

Relation::morphMap([
    'posts' => 'App\Post',
    'videos' => 'App\Video',
]);

You may register the morphMap in the boot function of your AppServiceProvider or create a separate service provider if you wish.

<a name=“many-to-many-polymorphic-relations”></a>

22.2.7 Many To Many Polymorphic Relations

22.2.7.1 Table Structure

In addition to traditional polymorphic relations, you may also define “many-to-many” polymorphic relations. For example, a blog Post and Video model could share a polymorphic relation to a Tag model. Using a many-to-many polymorphic relation allows you to have a single list of unique tags that are shared across blog posts and videos. First, let’s examine the table structure:

posts
    id - integer
    name - string

videos
    id - integer
    name - string

tags
    id - integer
    name - string

taggables
    tag_id - integer
    taggable_id - integer
    taggable_type - string

22.2.7.2 Model Structure

Next, we’re ready to define the relationships on the model. The Post and Video models will both have a tags method that calls the morphToMany method on the base Eloquent class:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    /**
     * Get all of the tags for the post.
     */
    public function tags()
    {
        return $this->morphToMany('App\Tag', 'taggable');
    }
}

22.2.7.3 Defining The Inverse Of The Relationship

Next, on the Tag model, you should define a method for each of its related models. So, for this example, we will define a posts method and a videos method:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
    /**
     * Get all of the posts that are assigned this tag.
     */
    public function posts()
    {
        return $this->morphedByMany('App\Post', 'taggable');
    }

    /**
     * Get all of the videos that are assigned this tag.
     */
    public function videos()
    {
        return $this->morphedByMany('App\Video', 'taggable');
    }
}

22.2.7.4 Retrieving The Relationship

Once your database table and models are defined, you may access the relationships via your models. For example, to access all of the tags for a post, you can use the tags dynamic property:

$post = App\Post::find(1);

foreach ($post->tags as $tag) {
    //
}

You may also retrieve the owner of a polymorphic relation from the polymorphic model by accessing the name of the method that performs the call to morphedByMany. In our case, that is the posts or videos methods on the Tag model. So, you will access those methods as dynamic properties:

$tag = App\Tag::find(1);

foreach ($tag->videos as $video) {
    //
}

<a name=“querying-relations”></a>

22.3 Querying Relations

Since all types of Eloquent relationships are defined via methods, you may call those methods to obtain an instance of the relationship without actually executing the relationship queries. In addition, all types of Eloquent relationships also serve as query builders, allowing you to continue to chain constraints onto the relationship query before finally executing the SQL against your database.

For example, imagine a blog system in which a User model has many associated Post models:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Get all of the posts for the user.
     */
    public function posts()
    {
        return $this->hasMany('App\Post');
    }
}

You may query the posts relationship and add additional constraints to the relationship like so:

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

$user->posts()->where('active', 1)->get();

You are able to use any of the query builder methods on the relationship, so be sure to explore the query builder documentation to learn about all of the methods that are available to you.

<a name=“relationship-methods-vs-dynamic-properties”></a>

22.3.1 Relationship Methods Vs. Dynamic Properties

If you do not need to add additional constraints to an Eloquent relationship query, you may access the relationship as if it were a property. For example, continuing to use our User and Post example models, we may access all of a user’s posts like so:

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

foreach ($user->posts as $post) {
    //
}

Dynamic properties are “lazy loading”, meaning they will only load their relationship data when you actually access them. Because of this, developers often use eager loading to pre-load relationships they know will be accessed after loading the model. Eager loading provides a significant reduction in SQL queries that must be executed to load a model’s relations.

<a name=“querying-relationship-existence”></a>

22.3.2 Querying Relationship Existence

When accessing the records for a model, you may wish to limit your results based on the existence of a relationship. For example, imagine you want to retrieve all blog posts that have at least one comment. To do so, you may pass the name of the relationship to the has and orHas methods:

// Retrieve all posts that have at least one comment...
$posts = App\Post::has('comments')->get();

You may also specify an operator and count to further customize the query:

// Retrieve all posts that have three or more comments...
$posts = App\Post::has('comments', '>=', 3)->get();

Nested has statements may also be constructed using “dot” notation. For example, you may retrieve all posts that have at least one comment and vote:

// Retrieve all posts that have at least one comment with votes...
$posts = App\Post::has('comments.votes')->get();

If you need even more power, you may use the whereHas and orWhereHas methods to put “where” conditions on your has queries. These methods allow you to add customized constraints to a relationship constraint, such as checking the content of a comment:

// Retrieve all posts with at least one comment containing words like foo%
$posts = App\Post::whereHas('comments', function ($query) {
    $query->where('content', 'like', 'foo%');
})->get();

<a name=“querying-relationship-absence”></a>

22.3.3 Querying Relationship Absence

When accessing the records for a model, you may wish to limit your results based on the absence of a relationship. For example, imagine you want to retrieve all blog posts that don’t have any comments. To do so, you may pass the name of the relationship to the doesntHave and orDoesntHave methods:

$posts = App\Post::doesntHave('comments')->get();

If you need even more power, you may use the whereDoesntHave and orWhereDoesntHave methods to put “where” conditions on your doesntHave queries. These methods allows you to add customized constraints to a relationship constraint, such as checking the content of a comment:

$posts = App\Post::whereDoesntHave('comments', function ($query) {
    $query->where('content', 'like', 'foo%');
})->get();

<a name=“counting-related-models”></a>

If you want to count the number of results from a relationship without actually loading them you may use the withCount method, which will place a {relation}_count column on your resulting models. For example:

$posts = App\Post::withCount('comments')->get();

foreach ($posts as $post) {
    echo $post->comments_count;
}

You may add the “counts” for multiple relations as well as add constraints to the queries:

$posts = App\Post::withCount(['votes', 'comments' => function ($query) {
    $query->where('content', 'like', 'foo%');
}])->get();

echo $posts[0]->votes_count;
echo $posts[0]->comments_count;

You may also alias the relationship count result, allowing multiple counts on the same relationship:

$posts = App\Post::withCount([
    'comments',
    'comments as pending_comments_count' => function ($query) {
        $query->where('approved', false);
    }
])->get();

echo $posts[0]->comments_count;

echo $posts[0]->pending_comments_count;

<a name=“eager-loading”></a>

22.4 Eager Loading

When accessing Eloquent relationships as properties, the relationship data is “lazy loaded”. This means the relationship data is not actually loaded until you first access the property. However, Eloquent can “eager load” relationships at the time you query the parent model. Eager loading alleviates the N + 1 query problem. To illustrate the N + 1 query problem, consider a Book model that is related to Author:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    /**
     * Get the author that wrote the book.
     */
    public function author()
    {
        return $this->belongsTo('App\Author');
    }
}

Now, let’s retrieve all books and their authors:

$books = App\Book::all();

foreach ($books as $book) {
    echo $book->author->name;
}

This loop will execute 1 query to retrieve all of the books on the table, then another query for each book to retrieve the author. So, if we have 25 books, this loop would run 26 queries: 1 for the original book, and 25 additional queries to retrieve the author of each book.

Thankfully, we can use eager loading to reduce this operation to just 2 queries. When querying, you may specify which relationships should be eager loaded using the with method:

$books = App\Book::with('author')->get();

foreach ($books as $book) {
    echo $book->author->name;
}

For this operation, only two queries will be executed:

select * from books

select * from authors where id in (1, 2, 3, 4, 5, ...)

22.4.0.1 Eager Loading Multiple Relationships

Sometimes you may need to eager load several different relationships in a single operation. To do so, just pass additional arguments to the with method:

$books = App\Book::with(['author', 'publisher'])->get();

22.4.0.2 Nested Eager Loading

To eager load nested relationships, you may use “dot” syntax. For example, let’s eager load all of the book’s authors and all of the author’s personal contacts in one Eloquent statement:

$books = App\Book::with('author.contacts')->get();

22.4.0.3 Eager Loading Specific Columns

You may not always need every column from the relationships you are retrieving. For this reason, Eloquent allows you to specify which columns of the relationship you would like to retrieve:

$users = App\Book::with('author:id,name')->get();

{note} When using this feature, you should always include the id column in the list of columns you wish to retrieve.

<a name=“constraining-eager-loads”></a>

22.4.1 Constraining Eager Loads

Sometimes you may wish to eager load a relationship, but also specify additional query constraints for the eager loading query. Here’s an example:

$users = App\User::with(['posts' => function ($query) {
    $query->where('title', 'like', '%first%');
}])->get();

In this example, Eloquent will only eager load posts where the post’s title column contains the word first. Of course, you may call other query builder methods to further customize the eager loading operation:

$users = App\User::with(['posts' => function ($query) {
    $query->orderBy('created_at', 'desc');
}])->get();

<a name=“lazy-eager-loading”></a>

22.4.2 Lazy Eager Loading

Sometimes you may need to eager load a relationship after the parent model has already been retrieved. For example, this may be useful if you need to dynamically decide whether to load related models:

$books = App\Book::all();

if ($someCondition) {
    $books->load('author', 'publisher');
}

If you need to set additional query constraints on the eager loading query, you may pass an array keyed by the relationships you wish to load. The array values should be Closure instances which receive the query instance:

$books->load(['author' => function ($query) {
    $query->orderBy('published_date', 'asc');
}]);

To load a relationship only when it has not already been loaded, use the loadMissing method:

public function format(Book $book)
{
    $book->loadMissing('author');

    return [
        'name' => $book->name,
        'author' => $book->author->name
    ];
}

<a name=“inserting-and-updating-related-models”></a>

<a name=“the-save-method”></a>

22.5.1 The Save Method

Eloquent provides convenient methods for adding new models to relationships. For example, perhaps you need to insert a new Comment for a Post model. Instead of manually setting the post_id attribute on the Comment, you may insert the Comment directly from the relationship’s save method:

$comment = new App\Comment(['message' => 'A new comment.']);

$post = App\Post::find(1);

$post->comments()->save($comment);

Notice that we did not access the comments relationship as a dynamic property. Instead, we called the comments method to obtain an instance of the relationship. The save method will automatically add the appropriate post_id value to the new Comment model.

If you need to save multiple related models, you may use the saveMany method:

$post = App\Post::find(1);

$post->comments()->saveMany([
    new App\Comment(['message' => 'A new comment.']),
    new App\Comment(['message' => 'Another comment.']),
]);

<a name=“the-create-method”></a>

22.5.2 The Create Method

In addition to the save and saveMany methods, you may also use the create method, which accepts an array of attributes, creates a model, and inserts it into the database. Again, the difference between save and create is that save accepts a full Eloquent model instance while create accepts a plain PHP array:

$post = App\Post::find(1);

$comment = $post->comments()->create([
    'message' => 'A new comment.',
]);

{tip} Before using the create method, be sure to review the documentation on attribute mass assignment.

You may use the createMany method to create multiple related models:

$post = App\Post::find(1);

$post->comments()->createMany([
    [
        'message' => 'A new comment.',
    ],
    [
        'message' => 'Another new comment.',
    ],
]);

<a name=“updating-belongs-to-relationships”></a>

22.5.3 Belongs To Relationships

When updating a belongsTo relationship, you may use the associate method. This method will set the foreign key on the child model:

$account = App\Account::find(10);

$user->account()->associate($account);

$user->save();

When removing a belongsTo relationship, you may use the dissociate method. This method will set the relationship’s foreign key to null:

$user->account()->dissociate();

$user->save();

<a name=“updating-many-to-many-relationships”></a>

22.5.4 Many To Many Relationships

22.5.4.1 Attaching / Detaching

Eloquent also provides a few additional helper methods to make working with related models more convenient. For example, let’s imagine a user can have many roles and a role can have many users. To attach a role to a user by inserting a record in the intermediate table that joins the models, use the attach method:

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

$user->roles()->attach($roleId);

When attaching a relationship to a model, you may also pass an array of additional data to be inserted into the intermediate table:

$user->roles()->attach($roleId, ['expires' => $expires]);

Of course, sometimes it may be necessary to remove a role from a user. To remove a many-to-many relationship record, use the detach method. The detach method will remove the appropriate record out of the intermediate table; however, both models will remain in the database:

// Detach a single role from the user...
$user->roles()->detach($roleId);

// Detach all roles from the user...
$user->roles()->detach();

For convenience, attach and detach also accept arrays of IDs as input:

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

$user->roles()->detach([1, 2, 3]);

$user->roles()->attach([
    1 => ['expires' => $expires],
    2 => ['expires' => $expires]
]);

22.5.4.2 Syncing Associations

You may also use the sync method to construct many-to-many associations. The sync method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table. So, after this operation is complete, only the IDs in the given array will exist in the intermediate table:

$user->roles()->sync([1, 2, 3]);

You may also pass additional intermediate table values with the IDs:

$user->roles()->sync([1 => ['expires' => true], 2, 3]);

If you do not want to detach existing IDs, you may use the syncWithoutDetaching method:

$user->roles()->syncWithoutDetaching([1, 2, 3]);

22.5.4.3 Toggling Associations

The many-to-many relationship also provides a toggle method which “toggles” the attachment status of the given IDs. If the given ID is currently attached, it will be detached. Likewise, if it is currently detached, it will be attached:

$user->roles()->toggle([1, 2, 3]);

22.5.4.4 Saving Additional Data On A Pivot Table

When working with a many-to-many relationship, the save method accepts an array of additional intermediate table attributes as its second argument:

App\User::find(1)->roles()->save($role, ['expires' => $expires]);

22.5.4.5 Updating A Record On A Pivot Table

If you need to update an existing row in your pivot table, you may use updateExistingPivot method. This method accepts the pivot record foreign key and an array of attributes to update:

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

$user->roles()->updateExistingPivot($roleId, $attributes);

<a name=“touching-parent-timestamps”></a>

22.6 Touching Parent Timestamps

When a model belongsTo or belongsToMany another model, such as a Comment which belongs to a Post, it is sometimes helpful to update the parent’s timestamp when the child model is updated. For example, when a Comment model is updated, you may want to automatically “touch” the updated_at timestamp of the owning Post. Eloquent makes it easy. Just add a touches property containing the names of the relationships to the child model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    /**
     * All of the relationships to be touched.
     *
     * @var array
     */
    protected $touches = ['post'];

    /**
     * Get the post that the comment belongs to.
     */
    public function post()
    {
        return $this->belongsTo('App\Post');
    }
}

Now, when you update a Comment, the owning Post will have its updated_at column updated as well, making it more convenient to know when to invalidate a cache of the Post model:

$comment = App\Comment::find(1);

$comment->text = 'Edit to this comment!';

$comment->save();

23 Eloquent: API Resources

<a name=“introduction”></a>

23.1 Introduction

When building an API, you may need a transformation layer that sits between your Eloquent models and the JSON responses that are actually returned to your application’s users. Laravel’s resource classes allow you to expressively and easily transform your models and model collections into JSON.

<a name=“generating-resources”></a>

23.2 Generating Resources

To generate a resource class, you may use the make:resource Artisan command. By default, resources will be placed in the app/Http/Resources directory of your application. Resources extend the Illuminate\Http\Resources\Json\Resource class:

php artisan make:resource UserResource

23.2.0.1 Resource Collections

In addition to generating resources that transform individual models, you may generate resources that are responsible for transforming collections of models. This allows your response to include links and other meta information that is relevant to an entire collection of a given resource.

To create a resource collection, you should use the --collection flag when creating the resource. Or, including the word Collection in the resource name will indicate to Laravel that it should create a collection resource. Collection resources extend the Illuminate\Http\Resources\Json\ResourceCollection class:

php artisan make:resource Users --collection

php artisan make:resource UserCollection

<a name=“concept-overview”></a>

23.3 Concept Overview

{tip} This is a high-level overview of resources and resource collections. You are highly encouraged to read the other sections of this documentation to gain a deeper understanding of the customization and power offered to you by resources.

Before diving into all of the options available to you when writing resources, let’s first take a high-level look at how resources are used within Laravel. A resource class represents a single model that needs to be transformed into a JSON structure. For example, here is a simple UserResource class:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;

class UserResource extends Resource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

Every resource class defines a toArray method which returns the array of attributes that should be converted to JSON when sending the response. Notice that we can access model properties directly from the $this variable. This is because a resource class will automatically proxy property and method access down to the underlying model for convenient access. Once the resource is defined, it may be returned from a route or controller:

use App\User;
use App\Http\Resources\UserResource;

Route::get('/user', function () {
    return new UserResource(User::find(1));
});

23.3.1 Resource Collections

If you are returning a collection of resources or a paginated response, you may use the collection method when creating the resource instance in your route or controller:

use App\User;
use App\Http\Resources\UserResource;

Route::get('/user', function () {
    return UserResource::collection(User::all());
});

Of course, this does not allow any addition of meta data that may need to be returned with the collection. If you would like to customize the resource collection response, you may create a dedicated resource to represent the collection:

php artisan make:resource UserCollection

Once the resource collection class has been generated, you may easily define any meta data that should be included with the response:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'data' => $this->collection,
            'links' => [
                'self' => 'link-value',
            ],
        ];
    }
}

After defining your resource collection, it may be returned from a route or controller:

use App\User;
use App\Http\Resources\UserCollection;

Route::get('/users', function () {
    return new UserCollection(User::all());
});

<a name=“writing-resources”></a>

23.4 Writing Resources

{tip} If you have not read the concept overview, you are highly encouraged to do so before proceeding with this documentation.

In essence, resources are simple. They only need to transform a given model into an array. So, each resource contains a toArray method which translates your model’s attributes into an API friendly array that can be returned to your users:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;

class UserResource extends Resource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

Once a resource has been defined, it may be returned directly from a route or controller:

use App\User;
use App\Http\Resources\UserResource;

Route::get('/user', function () {
    return new UserResource(User::find(1));
});

23.4.0.1 Relationships

If you would like to include related resources in your response, you may add them to the array returned by your toArray method. In this example, we will use the Post resource’s collection method to add the user’s blog posts to the resource response:

/**
 * Transform the resource into an array.
 *
 * @param  \Illuminate\Http\Request
 * @return array
 */
public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'posts' => Post::collection($this->posts),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

{tip} If you would like to include relationships only when they have already been loaded, check out the documentation on conditional relationships.

23.4.0.2 Resource Collections

While resources translate a single model into an array, resource collections translate a collection of models into an array. It is not absolutely necessary to define a resource collection class for each one of your model types since all resources provide a collection method to generate an “ad-hoc” resource collection on the fly:

use App\User;
use App\Http\Resources\UserResource;

Route::get('/user', function () {
    return UserResource::collection(User::all());
});

However, if you need to customize the meta data returned with the collection, it will be necessary to define a resource collection:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'data' => $this->collection,
            'links' => [
                'self' => 'link-value',
            ],
        ];
    }
}

Like singular resources, resource collections may be returned directly from routes or controllers:

use App\User;
use App\Http\Resources\UserCollection;

Route::get('/users', function () {
    return new UserCollection(User::all());
});

<a name=“data-wrapping”></a>

23.4.1 Data Wrapping

By default, your outer-most resource is wrapped in a data key when the resource response is converted to JSON. So, for example, a typical resource collection response looks like the following:

{
    "data": [
        {
            "id": 1,
            "name": "Eladio Schroeder Sr.",
            "email": "therese28@example.com",
        },
        {
            "id": 2,
            "name": "Liliana Mayert",
            "email": "evandervort@example.com",
        }
    ]
}

If you would like to disable the wrapping of the outer-most resource, you may use the withoutWrapping method on the base resource class. Typically, you should call this method from your AppServiceProvider or another service provider that is loaded on every request to your application:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Http\Resources\Json\Resource;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Resource::withoutWrapping();
    }

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

{note} The withoutWrapping method only affects the outer-most response and will not remove data keys that you manually add to your own resource collections.

23.4.2 Wrapping Nested Resources

You have total freedom to determine how your resource’s relationships are wrapped. If you would like all resource collections to be wrapped in a data key, regardless of their nesting, you should define a resource collection class for each resource and return the collection within a data key.

Of course, you may be wondering if this will cause your outer-most resource to be wrapped in two data keys. Don’t worry, Laravel will never let your resources be accidentally double-wrapped, so you don’t have to be concerned about the nesting level of the resource collection you are transforming:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class CommentsCollection extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return ['data' => $this->collection];
    }
}

23.4.3 Data Wrapping And Pagination

When returning paginated collections in a resource response, Laravel will wrap your resource data in a data key even if the withoutWrapping method has been called. This is because paginated responses always contain meta and links keys with information about the paginator’s state:

{
    "data": [
        {
            "id": 1,
            "name": "Eladio Schroeder Sr.",
            "email": "therese28@example.com",
        },
        {
            "id": 2,
            "name": "Liliana Mayert",
            "email": "evandervort@example.com",
        }
    ],
    "links":{
        "first": "http://example.com/pagination?page=1",
        "last": "http://example.com/pagination?page=1",
        "prev": null,
        "next": null
    },
    "meta":{
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://example.com/pagination",
        "per_page": 15,
        "to": 10,
        "total": 10
    }
}

<a name=“pagination”></a>

23.4.4 Pagination

You may always pass a paginator instance to the collection method of a resource or to a custom resource collection:

use App\User;
use App\Http\Resources\UserCollection;

Route::get('/users', function () {
    return new UserCollection(User::paginate());
});

Paginated responses always contain meta and links keys with information about the paginator’s state:

{
    "data": [
        {
            "id": 1,
            "name": "Eladio Schroeder Sr.",
            "email": "therese28@example.com",
        },
        {
            "id": 2,
            "name": "Liliana Mayert",
            "email": "evandervort@example.com",
        }
    ],
    "links":{
        "first": "http://example.com/pagination?page=1",
        "last": "http://example.com/pagination?page=1",
        "prev": null,
        "next": null
    },
    "meta":{
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://example.com/pagination",
        "per_page": 15,
        "to": 10,
        "total": 10
    }
}

<a name=“conditional-attributes”></a>

23.4.5 Conditional Attributes

Sometimes you may wish to only include an attribute in a resource response if a given condition is met. For example, you may wish to only include a value if the current user is an “administrator”. Laravel provides a variety of helper methods to assist you in this situation. The when method may be used to conditionally add an attribute to a resource response:

/**
 * Transform the resource into an array.
 *
 * @param  \Illuminate\Http\Request
 * @return array
 */
public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'secret' => $this->when($this->isAdmin(), 'secret-value'),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

In this example, the secret key will only be returned in the final resource response if the $this->isAdmin() method returns true. If the method returns false, the secret key will be removed from the resource response entirely before it is sent back to the client. The when method allows you to expressively define your resources without resorting to conditional statements when building the array.

The when method also accepts a Closure as its second argument, allowing you to calculate the resulting value only if the given condition is true:

'secret' => $this->when($this->isAdmin(), function () {
    return 'secret-value';
}),

{tip} Remember, method calls on resources proxy down to the underlying model instance. So, in this case, the isAdmin method is proxying to the underlying Eloquent model that was originally given to the resource.

23.4.5.1 Merging Conditional Attributes

Sometimes you may have several attributes that should only be included in the resource response based on the same condition. In this case, you may use the mergeWhen method to include the attributes in the response only when the given condition is true:

/**
 * Transform the resource into an array.
 *
 * @param  \Illuminate\Http\Request
 * @return array
 */
public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        $this->mergeWhen($this->isAdmin(), [
            'first-secret' => 'value',
            'second-secret' => 'value',
        ]),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

Again, if the given condition is false, these attributes will be removed from the resource response entirely before it is sent to the client.

{note} The mergeWhen method should not be used within arrays that mix string and numeric keys. Furthermore, it should not be used within arrays with numeric keys that are not ordered sequentially.

<a name=“conditional-relationships”></a>

23.4.6 Conditional Relationships

In addition to conditionally loading attributes, you may conditionally include relationships on your resource responses based on if the relationship has already been loaded on the model. This allows your controller to decide which relationships should be loaded on the model and your resource can easily include them only when they have actually been loaded.

Ultimately, this makes it easier to avoid “N+1” query problems within your resources. The whenLoaded method may be used to conditionally load a relationship. In order to avoid unnecessarily loading relationships, this method accepts the name of the relationship instead of the relationship itself:

/**
 * Transform the resource into an array.
 *
 * @param  \Illuminate\Http\Request
 * @return array
 */
public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'posts' => Post::collection($this->whenLoaded('posts')),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

In this example, if the relationship has not been loaded, the posts key will be removed from the resource response entirely before it is sent to the client.

23.4.6.1 Conditional Pivot Information

In addition to conditionally including relationship information in your resource responses, you may conditionally include data from the intermediate tables of many-to-many relationships using the whenPivotLoaded method. The whenPivotLoaded method accepts the name of the pivot table as its first argument. The second argument should be a Closure that defines the value to be returned if the pivot information is available on the model:

/**
 * Transform the resource into an array.
 *
 * @param  \Illuminate\Http\Request
 * @return array
 */
public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'expires_at' => $this->whenPivotLoaded('role_users', function () {
            return $this->pivot->expires_at;
        }),
    ];
}

<a name=“adding-meta-data”></a>

23.4.7 Adding Meta Data

Some JSON API standards require the addition of meta data to your resource and resource collections responses. This often includes things like links to the resource or related resources, or meta data about the resource itself. If you need to return additional meta data about a resource, include it in your toArray method. For example, you might include link information when transforming a resource collection:

/**
 * Transform the resource into an array.
 *
 * @param  \Illuminate\Http\Request
 * @return array
 */
public function toArray($request)
{
    return [
        'data' => $this->collection,
        'links' => [
            'self' => 'link-value',
        ],
    ];
}

When returning additional meta data from your resources, you never have to worry about accidentally overriding the links or meta keys that are automatically added by Laravel when returning paginated responses. Any additional links you define will be merged with the links provided by the paginator.

23.4.7.1 Top Level Meta Data

Sometimes you may wish to only include certain meta data with a resource response if the resource is the outer-most resource being returned. Typically, this includes meta information about the response as a whole. To define this meta data, add a with method to your resource class. This method should return an array of meta data to be included with the resource response only when the resource is the outer-most resource being rendered:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return parent::toArray($request);
    }

    /**
     * Get additional data that should be returned with the resource array.
     *
     * @param \Illuminate\Http\Request  $request
     * @return array
     */
    public function with($request)
    {
        return [
            'meta' => [
                'key' => 'value',
            ],
        ];
    }
}

23.4.7.2 Adding Meta Data When Constructing Resources

You may also add top-level data when constructing resource instances in your route or controller. The additional method, which is available on all resources, accepts an array of data that should be added to the resource response:

return (new UserCollection(User::all()->load('roles')))
                ->additional(['meta' => [
                    'key' => 'value',
                ]]);

<a name=“resource-responses”></a>

23.5 Resource Responses

As you have already read, resources may be returned directly from routes and controllers:

use App\User;
use App\Http\Resources\UserResource;

Route::get('/user', function () {
    return new UserResource(User::find(1));
});

However, sometimes you may need to customize the outgoing HTTP response before it is sent to the client. There are two ways to accomplish this. First, you may chain the response method onto the resource. This method will return an Illuminate\Http\Response instance, allowing you full control of the response’s headers:

use App\User;
use App\Http\Resources\UserResource;

Route::get('/user', function () {
    return (new UserResource(User::find(1)))
                ->response()
                ->header('X-Value', 'True');
});

Alternatively, you may define a withResponse method within the resource itself. This method will be called when the resource is returned as the outer-most resource in a response:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;

class UserResource extends Resource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
        ];
    }

    /**
     * Customize the outgoing response for the resource.
     *
     * @param  \Illuminate\Http\Request
     * @param  \Illuminate\Http\Response
     * @return void
     */
    public function withResponse($request, $response)
    {
        $response->header('X-Value', 'True');
    }
}

24 Eloquent: Serialization

<a name=“introduction”></a>

24.1 Introduction

When building JSON APIs, you will often need to convert your models and relationships to arrays or JSON. Eloquent includes convenient methods for making these conversions, as well as controlling which attributes are included in your serializations.

<a name=“serializing-models-and-collections”></a>

24.2 Serializing Models & Collections

<a name=“serializing-to-arrays”></a>

24.2.1 Serializing To Arrays

To convert a model and its loaded relationships to an array, you should use the toArray method. This method is recursive, so all attributes and all relations (including the relations of relations) will be converted to arrays:

$user = App\User::with('roles')->first();

return $user->toArray();

You may also convert entire collections of models to arrays:

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

return $users->toArray();

<a name=“serializing-to-json”></a>

24.2.2 Serializing To JSON

To convert a model to JSON, you should use the toJson method. Like toArray, the toJson method is recursive, so all attributes and relations will be converted to JSON:

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

return $user->toJson();

Alternatively, you may cast a model or collection to a string, which will automatically call the toJson method on the model or collection:

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

return (string) $user;

Since models and collections are converted to JSON when cast to a string, you can return Eloquent objects directly from your application’s routes or controllers:

Route::get('users', function () {
    return App\User::all();
});

<a name=“hiding-attributes-from-json”></a>

24.3 Hiding Attributes From JSON

Sometimes you may wish to limit the attributes, such as passwords, that are included in your model’s array or JSON representation. To do so, add a $hidden property to your model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = ['password'];
}

{note} When hiding relationships, use the relationship’s method name.

Alternatively, you may use the visible property to define a white-list of attributes that should be included in your model’s array and JSON representation. All other attributes will be hidden when the model is converted to an array or JSON:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be visible in arrays.
     *
     * @var array
     */
    protected $visible = ['first_name', 'last_name'];
}

24.3.0.1 Temporarily Modifying Attribute Visibility

If you would like to make some typically hidden attributes visible on a given model instance, you may use the makeVisible method. The makeVisible method returns the model instance for convenient method chaining:

return $user->makeVisible('attribute')->toArray();

Likewise, if you would like to make some typically visible attributes hidden on a given model instance, you may use the makeHidden method.

return $user->makeHidden('attribute')->toArray();

<a name=“appending-values-to-json”></a>

24.4 Appending Values To JSON

Occasionally, when casting models to an array or JSON, you may wish to add attributes that do not have a corresponding column in your database. To do so, first define an accessor for the value:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Get the administrator flag for the user.
     *
     * @return bool
     */
    public function getIsAdminAttribute()
    {
        return $this->attributes['admin'] == 'yes';
    }
}

After creating the accessor, add the attribute name to the appends property on the model. Note that attribute names are typically referenced in “snake case”, even though the accessor is defined using “camel case”:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    protected $appends = ['is_admin'];
}

Once the attribute has been added to the appends list, it will be included in both the model’s array and JSON representations. Attributes in the appends array will also respect the visible and hidden settings configured on the model.

24.4.0.1 Appending At Run Time

You may instruct a single model instance to append attributes using the append method. Or, you may use the setAppends method to override the entire array of appended properties for a given model instance:

return $user->append('is_admin')->toArray();

return $user->setAppends(['is_admin'])->toArray();

<a name=“date-serialization”></a>

24.5 Date Serialization

Laravel extends the Carbon date library in order to provide convenient customization of Carbon’s JSON serialization format. To customize how all Carbon dates throughout your application are serialized, use the Carbon::serializeUsing method. The serializeUsing method accepts a Closure which returns a string representation of the date for JSON serialization:

<?php

namespace App\Providers;

use Illuminate\Support\Carbon;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Carbon::serializeUsing(function ($carbon) {
            return $carbon->format('U');
        });
    }

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

25 Eloquent: Getting Started

<a name=“introduction”></a>

25.1 Introduction

The Eloquent ORM included with Laravel provides a beautiful, simple ActiveRecord implementation for working with your database. Each database table has a corresponding “Model” which is used to interact with that table. Models allow you to query for data in your tables, as well as insert new records into the table.

Before getting started, be sure to configure a database connection in config/database.php. For more information on configuring your database, check out the documentation.

<a name=“defining-models”></a>

25.2 Defining Models

To get started, let’s create an Eloquent model. Models typically live in the app directory, but you are free to place them anywhere that can be auto-loaded according to your composer.json file. All Eloquent models extend Illuminate\Database\Eloquent\Model class.

The easiest way to create a model instance is using the make:model Artisan command:

php artisan make:model User

If you would like to generate a database migration when you generate the model, you may use the --migration or -m option:

php artisan make:model User --migration

php artisan make:model User -m

<a name=“eloquent-model-conventions”></a>

25.2.1 Eloquent Model Conventions

Now, let’s look at an example Flight model, which we will use to retrieve and store information from our flights database table:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    //
}

25.2.1.1 Table Names

Note that we did not tell Eloquent which table to use for our Flight model. By convention, the “snake case”, plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the Flight model stores records in the flights table. You may specify a custom table by defining a table property on your model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'my_flights';
}

25.2.1.2 Primary Keys

Eloquent will also assume that each table has a primary key column named id. You may define a protected $primaryKey property to override this convention.

In addition, Eloquent assumes that the primary key is an incrementing integer value, which means that by default the primary key will be cast to an int automatically. If you wish to use a non-incrementing or a non-numeric primary key you must set the public $incrementing property on your model to false. If your primary key is not an integer, you should set the protected $keyType property on your model to string.

25.2.1.3 Timestamps

By default, Eloquent expects created_at and updated_at columns to exist on your tables. If you do not wish to have these columns automatically managed by Eloquent, set the $timestamps property on your model to false:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = false;
}

If you need to customize the format of your timestamps, set the $dateFormat property on your model. This property determines how date attributes are stored in the database, as well as their format when the model is serialized to an array or JSON:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The storage format of the model's date columns.
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

If you need to customize the names of the columns used to store the timestamps, you may set the CREATED_AT and UPDATED_AT constants in your model:

<?php

class Flight extends Model
{
    const CREATED_AT = 'creation_date';
    const UPDATED_AT = 'last_update';
}

25.2.1.4 Database Connection

By default, all Eloquent models will use the default database connection configured for your application. If you would like to specify a different connection for the model, use the $connection property:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The connection name for the model.
     *
     * @var string
     */
    protected $connection = 'connection-name';
}

<a name=“retrieving-models”></a>

25.3 Retrieving Models

Once you have created a model and its associated database table, you are ready to start retrieving data from your database. Think of each Eloquent model as a powerful query builder allowing you to fluently query the database table associated with the model. For example:

<?php

use App\Flight;

$flights = App\Flight::all();

foreach ($flights as $flight) {
    echo $flight->name;
}

25.3.0.1 Adding Additional Constraints

The Eloquent all method will return all of the results in the model’s table. Since each Eloquent model serves as a query builder, you may also add constraints to queries, and then use the get method to retrieve the results:

$flights = App\Flight::where('active', 1)
               ->orderBy('name', 'desc')
               ->take(10)
               ->get();

{tip} Since Eloquent models are query builders, you should review all of the methods available on the query builder. You may use any of these methods in your Eloquent queries.

<a name=“collections”></a>

25.3.1 Collections

For Eloquent methods like all and get which retrieve multiple results, an instance of Illuminate\Database\Eloquent\Collection will be returned. The Collection class provides a variety of helpful methods for working with your Eloquent results:

$flights = $flights->reject(function ($flight) {
    return $flight->cancelled;
});

Of course, you may also loop over the collection like an array:

foreach ($flights as $flight) {
    echo $flight->name;
}

<a name=“chunking-results”></a>

25.3.2 Chunking Results

If you need to process thousands of Eloquent records, use the chunk command. The chunk method will retrieve a “chunk” of Eloquent models, feeding them to a given Closure for processing. Using the chunk method will conserve memory when working with large result sets:

Flight::chunk(200, function ($flights) {
    foreach ($flights as $flight) {
        //
    }
});

The first argument passed to the method is the number of records you wish to receive per “chunk”. The Closure passed as the second argument will be called for each chunk that is retrieved from the database. A database query will be executed to retrieve each chunk of records passed to the Closure.

25.3.2.1 Using Cursors

The cursor method allows you to iterate through your database records using a cursor, which will only execute a single query. When processing large amounts of data, the cursor method may be used to greatly reduce your memory usage:

foreach (Flight::where('foo', 'bar')->cursor() as $flight) {
    //
}

<a name=“retrieving-single-models”></a>

25.4 Retrieving Single Models / Aggregates

Of course, in addition to retrieving all of the records for a given table, you may also retrieve single records using find or first. Instead of returning a collection of models, these methods return a single model instance:

// Retrieve a model by its primary key...
$flight = App\Flight::find(1);

// Retrieve the first model matching the query constraints...
$flight = App\Flight::where('active', 1)->first();

You may also call the find method with an array of primary keys, which will return a collection of the matching records:

$flights = App\Flight::find([1, 2, 3]);

25.4.0.1 Not Found Exceptions

Sometimes you may wish to throw an exception if a model is not found. This is particularly useful in routes or controllers. The findOrFail and firstOrFail methods will retrieve the first result of the query; however, if no result is found, a Illuminate\Database\Eloquent\ModelNotFoundException will be thrown:

$model = App\Flight::findOrFail(1);

$model = App\Flight::where('legs', '>', 100)->firstOrFail();

If the exception is not caught, a 404 HTTP response is automatically sent back to the user. It is not necessary to write explicit checks to return 404 responses when using these methods:

Route::get('/api/flights/{id}', function ($id) {
    return App\Flight::findOrFail($id);
});

<a name=“retrieving-aggregates”></a>

25.4.1 Retrieving Aggregates

You may also use the count, sum, max, and other aggregate methods provided by the query builder. These methods return the appropriate scalar value instead of a full model instance:

$count = App\Flight::where('active', 1)->count();

$max = App\Flight::where('active', 1)->max('price');

<a name=“inserting-and-updating-models”></a>

25.5 Inserting & Updating Models

<a name=“inserts”></a>

25.5.1 Inserts

To create a new record in the database, create a new model instance, set attributes on the model, then call the save method:

<?php

namespace App\Http\Controllers;

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

class FlightController extends Controller
{
    /**
     * Create a new flight instance.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        // Validate the request...

        $flight = new Flight;

        $flight->name = $request->name;

        $flight->save();
    }
}

In this example, we assign the name parameter from the incoming HTTP request to the name attribute of the App\Flight model instance. When we call the save method, a record will be inserted into the database. The created_at and updated_at timestamps will automatically be set when the save method is called, so there is no need to set them manually.

<a name=“updates”></a>

25.5.2 Updates

The save method may also be used to update models that already exist in the database. To update a model, you should retrieve it, set any attributes you wish to update, and then call the save method. Again, the updated_at timestamp will automatically be updated, so there is no need to manually set its value:

$flight = App\Flight::find(1);

$flight->name = 'New Flight Name';

$flight->save();

25.5.2.1 Mass Updates

Updates can also be performed against any number of models that match a given query. In this example, all flights that are active and have a destination of San Diego will be marked as delayed:

App\Flight::where('active', 1)
          ->where('destination', 'San Diego')
          ->update(['delayed' => 1]);

The update method expects an array of column and value pairs representing the columns that should be updated.

{note} When issuing a mass update via Eloquent, the saved and updated model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update.

<a name=“mass-assignment”></a>

25.5.3 Mass Assignment

You may also use the create method to save a new model in a single line. The inserted model instance will be returned to you from the method. However, before doing so, you will need to specify either a fillable or guarded attribute on the model, as all Eloquent models protect against mass-assignment by default.

A mass-assignment vulnerability occurs when a user passes an unexpected HTTP parameter through a request, and that parameter changes a column in your database you did not expect. For example, a malicious user might send an is_admin parameter through an HTTP request, which is then passed into your model’s create method, allowing the user to escalate themselves to an administrator.

So, to get started, you should define which model attributes you want to make mass assignable. You may do this using the $fillable property on the model. For example, let’s make the name attribute of our Flight model mass assignable:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['name'];
}

Once we have made the attributes mass assignable, we can use the create method to insert a new record in the database. The create method returns the saved model instance:

$flight = App\Flight::create(['name' => 'Flight 10']);

If you already have a model instance, you may use the fill method to populate it with an array of attributes:

$flight->fill(['name' => 'Flight 22']);

25.5.3.1 Guarding Attributes

While $fillable serves as a “white list” of attributes that should be mass assignable, you may also choose to use $guarded. The $guarded property should contain an array of attributes that you do not want to be mass assignable. All other attributes not in the array will be mass assignable. So, $guarded functions like a “black list”. Of course, you should use either $fillable or $guarded - not both. In the example below, all attributes except for price will be mass assignable:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The attributes that aren't mass assignable.
     *
     * @var array
     */
    protected $guarded = ['price'];
}

If you would like to make all attributes mass assignable, you may define the $guarded property as an empty array:

/**
 * The attributes that aren't mass assignable.
 *
 * @var array
 */
protected $guarded = [];

<a name=“other-creation-methods”></a>

25.5.4 Other Creation Methods

25.5.4.1 firstOrCreate/ firstOrNew

There are two other methods you may use to create models by mass assigning attributes: firstOrCreate and firstOrNew. The firstOrCreate method will attempt to locate a database record using the given column / value pairs. If the model can not be found in the database, a record will be inserted with the attributes from the first parameter, along with those in the optional second parameter.

The firstOrNew method, like firstOrCreate will attempt to locate a record in the database matching the given attributes. However, if a model is not found, a new model instance will be returned. Note that the model returned by firstOrNew has not yet been persisted to the database. You will need to call save manually to persist it:

// Retrieve flight by name, or create it if it doesn't exist...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);

// Retrieve flight by name, or create it with the name and delayed attributes...
$flight = App\Flight::firstOrCreate(
    ['name' => 'Flight 10'], ['delayed' => 1]
);

// Retrieve by name, or instantiate...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);

// Retrieve by name, or instantiate with the name and delayed attributes...
$flight = App\Flight::firstOrNew(
    ['name' => 'Flight 10'], ['delayed' => 1]
);

25.5.4.2 updateOrCreate

You may also come across situations where you want to update an existing model or create a new model if none exists. Laravel provides an updateOrCreate method to do this in one step. Like the firstOrCreate method, updateOrCreate persists the model, so there’s no need to call save():

// If there's a flight from Oakland to San Diego, set the price to $99.
// If no matching model exists, create one.
$flight = App\Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99]
);

<a name=“deleting-models”></a>

25.6 Deleting Models

To delete a model, call the delete method on a model instance:

$flight = App\Flight::find(1);

$flight->delete();

25.6.0.1 Deleting An Existing Model By Key

In the example above, we are retrieving the model from the database before calling the delete method. However, if you know the primary key of the model, you may delete the model without retrieving it. To do so, call the destroy method:

App\Flight::destroy(1);

App\Flight::destroy([1, 2, 3]);

App\Flight::destroy(1, 2, 3);

25.6.0.2 Deleting Models By Query

Of course, you may also run a delete statement on a set of models. In this example, we will delete all flights that are marked as inactive. Like mass updates, mass deletes will not fire any model events for the models that are deleted:

$deletedRows = App\Flight::where('active', 0)->delete();

{note} When executing a mass delete statement via Eloquent, the deleting and deleted model events will not be fired for the deleted models. This is because the models are never actually retrieved when executing the delete statement.

<a name=“soft-deleting”></a>

25.6.1 Soft Deleting

In addition to actually removing records from your database, Eloquent can also “soft delete” models. When models are soft deleted, they are not actually removed from your database. Instead, a deleted_at attribute is set on the model and inserted into the database. If a model has a non-null deleted_at value, the model has been soft deleted. To enable soft deletes for a model, use the Illuminate\Database\Eloquent\SoftDeletes trait on the model and add the deleted_at column to your $dates property:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Flight extends Model
{
    use SoftDeletes;

    /**
     * The attributes that should be mutated to dates.
     *
     * @var array
     */
    protected $dates = ['deleted_at'];
}

Of course, you should add the deleted_at column to your database table. The Laravel schema builder contains a helper method to create this column:

Schema::table('flights', function ($table) {
    $table->softDeletes();
});

Now, when you call the delete method on the model, the deleted_at column will be set to the current date and time. And, when querying a model that uses soft deletes, the soft deleted models will automatically be excluded from all query results.

To determine if a given model instance has been soft deleted, use the trashed method:

if ($flight->trashed()) {
    //
}

<a name=“querying-soft-deleted-models”></a>

25.6.2 Querying Soft Deleted Models

25.6.2.1 Including Soft Deleted Models

As noted above, soft deleted models will automatically be excluded from query results. However, you may force soft deleted models to appear in a result set using the withTrashed method on the query:

$flights = App\Flight::withTrashed()
                ->where('account_id', 1)
                ->get();

The withTrashed method may also be used on a relationship query:

$flight->history()->withTrashed()->get();

25.6.2.2 Retrieving Only Soft Deleted Models

The onlyTrashed method will retrieve only soft deleted models:

$flights = App\Flight::onlyTrashed()
                ->where('airline_id', 1)
                ->get();

25.6.2.3 Restoring Soft Deleted Models

Sometimes you may wish to “un-delete” a soft deleted model. To restore a soft deleted model into an active state, use the restore method on a model instance:

$flight->restore();

You may also use the restore method in a query to quickly restore multiple models. Again, like other “mass” operations, this will not fire any model events for the models that are restored:

App\Flight::withTrashed()
        ->where('airline_id', 1)
        ->restore();

Like the withTrashed method, the restore method may also be used on relationships:

$flight->history()->restore();

25.6.2.4 Permanently Deleting Models

Sometimes you may need to truly remove a model from your database. To permanently remove a soft deleted model from the database, use the forceDelete method:

// Force deleting a single model instance...
$flight->forceDelete();

// Force deleting all related models...
$flight->history()->forceDelete();

<a name=“query-scopes”></a>

25.7 Query Scopes

<a name=“global-scopes”></a>

25.7.1 Global Scopes

Global scopes allow you to add constraints to all queries for a given model. Laravel’s own soft delete functionality utilizes global scopes to only pull “non-deleted” models from the database. Writing your own global scopes can provide a convenient, easy way to make sure every query for a given model receives certain constraints.

25.7.1.1 Writing Global Scopes

Writing a global scope is simple. Define a class that implements the Illuminate\Database\Eloquent\Scope interface. This interface requires you to implement one method: apply. The apply method may add where constraints to the query as needed:

<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class AgeScope implements Scope
{
    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        $builder->where('age', '>', 200);
    }
}

{tip} If your global scope is adding columns to the select clause of the query, you should use the addSelect method instead of select. This will prevent the unintentional replacement of the query’s existing select clause.

25.7.1.2 Applying Global Scopes

To assign a global scope to a model, you should override a given model’s boot method and use the addGlobalScope method:

<?php

namespace App;

use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope(new AgeScope);
    }
}

After adding the scope, a query to User::all() will produce the following SQL:

select * from `users` where `age` > 200

25.7.1.3 Anonymous Global Scopes

Eloquent also allows you to define global scopes using Closures, which is particularly useful for simple scopes that do not warrant a separate class:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class User extends Model
{
    /**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope('age', function (Builder $builder) {
            $builder->where('age', '>', 200);
        });
    }
}

25.7.1.4 Removing Global Scopes

If you would like to remove a global scope for a given query, you may use the withoutGlobalScope method. The method accepts the class name of the global scope as its only argument:

User::withoutGlobalScope(AgeScope::class)->get();

If you would like to remove several or even all of the global scopes, you may use the withoutGlobalScopes method:

// Remove all of the global scopes...
User::withoutGlobalScopes()->get();

// Remove some of the global scopes...
User::withoutGlobalScopes([
    FirstScope::class, SecondScope::class
])->get();

<a name=“local-scopes”></a>

25.7.2 Local Scopes

Local scopes allow you to define common sets of constraints that you may easily re-use throughout your application. For example, you may need to frequently retrieve all users that are considered “popular”. To define a scope, prefix an Eloquent model method with scope.

Scopes should always return a query builder instance:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Scope a query to only include popular users.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePopular($query)
    {
        return $query->where('votes', '>', 100);
    }

    /**
     * Scope a query to only include active users.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeActive($query)
    {
        return $query->where('active', 1);
    }
}

25.7.2.1 Utilizing A Local Scope

Once the scope has been defined, you may call the scope methods when querying the model. However, you should not include the scope prefix when calling the method. You can even chain calls to various scopes, for example:

$users = App\User::popular()->active()->orderBy('created_at')->get();

25.7.2.2 Dynamic Scopes

Sometimes you may wish to define a scope that accepts parameters. To get started, just add your additional parameters to your scope. Scope parameters should be defined after the $query parameter:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Scope a query to only include users of a given type.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param mixed $type
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }
}

Now, you may pass the parameters when calling the scope:

$users = App\User::ofType('admin')->get();

<a name=“events”></a>

25.8 Events

Eloquent models fire several events, allowing you to hook into the following points in a model’s lifecycle: retrieved, creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored. Events allow you to easily execute code each time a specific model class is saved or updated in the database.

The retrieved event will fire when an existing model is retrieved from the database. When a new model is saved for the first time, the creating and created events will fire. If a model already existed in the database and the save method is called, the updating / updated events will fire. However, in both cases, the saving / saved events will fire.

To get started, define a $dispatchesEvents property on your Eloquent model that maps various points of the Eloquent model’s lifecycle to your own event classes:

<?php

namespace App;

use App\Events\UserSaved;
use App\Events\UserDeleted;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The event map for the model.
     *
     * @var array
     */
    protected $dispatchesEvents = [
        'saved' => UserSaved::class,
        'deleted' => UserDeleted::class,
    ];
}

<a name=“observers”></a>

25.8.1 Observers

If you are listening for many events on a given model, you may use observers to group all of your listeners into a single class. Observers classes have method names which reflect the Eloquent events you wish to listen for. Each of these methods receives the model as their only argument. Laravel does not include a default directory for observers, so you may create any directory you like to house your observer classes:

<?php

namespace App\Observers;

use App\User;

class UserObserver
{
    /**
     * Listen to the User created event.
     *
     * @param  \App\User  $user
     * @return void
     */
    public function created(User $user)
    {
        //
    }

    /**
     * Listen to the User deleting event.
     *
     * @param  \App\User  $user
     * @return void
     */
    public function deleting(User $user)
    {
        //
    }
}

To register an observer, use the observe method on the model you wish to observe. You may register observers in the boot method of one of your service providers. In this example, we’ll register the observer in the AppServiceProvider:

<?php

namespace App\Providers;

use App\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;

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

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

26 Encryption

<a name=“introduction”></a>

26.1 Introduction

Laravel’s encrypter uses OpenSSL to provide AES-256 and AES-128 encryption. You are strongly encouraged to use Laravel’s built-in encryption facilities and not attempt to roll your own “home grown” encryption algorithms. All of Laravel’s encrypted values are signed using a message authentication code (MAC) so that their underlying value can not be modified once encrypted.

<a name=“configuration”></a>

26.2 Configuration

Before using Laravel’s encrypter, you must set a key option in your config/app.php configuration file. You should use the php artisan key:generate command to generate this key since this Artisan command will use PHP’s secure random bytes generator to build your key. If this value is not properly set, all values encrypted by Laravel will be insecure.

<a name=“using-the-encrypter”></a>

26.3 Using The Encrypter

26.3.0.1 Encrypting A Value

You may encrypt a value using the encrypt helper. All encrypted values are encrypted using OpenSSL and the AES-256-CBC cipher. Furthermore, all encrypted values are signed with a message authentication code (MAC) to detect any modifications to the encrypted string:

<?php

namespace App\Http\Controllers;

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

class UserController extends Controller
{
    /**
     * Store a secret message for the user.
     *
     * @param  Request  $request
     * @param  int  $id
     * @return Response
     */
    public function storeSecret(Request $request, $id)
    {
        $user = User::findOrFail($id);

        $user->fill([
            'secret' => encrypt($request->secret)
        ])->save();
    }
}

26.3.0.2 Encrypting Without Serialization

Encrypted values are passed through serialize during encryption, which allows for encryption of objects and arrays. Thus, non-PHP clients receiving encrypted values will need to unserialize the data. If you would like to encrypt and decrypt values without serialization, you may use the encryptString and decryptString methods of the Crypt facade:

use Illuminate\Support\Facades\Crypt;

$encrypted = Crypt::encryptString('Hello world.');

$decrypted = Crypt::decryptString($encrypted);

26.3.0.3 Decrypting A Value

You may decrypt values using the decrypt helper. If the value can not be properly decrypted, such as when the MAC is invalid, an Illuminate\Contracts\Encryption\DecryptException will be thrown:

use Illuminate\Contracts\Encryption\DecryptException;

try {
    $decrypted = decrypt($encryptedValue);
} catch (DecryptException $e) {
    //
}

27 Envoy Task Runner

<a name=“introduction”></a>

27.1 Introduction

Laravel Envoy provides a clean, minimal syntax for defining common tasks you run on your remote servers. Using Blade style syntax, you can easily setup tasks for deployment, Artisan commands, and more. Currently, Envoy only supports the Mac and Linux operating systems.

<a name=“installation”></a>

27.1.1 Installation

First, install Envoy using the Composer global require command:

composer global require laravel/envoy

Since global Composer libraries can sometimes cause package version conflicts, you may wish to consider using cgr, which is a drop-in replacement for the composer global require command. The cgr library’s installation instructions can be found on GitHub.

{note} Make sure to place the ~/.composer/vendor/bin directory in your PATH so the envoy executable is found when running the envoy command in your terminal.

27.1.1.1 Updating Envoy

You may also use Composer to keep your Envoy installation up to date. Issuing the composer global update command will update all of your globally installed Composer packages:

composer global update

<a name=“writing-tasks”></a>

27.2 Writing Tasks

All of your Envoy tasks should be defined in an Envoy.blade.php file in the root of your project. Here’s an example to get you started:

@servers(['web' => ['user@192.168.1.1']])

@task('foo', ['on' => 'web'])
    ls -la
@endtask

As you can see, an array of @servers is defined at the top of the file, allowing you to reference these servers in the on option of your task declarations. Within your @task declarations, you should place the Bash code that should run on your server when the task is executed.

You can force a script to run locally by specifying the server’s IP address as 127.0.0.1:

@servers(['localhost' => '127.0.0.1'])

<a name=“setup”></a>

27.2.1 Setup

Sometimes, you may need to execute some PHP code before executing your Envoy tasks. You may use the @setup directive to declare variables and do other general PHP work before any of your other tasks are executed:

@setup
    $now = new DateTime();

    $environment = isset($env) ? $env : "testing";
@endsetup

If you need to require other PHP files before your task is executed, you may use the @include directive at the top of your Envoy.blade.php file:

@include('vendor/autoload.php')

@task('foo')
    # ...
@endtask

<a name=“variables”></a>

27.2.2 Variables

If needed, you may pass option values into Envoy tasks using the command line:

envoy run deploy --branch=master

You may access the options in your tasks via Blade’s “echo” syntax. Of course, you may also use if statements and loops within your tasks. For example, let’s verify the presence of the $branch variable before executing the git pull command:

@servers(['web' => '192.168.1.1'])

@task('deploy', ['on' => 'web'])
    cd site

    @if ($branch)
        git pull origin {{ $branch }}
    @endif

    php artisan migrate
@endtask

<a name=“stories”></a>

27.2.3 Stories

Stories group a set of tasks under a single, convenient name, allowing you to group small, focused tasks into large tasks. For instance, a deploy story may run the git and composer tasks by listing the task names within its definition:

@servers(['web' => '192.168.1.1'])

@story('deploy')
    git
    composer
@endstory

@task('git')
    git pull origin master
@endtask

@task('composer')
    composer install
@endtask

Once the story has been written, you may run it just like a typical task:

envoy run deploy

<a name=“multiple-servers”></a>

27.2.4 Multiple Servers

Envoy allows you to easily run a task across multiple servers. First, add additional servers to your @servers declaration. Each server should be assigned a unique name. Once you have defined your additional servers, list each of the servers in the task’s on array:

@servers(['web-1' => '192.168.1.1', 'web-2' => '192.168.1.2'])

@task('deploy', ['on' => ['web-1', 'web-2']])
    cd site
    git pull origin {{ $branch }}
    php artisan migrate
@endtask

27.2.4.1 Parallel Execution

By default, tasks will be executed on each server serially. In other words, a task will finish running on the first server before proceeding to execute on the second server. If you would like to run a task across multiple servers in parallel, add the parallel option to your task declaration:

@servers(['web-1' => '192.168.1.1', 'web-2' => '192.168.1.2'])

@task('deploy', ['on' => ['web-1', 'web-2'], 'parallel' => true])
    cd site
    git pull origin {{ $branch }}
    php artisan migrate
@endtask

<a name=“running-tasks”></a>

27.3 Running Tasks

To run a task or story that is defined in your Envoy.blade.php file, execute Envoy’s run command, passing the name of the task or story you would like to execute. Envoy will run the task and display the output from the servers as the task is running:

envoy run task

<a name=“confirming-task-execution”></a>

27.3.1 Confirming Task Execution

If you would like to be prompted for confirmation before running a given task on your servers, you should add the confirm directive to your task declaration. This option is particularly useful for destructive operations:

@task('deploy', ['on' => 'web', 'confirm' => true])
    cd site
    git pull origin {{ $branch }}
    php artisan migrate
@endtask

<a name=“notifications”></a>
<a name=“hipchat-notifications”></a>

27.4 Notifications

<a name=“slack”></a>

27.4.1 Slack

Envoy also supports sending notifications to Slack after each task is executed. The @slack directive accepts a Slack hook URL and a channel name. You may retrieve your webhook URL by creating an “Incoming WebHooks” integration in your Slack control panel. You should pass the entire webhook URL into the @slack directive:

@finished
    @slack('webhook-url', '#bots')
@endfinished

You may provide one of the following as the channel argument:

<div class=“content-list” markdown=“1”>

  • To send the notification to a channel: #channel
  • To send the notification to a user: @user
    </div>

28 Errors & Logging

<a name=“introduction”></a>

28.1 Introduction

When you start a new Laravel project, error and exception handling is already configured for you. The App\Exceptions\Handler class is where all exceptions triggered by your application are logged and then rendered back to the user. We’ll dive deeper into this class throughout this documentation.

For logging, Laravel utilizes the Monolog library, which provides support for a variety of powerful log handlers. Laravel configures several of these handlers for you, allowing you to choose between a single log file, rotating log files, or writing error information to the system log.

<a name=“configuration”></a>

28.2 Configuration

<a name=“error-detail”></a>

28.2.1 Error Detail

The debug option in your config/app.php configuration file determines how much information about an error is actually displayed to the user. By default, this option is set to respect the value of the APP_DEBUG environment variable, which is stored in your .env file.

For local development, you should set the APP_DEBUG environment variable to true. In your production environment, this value should always be false. If the value is set to true in production, you risk exposing sensitive configuration values to your application’s end users.

<a name=“log-storage”></a>

28.2.2 Log Storage

Out of the box, Laravel supports writing log information to single files, daily files, the syslog, and the errorlog. To configure which storage mechanism Laravel uses, you should modify the log option in your config/app.php configuration file. For example, if you wish to use daily log files instead of a single file, you should set the log value in your app configuration file to daily:

'log' => 'daily'

28.2.2.1 Maximum Daily Log Files

When using the daily log mode, Laravel will only retain five days of log files by default. If you want to adjust the number of retained files, you may add a log_max_files configuration value to your app configuration file:

'log_max_files' => 30

<a name=“log-severity-levels”></a>

28.2.3 Log Severity Levels

When using Monolog, log messages may have different levels of severity. By default, Laravel writes all log levels to storage. However, in your production environment, you may wish to configure the minimum severity that should be logged by adding the log_level option to your app.php configuration file.

Once this option has been configured, Laravel will log all levels greater than or equal to the specified severity. For example, a default log_level of error will log error, critical, alert, and emergency messages:

'log_level' => env('APP_LOG_LEVEL', 'error'),

{tip} Monolog recognizes the following severity levels - from least severe to most severe: debug, info, notice, warning, error, critical, alert, emergency.

<a name=“custom-monolog-configuration”></a>

28.2.4 Custom Monolog Configuration

If you would like to have complete control over how Monolog is configured for your application, you may use the application’s configureMonologUsing method. You should place a call to this method in your bootstrap/app.php file right before the $app variable is returned by the file:

$app->configureMonologUsing(function ($monolog) {
    $monolog->pushHandler(...);
});

return $app;

28.2.4.1 Customizing The Channel Name

By default, Monolog is instantiated with name that matches the current environment, such as production or local. To change this value, add the log_channel option to your app.php configuration file:

'log_channel' => env('APP_LOG_CHANNEL', 'my-app-name'),

<a name=“the-exception-handler”></a>

28.3 The Exception Handler

<a name=“report-method”></a>

28.3.1 The Report Method

All exceptions are handled by the App\Exceptions\Handler class. This class contains two methods: report and render. We’ll examine each of these methods in detail. The report method is used to log exceptions or send them to an external service like Bugsnag or Sentry. By default, the report method passes the exception to the base class where the exception is logged. However, you are free to log exceptions however you wish.

For example, if you need to report different types of exceptions in different ways, you may use the PHP instanceof comparison operator:

/**
 * Report or log an exception.
 *
 * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
 *
 * @param  \Exception  $exception
 * @return void
 */
public function report(Exception $exception)
{
    if ($exception instanceof CustomException) {
        //
    }

    return parent::report($exception);
}

28.3.1.1 The report Helper

Sometimes you may need to report an exception but continue handling the current request. The report helper function allows you to quickly report an exception using your exception handler’s report method without rendering an error page:

public function isValid($value)
{
    try {
        // Validate the value...
    } catch (Exception $e) {
        report($e);

        return false;
    }
}

28.3.1.2 Ignoring Exceptions By Type

The $dontReport property of the exception handler contains an array of exception types that will not be logged. For example, exceptions resulting from 404 errors, as well as several other types of errors, are not written to your log files. You may add other exception types to this array as needed:

/**
 * A list of the exception types that should not be reported.
 *
 * @var array
 */
protected $dontReport = [
    \Illuminate\Auth\AuthenticationException::class,
    \Illuminate\Auth\Access\AuthorizationException::class,
    \Symfony\Component\HttpKernel\Exception\HttpException::class,
    \Illuminate\Database\Eloquent\ModelNotFoundException::class,
    \Illuminate\Validation\ValidationException::class,
];

<a name=“render-method”></a>

28.3.2 The Render Method

The render method is responsible for converting a given exception into an HTTP response that should be sent back to the browser. By default, the exception is passed to the base class which generates a response for you. However, you are free to check the exception type or return your own custom response:

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $exception
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $exception)
{
    if ($exception instanceof CustomException) {
        return response()->view('errors.custom', [], 500);
    }

    return parent::render($request, $exception);
}

<a name=“renderable-exceptions”></a>

28.3.3 Reportable & Renderable Exceptions

Instead of type-checking exceptions in the exception handler’s report and render methods, you may define report and render methods directly on your custom exception. When these methods exist, they will be called automatically by the framework:

<?php

namespace App\Exceptions;

use Exception;

class RenderException extends Exception
{
    /**
     * Report the exception.
     *
     * @return void
     */
    public function report()
    {
        //
    }

    /**
     * Render the exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request
     * @return \Illuminate\Http\Response
     */
    public function render($request)
    {
        return response(...);
    }
}

<a name=“http-exceptions”></a>

28.4 HTTP Exceptions

Some exceptions describe HTTP error codes from the server. For example, this may be a “page not found” error (404), an “unauthorized error” (401) or even a developer generated 500 error. In order to generate such a response from anywhere in your application, you may use the abort helper:

abort(404);

The abort helper will immediately raise an exception which will be rendered by the exception handler. Optionally, you may provide the response text:

abort(403, 'Unauthorized action.');

<a name=“custom-http-error-pages”></a>

28.4.1 Custom HTTP Error Pages

Laravel makes it easy to display custom error pages for various HTTP status codes. For example, if you wish to customize the error page for 404 HTTP status codes, create a resources/views/errors/404.blade.php. This file will be served on all 404 errors generated by your application. The views within this directory should be named to match the HTTP status code they correspond to. The HttpException instance raised by the abort function will be passed to the view as an $exception variable:

<h2>{{ $exception->getMessage() }}</h2>

<a name=“logging”></a>

28.5 Logging

Laravel provides a simple abstraction layer on top of the powerful Monolog library. By default, Laravel is configured to create a log file for your application in the storage/logs directory. You may write information to the logs using the Log facade:

<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        Log::info('Showing user profile for user: '.$id);

        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

The logger provides the eight logging levels defined in RFC 5424: emergency, alert, critical, error, warning, notice, info and debug.

Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);

28.5.0.1 Contextual Information

An array of contextual data may also be passed to the log methods. This contextual data will be formatted and displayed with the log message:

Log::info('User failed to login.', ['id' => $user->id]);

28.5.0.2 Accessing The Underlying Monolog Instance

Monolog has a variety of additional handlers you may use for logging. If needed, you may access the underlying Monolog instance being used by Laravel:

$monolog = Log::getMonolog();

29 Events

<a name=“introduction”></a>

29.1 Introduction

Laravel’s events provides a simple observer implementation, allowing you to subscribe and listen for various events that occur in your application. Event classes are typically stored in the app/Events directory, while their listeners are stored in app/Listeners. Don’t worry if you don’t see these directories in your application, since they will be created for you as you generate events and listeners using Artisan console commands.

Events serve as a great way to decouple various aspects of your application, since a single event can have multiple listeners that do not depend on each other. For example, you may wish to send a Slack notification to your user each time an order has shipped. Instead of coupling your order processing code to your Slack notification code, you can raise an OrderShipped event, which a listener can receive and transform into a Slack notification.

<a name=“registering-events-and-listeners”></a>

29.2 Registering Events & Listeners

The EventServiceProvider included with your Laravel application provides a convenient place to register all of your application’s event listeners. The listen property contains an array of all events (keys) and their listeners (values). Of course, you may add as many events to this array as your application requires. For example, let’s add a OrderShipped event:

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'App\Events\OrderShipped' => [
        'App\Listeners\SendShipmentNotification',
    ],
];

<a name=“generating-events-and-listeners”></a>

29.2.1 Generating Events & Listeners

Of course, manually creating the files for each event and listener is cumbersome. Instead, add listeners and events to your EventServiceProvider and use the event:generate command. This command will generate any events or listeners that are listed in your EventServiceProvider. Of course, events and listeners that already exist will be left untouched:

php artisan event:generate

<a name=“manually-registering-events”></a>

29.2.2 Manually Registering Events

Typically, events should be registered via the EventServiceProvider $listen array; however, you may also register Closure based events manually in the boot method of your EventServiceProvider:

/**
 * Register any other events for your application.
 *
 * @return void
 */
public function boot()
{
    parent::boot();

    Event::listen('event.name', function ($foo, $bar) {
        //
    });
}

29.2.2.1 Wildcard Event Listeners

You may even register listeners using the * as a wildcard parameter, allowing you to catch multiple events on the same listener. Wildcard listeners receive the event name as their first argument, and the entire event data array as their second argument:

Event::listen('event.*', function ($eventName, array $data) {
    //
});

<a name=“defining-events”></a>

29.3 Defining Events

An event class is a data container which holds the information related to the event. For example, let’s assume our generated OrderShipped event receives an Eloquent ORM object:

<?php

namespace App\Events;

use App\Order;
use Illuminate\Queue\SerializesModels;

class OrderShipped
{
    use SerializesModels;

    public $order;

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

As you can see, this event class contains no logic. It is a container for the Order instance that was purchased. The SerializesModels trait used by the event will gracefully serialize any Eloquent models if the event object is serialized using PHP’s serialize function.

<a name=“defining-listeners”></a>

29.4 Defining Listeners

Next, let’s take a look at the listener for our example event. Event listeners receive the event instance in their handle method. The event:generate command will automatically import the proper event class and type-hint the event on the handle method. Within the handle method, you may perform any actions necessary to respond to the event:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;

class SendShipmentNotification
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  OrderShipped  $event
     * @return void
     */
    public function handle(OrderShipped $event)
    {
        // Access the order using $event->order...
    }
}

{tip} Your event listeners may also type-hint any dependencies they need on their constructors. All event listeners are resolved via the Laravel service container, so dependencies will be injected automatically.

29.4.0.1 Stopping The Propagation Of An Event

Sometimes, you may wish to stop the propagation of an event to other listeners. You may do so by returning false from your listener’s handle method.

<a name=“queued-event-listeners”></a>

29.5 Queued Event Listeners

Queueing listeners can be beneficial if your listener is going to perform a slow task such as sending an e-mail or making an HTTP request. Before getting started with queued listeners, make sure to configure your queue and start a queue listener on your server or local development environment.

To specify that a listener should be queued, add the ShouldQueue interface to the listener class. Listeners generated by the event:generate Artisan command already have this interface imported into the current namespace, so you can use it immediately:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
    //
}

That’s it! Now, when this listener is called for an event, it will be automatically queued by the event dispatcher using Laravel’s queue system. If no exceptions are thrown when the listener is executed by the queue, the queued job will automatically be deleted after it has finished processing.

29.5.0.1 Customizing The Queue Connection & Queue Name

If you would like to customize the queue connection and queue name used by an event listener, you may define $connection and $queue properties on your listener class:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
    /**
     * The name of the connection the job should be sent to.
     *
     * @var string|null
     */
    public $connection = 'sqs';

    /**
     * The name of the queue the job should be sent to.
     *
     * @var string|null
     */
    public $queue = 'listeners';
}

<a name=“manually-accessing-the-queue”></a>

29.5.1 Manually Accessing The Queue

If you need to manually access the listener’s underlying queue job’s delete and release methods, you may do so using the Illuminate\Queue\InteractsWithQueue trait. This trait is imported by default on generated listeners and provides access to these methods:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
    use InteractsWithQueue;

    /**
     * Handle the event.
     *
     * @param  \App\Events\OrderShipped  $event
     * @return void
     */
    public function handle(OrderShipped $event)
    {
        if (true) {
            $this->release(30);
        }
    }
}

<a name=“handling-failed-jobs”></a>

29.5.2 Handling Failed Jobs

Sometimes your queued event listeners may fail. If queued listener exceeds the maximum number of attempts as defined by your queue worker, the failed method will be called on your listener. The failed method receives the event instance and the exception that caused the failure:

<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
    use InteractsWithQueue;

    /**
     * Handle the event.
     *
     * @param  \App\Events\OrderShipped  $event
     * @return void
     */
    public function handle(OrderShipped $event)
    {
        //
    }

    /**
     * Handle a job failure.
     *
     * @param  \App\Events\OrderShipped  $event
     * @param  \Exception  $exception
     * @return void
     */
    public function failed(OrderShipped $event, $exception)
    {
        //
    }
}

<a name=“dispatching-events”></a>

29.6 Dispatching Events

To dispatch an event, you may pass an instance of the event to the event helper. The helper will dispatch the event to all of its registered listeners. Since the event helper is globally available, you may call it from anywhere in your application:

<?php

namespace App\Http\Controllers;

use App\Order;
use App\Events\OrderShipped;
use App\Http\Controllers\Controller;

class OrderController extends Controller
{
    /**
     * Ship the given order.
     *
     * @param  int  $orderId
     * @return Response
     */
    public function ship($orderId)
    {
        $order = Order::findOrFail($orderId);

        // Order shipment logic...

        event(new OrderShipped($order));
    }
}

{tip} When testing, it can be helpful to assert that certain events were dispatched without actually triggering their listeners. Laravel’s built-in testing helpers makes it a cinch.

<a name=“event-subscribers”></a>

29.7 Event Subscribers

<a name=“writing-event-subscribers”></a>

29.7.1 Writing Event Subscribers

Event subscribers are classes that may subscribe to multiple events from within the class itself, allowing you to define several event handlers within a single class. Subscribers should define a subscribe method, which will be passed an event dispatcher instance. You may call the listen method on the given dispatcher to register event listeners:

<?php

namespace App\Listeners;

class UserEventSubscriber
{
    /**
     * Handle user login events.
     */
    public function onUserLogin($event) {}

    /**
     * Handle user logout events.
     */
    public function onUserLogout($event) {}

    /**
     * Register the listeners for the subscriber.
     *
     * @param  Illuminate\Events\Dispatcher  $events
     */
    public function subscribe($events)
    {
        $events->listen(
            'Illuminate\Auth\Events\Login',
            'App\Listeners\UserEventSubscriber@onUserLogin'
        );

        $events->listen(
            'Illuminate\Auth\Events\Logout',
            'App\Listeners\UserEventSubscriber@onUserLogout'
        );
    }

}

<a name=“registering-event-subscribers”></a>

29.7.2 Registering Event Subscribers

After writing the subscriber, you are ready to register it with the event dispatcher. You may register subscribers using the $subscribe property on the EventServiceProvider. For example, let’s add the UserEventSubscriber to the list:

<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        //
    ];

    /**
     * The subscriber classes to register.
     *
     * @var array
     */
    protected $subscribe = [
        'App\Listeners\UserEventSubscriber',
    ];
}

30 Facades

<a name=“introduction”></a>

30.1 Introduction

Facades provide a “static” interface to classes that are available in the application’s service container. Laravel ships with many facades which provide access to almost all of Laravel’s features. Laravel facades serve as “static proxies” to underlying classes in the service container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.

All of Laravel’s facades are defined in the Illuminate\Support\Facades namespace. So, we can easily access a facade like so:

use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});

Throughout the Laravel documentation, many of the examples will use facades to demonstrate various features of the framework.

<a name=“when-to-use-facades”></a>

30.2 When To Use Facades

Facades have many benefits. They provide a terse, memorable syntax that allows you to use Laravel’s features without remembering long class names that must be injected or configured manually. Furthermore, because of their unique usage of PHP’s dynamic methods, they are easy to test.

However, some care must be taken when using facades. The primary danger of facades is class scope creep. Since facades are so easy to use and do not require injection, it can be easy to let your classes continue to grow and use many facades in a single class. Using dependency injection, this potential is mitigated by the visual feedback a large constructor gives you that your class is growing too large. So, when using facades, pay special attention to the size of your class so that its scope of responsibility stays narrow.

{tip} When building a third-party package that interacts with Laravel, it’s better to inject Laravel contracts instead of using facades. Since packages are built outside of Laravel itself, you will not have access to Laravel’s facade testing helpers.

<a name=“facades-vs-dependency-injection”></a>

30.2.1 Facades Vs. Dependency Injection

One of the primary benefits of dependency injection is the ability to swap implementations of the injected class. This is useful during testing since you can inject a mock or stub and assert that various methods were called on the stub.

Typically, it would not be possible to mock or stub a truly static class method. However, since facades use dynamic methods to proxy method calls to objects resolved from the service container, we actually can test facades just as we would test an injected class instance. For example, given the following route:

use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});

We can write the following test to verify that the Cache::get method was called with the argument we expected:

use Illuminate\Support\Facades\Cache;

/**
 * A basic functional test example.
 *
 * @return void
 */
public function testBasicExample()
{
    Cache::shouldReceive('get')
         ->with('key')
         ->andReturn('value');

    $this->visit('/cache')
         ->see('value');
}

<a name=“facades-vs-helper-functions”></a>

30.2.2 Facades Vs. Helper Functions

In addition to facades, Laravel includes a variety of “helper” functions which can perform common tasks like generating views, firing events, dispatching jobs, or sending HTTP responses. Many of these helper functions perform the same function as a corresponding facade. For example, this facade call and helper call are equivalent:

return View::make('profile');

return view('profile');

There is absolutely no practical difference between facades and helper functions. When using helper functions, you may still test them exactly as you would the corresponding facade. For example, given the following route:

Route::get('/cache', function () {
    return cache('key');
});

Under the hood, the cache helper is going to call the get method on the class underlying the Cache facade. So, even though we are using the helper function, we can write the following test to verify that the method was called with the argument we expected:

use Illuminate\Support\Facades\Cache;

/**
 * A basic functional test example.
 *
 * @return void
 */
public function testBasicExample()
{
    Cache::shouldReceive('get')
         ->with('key')
         ->andReturn('value');

    $this->visit('/cache')
         ->see('value');
}

<a name=“how-facades-work”></a>

30.3 How Facades Work

In a Laravel application, a facade is a class that provides access to an object from the container. The machinery that makes this work is in the Facade class. Laravel’s facades, and any custom facades you create, will extend the base Illuminate\Support\Facades\Facade class.

The Facade base class makes use of the __callStatic() magic-method to defer calls from your facade to an object resolved from the container. In the example below, a call is made to the Laravel cache system. By glancing at this code, one might assume that the static method get is being called on the Cache class:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        $user = Cache::get('user:'.$id);

        return view('profile', ['user' => $user]);
    }
}

Notice that near the top of the file we are “importing” the Cache facade. This facade serves as a proxy to accessing the underlying implementation of the Illuminate\Contracts\Cache\Factory interface. Any calls we make using the facade will be passed to the underlying instance of Laravel’s cache service.

If we look at that Illuminate\Support\Facades\Cache class, you’ll see that there is no static method get:

class Cache extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor() { return 'cache'; }
}

Instead, the Cache facade extends the base Facade class and defines the method getFacadeAccessor(). This method’s job is to return the name of a service container binding. When a user references any static method on the Cache facade, Laravel resolves the cache binding from the service container and runs the requested method (in this case, get) against that object.

<a name=“real-time-facades”></a>

30.4 Real-Time Facades

Using real-time facades, you may treat any class in your application as if it were a facade. To illustrate how this can be used, let’s examine an alternative. For example, let’s assume our Podcast model has a publish method. However, in order to publish the podcast, we need to inject a Publisher instance:

<?php

namespace App;

use App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * Publish the podcast.
     *
     * @param  Publisher  $publisher
     * @return void
     */
    public function publish(Publisher $publisher)
    {
        $this->update(['publishing' => now()]);

        $publisher->publish($this);
    }
}

Injecting a publisher implementation into the method allows us to easily test the method in isolation since we can mock the injected publisher. However, it requires us to always pass a publisher instance each time we call the publish method. Using real-time facades, we can maintain the same testability while not being required to explicitly pass a Publisher instance. To generate a real-time facade, prefix the namespace of the imported class with Facades:

<?php

namespace App;

use Facades\App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * Publish the podcast.
     *
     * @return void
     */
    public function publish()
    {
        $this->update(['publishing' => now()]);

        Publisher::publish($this);
    }
}

When the real-time facade is used, the publisher implementation will be resolved out of the service container using the portion of the interface or class name that appears after the Facades prefix. When testing, we can use Laravel’s built-in facade testing helpers to mock this method call:

<?php

namespace Tests\Feature;

use App\Podcast;
use Tests\TestCase;
use Facades\App\Contracts\Publisher;
use Illuminate\Foundation\Testing\RefreshDatabase;

class PodcastTest extends TestCase
{
    use RefreshDatabase;

    /**
     * A test example.
     *
     * @return void
     */
    public function test_podcast_can_be_published()
    {
        $podcast = factory(Podcast::class)->create();

        Publisher::shouldReceive('publish')->once()->with($podcast);

        $podcast->publish();
    }
}

<a name=“facade-class-reference”></a>

30.5 Facade Class Reference

Below you will find every facade and its underlying class. This is a useful tool for quickly digging into the API documentation for a given facade root. The service container binding key is also included where applicable.

Facade Class Service Container Binding
App Illuminate\Foundation\Application app
Artisan Illuminate\Contracts\Console\Kernel artisan
Auth Illuminate\Auth\AuthManager auth
Auth (Instance) Illuminate\Contracts\Auth\Guard auth.driver
Blade Illuminate\View\Compilers\BladeCompiler blade.compiler
Broadcast Illuminate\Contracts\Broadcasting\Factory  
Broadcast (Instance) Illuminate\Contracts\Broadcasting\Broadcaster  
Bus Illuminate\Contracts\Bus\Dispatcher  
Cache Illuminate\Cache\CacheManager cache
Cache (Instance) Illuminate\Cache\Repository cache.store
Config Illuminate\Config\Repository config
Cookie Illuminate\Cookie\CookieJar cookie
Crypt Illuminate\Encryption\Encrypter encrypter
DB Illuminate\Database\DatabaseManager db
DB (Instance) Illuminate\Database\Connection db.connection
Event Illuminate\Events\Dispatcher events
File Illuminate\Filesystem\Filesystem files
Gate Illuminate\Contracts\Auth\Access\Gate  
Hash Illuminate\Contracts\Hashing\Hasher hash
Lang Illuminate\Translation\Translator translator
Log Illuminate\Log\Writer log
Mail Illuminate\Mail\Mailer mailer
Notification Illuminate\Notifications\ChannelManager  
Password Illuminate\Auth\Passwords\PasswordBrokerManager auth.password
Password (Instance) Illuminate\Auth\Passwords\PasswordBroker auth.password.broker
Queue Illuminate\Queue\QueueManager queue
Queue (Instance) Illuminate\Contracts\Queue\Queue queue.connection
Queue (Base Class) Illuminate\Queue\Queue  
Redirect Illuminate\Routing\Redirector redirect
Redis Illuminate\Redis\RedisManager redis
Redis (Instance) Illuminate\Redis\Connections\Connection redis.connection
Request Illuminate\Http\Request request
Response Illuminate\Contracts\Routing\ResponseFactory  
Response (Instance) Illuminate\Http\Response  
Route Illuminate\Routing\Router router
Schema Illuminate\Database\Schema\Builder  
Session Illuminate\Session\SessionManager session
Session (Instance) Illuminate\Session\Store session.store
Storage Illuminate\Filesystem\FilesystemManager filesystem
Storage (Instance) Illuminate\Contracts\Filesystem\Filesystem filesystem.disk
URL Illuminate\Routing\UrlGenerator url
Validator Illuminate\Validation\Factory validator
Validator (Instance) Illuminate\Validation\Validator  
View Illuminate\View\Factory view
View (Instance) Illuminate\View\View  

31 File Storage

<a name=“introduction”></a>

31.1 Introduction

Laravel provides a powerful filesystem abstraction thanks to the wonderful Flysystem PHP package by Frank de Jonge. The Laravel Flysystem integration provides simple to use drivers for working with local filesystems, Amazon S3, and Rackspace Cloud Storage. Even better, it’s amazingly simple to switch between these storage options as the API remains the same for each system.

<a name=“configuration”></a>

31.2 Configuration

The filesystem configuration file is located at config/filesystems.php. Within this file you may configure all of your “disks”. Each disk represents a particular storage driver and storage location. Example configurations for each supported driver are included in the configuration file. So, modify the configuration to reflect your storage preferences and credentials.

Of course, you may configure as many disks as you like, and may even have multiple disks that use the same driver.

<a name=“the-public-disk”></a>

31.2.1 The Public Disk

The public disk is intended for files that are going to be publicly accessible. By default, the public disk uses the local driver and stores these files in storage/app/public. To make them accessible from the web, you should create a symbolic link from public/storage to storage/app/public. This convention will keep your publicly accessible files in one directory that can be easily shared across deployments when using zero down-time deployment systems like Envoyer.

To create the symbolic link, you may use the storage:link Artisan command:

php artisan storage:link

Of course, once a file has been stored and the symbolic link has been created, you can create a URL to the files using the asset helper:

echo asset('storage/file.txt');

<a name=“the-local-driver”></a>

31.2.2 The Local Driver

When using the local driver, all file operations are relative to the root directory defined in your configuration file. By default, this value is set to the storage/app directory. Therefore, the following method would store a file in storage/app/file.txt:

Storage::disk('local')->put('file.txt', 'Contents');

<a name=“driver-prerequisites”></a>

31.2.3 Driver Prerequisites

31.2.3.1 Composer Packages

Before using the S3 or Rackspace drivers, you will need to install the appropriate package via Composer:

  • Amazon S3: league/flysystem-aws-s3-v3 ~1.0
  • Rackspace: league/flysystem-rackspace ~1.0

31.2.3.2 S3 Driver Configuration

The S3 driver configuration information is located in your config/filesystems.php configuration file. This file contains an example configuration array for an S3 driver. You are free to modify this array with your own S3 configuration and credentials. For convenience, these environment variables match the naming convention used by the AWS CLI.

31.2.3.3 FTP Driver Configuration

Laravel’s Flysystem integrations works great with FTP; however, a sample configuration is not included with the framework’s default filesystems.php configuration file. If you need to configure a FTP filesystem, you may use the example configuration below:

'ftp' => [
    'driver'   => 'ftp',
    'host'     => 'ftp.example.com',
    'username' => 'your-username',
    'password' => 'your-password',

    // Optional FTP Settings...
    // 'port'     => 21,
    // 'root'     => '',
    // 'passive'  => true,
    // 'ssl'      => true,
    // 'timeout'  => 30,
],

31.2.3.4 Rackspace Driver Configuration

Laravel’s Flysystem integrations works great with Rackspace; however, a sample configuration is not included with the framework’s default filesystems.php configuration file. If you need to configure a Rackspace filesystem, you may use the example configuration below:

'rackspace' => [
    'driver'    => 'rackspace',
    'username'  => 'your-username',
    'key'       => 'your-key',
    'container' => 'your-container',
    'endpoint'  => 'https://identity.api.rackspacecloud.com/v2.0/',
    'region'    => 'IAD',
    'url_type'  => 'publicURL',
],

<a name=“obtaining-disk-instances”></a>

31.3 Obtaining Disk Instances

The Storage facade may be used to interact with any of your configured disks. For example, you may use the put method on the facade to store an avatar on the default disk. If you call methods on the Storage facade without first calling the disk method, the method call will automatically be passed to the default disk:

use Illuminate\Support\Facades\Storage;

Storage::put('avatars/1', $fileContents);

If your applications interacts with multiple disks, you may use the disk method on the Storage facade to work with files on a particular disk:

Storage::disk('s3')->put('avatars/1', $fileContents);

<a name=“retrieving-files”></a>

31.4 Retrieving Files

The get method may be used to retrieve the contents of a file. The raw string contents of the file will be returned by the method. Remember, all file paths should be specified relative to the “root” location configured for the disk:

$contents = Storage::get('file.jpg');

The exists method may be used to determine if a file exists on the disk:

$exists = Storage::disk('s3')->exists('file.jpg');

<a name=“file-urls”></a>

31.4.1 File URLs

You may use the url method to get the URL for the given file. If you are using the local driver, this will typically just prepend /storage to the given path and return a relative URL to the file. If you are using the s3 or rackspace driver, the fully qualified remote URL will be returned:

use Illuminate\Support\Facades\Storage;

$url = Storage::url('file1.jpg');

{note} Remember, if you are using the local driver, all files that should be publicly accessible should be placed in the storage/app/public directory. Furthermore, you should create a symbolic link at public/storage which points to the storage/app/public directory.

31.4.1.1 Temporary URLs

For files stored using the s3 or rackspace driver, you may create a temporary URL to a given file using the temporaryUrl method. This methods accepts a path and a DateTime instance specifying when the URL should expire:

$url = Storage::temporaryUrl(
    'file1.jpg', now()->addMinutes(5)
);

31.4.1.2 Local URL Host Customization

If you would like to pre-define the host for files stored on a disk using the local driver, you may add a url option to the disk’s configuration array:

'public' => [
    'driver' => 'local',
    'root' => storage_path('app/public'),
    'url' => env('APP_URL').'/storage',
    'visibility' => 'public',
],

<a name=“file-metadata”></a>

31.4.2 File Metadata

In addition to reading and writing files, Laravel can also provide information about the files themselves. For example, the size method may be used to get the size of the file in bytes:

use Illuminate\Support\Facades\Storage;

$size = Storage::size('file1.jpg');

The lastModified method returns the UNIX timestamp of the last time the file was modified:

$time = Storage::lastModified('file1.jpg');

<a name=“storing-files”></a>

31.5 Storing Files

The put method may be used to store raw file contents on a disk. You may also pass a PHP resource to the put method, which will use Flysystem’s underlying stream support. Using streams is greatly recommended when dealing with large files:

use Illuminate\Support\Facades\Storage;

Storage::put('file.jpg', $contents);

Storage::put('file.jpg', $resource);

31.5.0.1 Automatic Streaming

If you would like Laravel to automatically manage streaming a given file to your storage location, you may use the putFile or putFileAs method. This method accepts either a Illuminate\Http\File or Illuminate\Http\UploadedFile instance and will automatically stream the file to your desired location:

use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;

// Automatically generate a unique ID for file name...
Storage::putFile('photos', new File('/path/to/photo'));

// Manually specify a file name...
Storage::putFileAs('photos', new File('/path/to/photo'), 'photo.jpg');

There are a few important things to note about the putFile method. Note that we only specified a directory name, not a file name. By default, the putFile method will generate a unique ID to serve as the file name. The path to the file will be returned by the putFile method so you can store the path, including the generated file name, in your database.

The putFile and putFileAs methods also accept an argument to specify the “visibility” of the stored file. This is particularly useful if you are storing the file on a cloud disk such as S3 and would like the file to be publicly accessible:

Storage::putFile('photos', new File('/path/to/photo'), 'public');

31.5.0.2 Prepending & Appending To Files

The prepend and append methods allow you to write to the beginning or end of a file:

Storage::prepend('file.log', 'Prepended Text');

Storage::append('file.log', 'Appended Text');

31.5.0.3 Copying & Moving Files

The copy method may be used to copy an existing file to a new location on the disk, while the move method may be used to rename or move an existing file to a new location:

Storage::copy('old/file1.jpg', 'new/file1.jpg');

Storage::move('old/file1.jpg', 'new/file1.jpg');

<a name=“file-uploads”></a>

31.5.1 File Uploads

In web applications, one of the most common use-cases for storing files is storing user uploaded files such as profile pictures, photos, and documents. Laravel makes it very easy to store uploaded files using the store method on an uploaded file instance. Call the store method with the path at which you wish to store the uploaded file:

<?php

namespace App\Http\Controllers;

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

class UserAvatarController extends Controller
{
    /**
     * Update the avatar for the user.
     *
     * @param  Request  $request
     * @return Response
     */
    public function update(Request $request)
    {
        $path = $request->file('avatar')->store('avatars');

        return $path;
    }
}

There are a few important things to note about this example. Note that we only specified a directory name, not a file name. By default, the store method will generate a unique ID to serve as the file name. The path to the file will be returned by the store method so you can store the path, including the generated file name, in your database.

You may also call the putFile method on the Storage facade to perform the same file manipulation as the example above:

$path = Storage::putFile('avatars', $request->file('avatar'));

31.5.1.1 Specifying A File Name

If you would not like a file name to be automatically assigned to your stored file, you may use the storeAs method, which receives the path, the file name, and the (optional) disk as its arguments:

$path = $request->file('avatar')->storeAs(
    'avatars', $request->user()->id
);

Of course, you may also use the putFileAs method on the Storage facade, which will perform the same file manipulation as the example above:

$path = Storage::putFileAs(
    'avatars', $request->file('avatar'), $request->user()->id
);

31.5.1.2 Specifying A Disk

By default, this method will use your default disk. If you would like to specify another disk, pass the disk name as the second argument to the store method:

$path = $request->file('avatar')->store(
    'avatars/'.$request->user()->id, 's3'
);

<a name=“file-visibility”></a>

31.5.2 File Visibility

In Laravel’s Flysystem integration, “visibility” is an abstraction of file permissions across multiple platforms. Files may either be declared public or private. When a file is declared public, you are indicating that the file should generally be accessible to others. For example, when using the S3 driver, you may retrieve URLs for public files.

You can set the visibility when setting the file via the put method:

use Illuminate\Support\Facades\Storage;

Storage::put('file.jpg', $contents, 'public');

If the file has already been stored, its visibility can be retrieved and set via the getVisibility and setVisibility methods:

$visibility = Storage::getVisibility('file.jpg');

Storage::setVisibility('file.jpg', 'public')

<a name=“deleting-files”></a>

31.6 Deleting Files

The delete method accepts a single filename or an array of files to remove from the disk:

use Illuminate\Support\Facades\Storage;

Storage::delete('file.jpg');

Storage::delete(['file1.jpg', 'file2.jpg']);

If necessary, you may specify the disk that the file should be deleted from:

use Illuminate\Support\Facades\Storage;

Storage::disk('s3')->delete('folder_path/file_name.jpg');

<a name=“directories”></a>

31.7 Directories

31.7.0.1 Get All Files Within A Directory

The files method returns an array of all of the files in a given directory. If you would like to retrieve a list of all files within a given directory including all sub-directories, you may use the allFiles method:

use Illuminate\Support\Facades\Storage;

$files = Storage::files($directory);

$files = Storage::allFiles($directory);

31.7.0.2 Get All Directories Within A Directory

The directories method returns an array of all the directories within a given directory. Additionally, you may use the allDirectories method to get a list of all directories within a given directory and all of its sub-directories:

$directories = Storage::directories($directory);

// Recursive...
$directories = Storage::allDirectories($directory);

31.7.0.3 Create A Directory

The makeDirectory method will create the given directory, including any needed sub-directories:

Storage::makeDirectory($directory);

31.7.0.4 Delete A Directory

Finally, the deleteDirectory may be used to remove a directory and all of its files:

Storage::deleteDirectory($directory);

<a name=“custom-filesystems”></a>

31.8 Custom Filesystems

Laravel’s Flysystem integration provides drivers for several “drivers” out of the box; however, Flysystem is not limited to these and has adapters for many other storage systems. You can create a custom driver if you want to use one of these additional adapters in your Laravel application.

In order to set up the custom filesystem you will need a Flysystem adapter. Let’s add a community maintained Dropbox adapter to our project:

composer require spatie/flysystem-dropbox

Next, you should create a service provider such as DropboxServiceProvider. In the provider’s boot method, you may use the Storage facade’s extend method to define the custom driver:

<?php

namespace App\Providers;

use Storage;
use League\Flysystem\Filesystem;
use Illuminate\Support\ServiceProvider;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;

class DropboxServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Storage::extend('dropbox', function ($app, $config) {
            $client = new DropboxClient(
                $config['authorizationToken']
            );

            return new Filesystem(new DropboxAdapter($client));
        });
    }

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

The first argument of the extend method is the name of the driver and the second is a Closure that receives the $app and $config variables. The resolver Closure must return an instance of League\Flysystem\Filesystem. The $config variable contains the values defined in config/filesystems.php for the specified disk.

Once you have created the service provider to register the extension, you may use the dropbox driver in your config/filesystems.php configuration file.

32 JavaScript & CSS Scaffolding

<a name=“introduction”></a>

32.1 Introduction

While Laravel does not dictate which JavaScript or CSS pre-processors you use, it does provide a basic starting point using Bootstrap and Vue that will be helpful for many applications. By default, Laravel uses NPM to install both of these frontend packages.

32.1.0.1 CSS

Laravel Mix provides a clean, expressive API over compiling SASS or Less, which are extensions of plain CSS that add variables, mixins, and other powerful features that make working with CSS much more enjoyable. In this document, we will briefly discuss CSS compilation in general; however, you should consult the full Laravel Mix documentation for more information on compiling SASS or Less.

32.1.0.2 JavaScript

Laravel does not require you to use a specific JavaScript framework or library to build your applications. In fact, you don’t have to use JavaScript at all. However, Laravel does include some basic scaffolding to make it easier to get started writing modern JavaScript using the Vue library. Vue provides an expressive API for building robust JavaScript applications using components. As with CSS, we may use Laravel Mix to easily compile JavaScript components into a single, browser-ready JavaScript file.

32.1.0.3 Removing The Frontend Scaffolding

If you would like to remove the frontend scaffolding from your application, you may use the preset Artisan command. This command, when combined with the none option, will remove the Bootstrap and Vue scaffolding from your application, leaving only a blank SASS file and a few common JavaScript utility libraries:

php artisan preset none

<a name=“writing-css”></a>

32.2 Writing CSS

Laravel’s package.json file includes the bootstrap-sass package to help you get started prototyping your application’s frontend using Bootstrap. However, feel free to add or remove packages from the package.json file as needed for your own application. You are not required to use the Bootstrap framework to build your Laravel application - it is provided as a good starting point for those who choose to use it.

Before compiling your CSS, install your project’s frontend dependencies using the Node package manager (NPM):

npm install

Once the dependencies have been installed using npm install, you can compile your SASS files to plain CSS using Laravel Mix. The npm run dev command will process the instructions in your webpack.mix.js file. Typically, your compiled CSS will be placed in the public/css directory:

npm run dev

The default webpack.mix.js included with Laravel will compile the resources/assets/sass/app.scss SASS file. This app.scss file imports a file of SASS variables and loads Bootstrap, which provides a good starting point for most applications. Feel free to customize the app.scss file however you wish or even use an entirely different pre-processor by configuring Laravel Mix.

<a name=“writing-javascript”></a>

32.3 Writing JavaScript

All of the JavaScript dependencies required by your application can be found in the package.json file in the project’s root directory. This file is similar to a composer.json file except it specifies JavaScript dependencies instead of PHP dependencies. You can install these dependencies using the Node package manager (NPM):

npm install

{tip} By default, the Laravel package.json file includes a few packages such as vue and axios to help you get started building your JavaScript application. Feel free to add or remove from the package.json file as needed for your own application.

Once the packages are installed, you can use the npm run dev command to compile your assets. Webpack is a module bundler for modern JavaScript applications. When you run the npm run dev command, Webpack will execute the instructions in your webpack.mix.js file:

npm run dev

By default, the Laravel webpack.mix.js file compiles your SASS and the resources/assets/js/app.js file. Within the app.js file you may register your Vue components or, if you prefer a different framework, configure your own JavaScript application. Your compiled JavaScript will typically be placed in the public/js directory.

{tip} The app.js file will load the resources/assets/js/bootstrap.js file which bootstraps and configures Vue, Axios, jQuery, and all other JavaScript dependencies. If you have additional JavaScript dependencies to configure, you may do so in this file.

<a name=“writing-vue-components”></a>

32.3.1 Writing Vue Components

By default, fresh Laravel applications contain an ExampleComponent.vue Vue component located in the resources/assets/js/components directory. The ExampleComponent.vue file is an example of a single file Vue component which defines its JavaScript and HTML template in the same file. Single file components provide a very convenient approach to building JavaScript driven applications. The example component is registered in your app.js file:

Vue.component(
    'example-component',
    require('./components/ExampleComponent.vue')
);

To use the component in your application, you may drop it into one of your HTML templates. For example, after running the make:auth Artisan command to scaffold your application’s authentication and registration screens, you could drop the component into the home.blade.php Blade template:

@extends('layouts.app')

@section('content')
    <example-component></example-component>
@endsection

{tip} Remember, you should run the npm run dev command each time you change a Vue component. Or, you may run the npm run watch command to monitor and automatically recompile your components each time they are modified.

Of course, if you are interested in learning more about writing Vue components, you should read the Vue documentation, which provides a thorough, easy-to-read overview of the entire Vue framework.

<a name=“using-react”></a>

32.3.2 Using React

If you prefer to use React to build your JavaScript application, Laravel makes it a cinch to swap the Vue scaffolding with React scaffolding. On any fresh Laravel application, you may use the preset command with the react option:

php artisan preset react

This single command will remove the Vue scaffolding and replace it with React scaffolding, including an example component.

33 Hashing

<a name=“introduction”></a>

33.1 Introduction

The Laravel Hash facade provides secure Bcrypt hashing for storing user passwords. If you are using the built-in LoginController and RegisterController classes that are included with your Laravel application, they will automatically use Bcrypt for registration and authentication.

{tip} Bcrypt is a great choice for hashing passwords because its “work factor” is adjustable, which means that the time it takes to generate a hash can be increased as hardware power increases.

<a name=“basic-usage”></a>

33.2 Basic Usage

You may hash a password by calling the make method on the Hash facade:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use App\Http\Controllers\Controller;

class UpdatePasswordController extends Controller
{
    /**
     * Update the password for the user.
     *
     * @param  Request  $request
     * @return Response
     */
    public function update(Request $request)
    {
        // Validate the new password length...

        $request->user()->fill([
            'password' => Hash::make($request->newPassword)
        ])->save();
    }
}

The make method also allows you to manage the work factor of the bcrypt hashing algorithm using the rounds option; however, the default is acceptable for most applications:

$hashed = Hash::make('password', [
    'rounds' => 12
]);

33.2.0.1 Verifying A Password Against A Hash

The check method allows you to verify that a given plain-text string corresponds to a given hash. However, if you are using the LoginController included with Laravel, you will probably not need to use this directly, as this controller automatically calls this method:

if (Hash::check('plain-text', $hashedPassword)) {
    // The passwords match...
}

33.2.0.2 Checking If A Password Needs To Be Rehashed

The needsRehash function allows you to determine if the work factor used by the hasher has changed since the password was hashed:

if (Hash::needsRehash($hashed)) {
    $hashed = Hash::make('plain-text');
}

34 Helpers

<a name=“introduction”></a>

34.1 Introduction

Laravel includes a variety of global “helper” PHP functions. Many of these functions are used by the framework itself; however, you are free to use them in your own applications if you find them convenient.

<a name=“available-methods”></a>

34.2 Available Methods

<style>
.collection-method-list > p {
column-count: 3; -moz-column-count: 3; -webkit-column-count: 3;
column-gap: 2em; -moz-column-gap: 2em; -webkit-column-gap: 2em;
}

.collection-method-list a {
    display: block;
}

</style>

34.2.1 Arrays & Objects

<div class=“collection-method-list” markdown=“1”>

array_add
array_collapse
array_divide
array_dot
array_except
array_first
array_flatten
array_forget
array_get
array_has
array_last
array_only
array_pluck
array_prepend
array_pull
array_random
array_set
array_sort
array_sort_recursive
array_where
array_wrap
data_fill
data_get
data_set
head
last
</div>

34.2.2 Paths

<div class=“collection-method-list” markdown=“1”>

app_path
base_path
config_path
database_path
mix
public_path
resource_path
storage_path

</div>

34.2.3 Strings

<div class=“collection-method-list” markdown=“1”>

__
camel_case
class_basename
e
ends_with
kebab_case
preg_replace_array
snake_case
starts_with
str_after
str_before
str_contains
str_finish
str_is
str_limit
str_plural
str_random
str_replace_array
str_replace_first
str_replace_last
str_singular
str_slug
str_start
studly_case
title_case
trans
trans_choice

</div>

34.2.4 URLs

<div class=“collection-method-list” markdown=“1”>

action
asset
secure_asset
route
secure_url
url

</div>

34.2.5 Miscellaneous

<div class=“collection-method-list” markdown=“1”>

abort
abort_if
abort_unless
app
auth
back
bcrypt
blank
broadcast
cache
class_uses_recursive
collect
config
cookie
csrf_field
csrf_token
dd
decrypt
dispatch
dispatch_now
dump
encrypt
env
event
factory
filled
info
logger
method_field
now
old
optional
policy
redirect
report
request
rescue
resolve
response
retry
session
tap
today
throw_if
throw_unless
trait_uses_recursive
transform
validator
value
view
with

</div>

<a name=“method-listing”></a>

34.3 Method Listing

<style>
#collection-method code {
font-size: 14px;
}

#collection-method:not(.first-collection-method) {
    margin-top: 50px;
}

</style>

<a name=“arrays”></a>

34.4 Arrays & Objects

<a name=“method-array-add”></a>

34.4.0.1 array_add() {#collection-method .first-collection-method}

The array_add function adds a given key / value pair to an array if the given key doesn’t already exist in the array:

$array = array_add(['name' => 'Desk'], 'price', 100);

// ['name' => 'Desk', 'price' => 100]

<a name=“method-array-collapse”></a>

34.4.0.2 array_collapse() {#collection-method}

The array_collapse function collapses an array of arrays into a single array:

$array = array_collapse([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);

// [1, 2, 3, 4, 5, 6, 7, 8, 9]

<a name=“method-array-divide”></a>

34.4.0.3 array_divide() {#collection-method}

The array_divide function returns two arrays, one containing the keys, and the other containing the values of the given array:

list($keys, $values) = array_divide(['name' => 'Desk']);

// $keys: ['name']

// $values: ['Desk']

<a name=“method-array-dot”></a>

34.4.0.4 array_dot() {#collection-method}

The array_dot function flattens a multi-dimensional array into a single level array that uses “dot” notation to indicate depth:

$array = ['products' => ['desk' => ['price' => 100]]];

$flattened = array_dot($array);

// ['products.desk.price' => 100]

<a name=“method-array-except”></a>

34.4.0.5 array_except() {#collection-method}

The array_except function removes the given key / value pairs from an array:

$array = ['name' => 'Desk', 'price' => 100];

$filtered = array_except($array, ['price']);

// ['name' => 'Desk']

<a name=“method-array-first”></a>

34.4.0.6 array_first() {#collection-method}

The array_first function returns the first element of an array passing a given truth test:

$array = [100, 200, 300];

$first = array_first($array, function ($value, $key) {
    return $value >= 150;
});

// 200

A default value may also be passed as the third parameter to the method. This value will be returned if no value passes the truth test:

$first = array_first($array, $callback, $default);

<a name=“method-array-flatten”></a>

34.4.0.7 array_flatten() {#collection-method}

The array_flatten function flattens a multi-dimensional array into a single level array:

$array = ['name' => 'Joe', 'languages' => ['PHP', 'Ruby']];

$flattened = array_flatten($array);

// ['Joe', 'PHP', 'Ruby']

<a name=“method-array-forget”></a>

34.4.0.8 array_forget() {#collection-method}

The array_forget function removes a given key / value pair from a deeply nested array using “dot” notation:

$array = ['products' => ['desk' => ['price' => 100]]];

array_forget($array, 'products.desk');

// ['products' => []]

<a name=“method-array-get”></a>

34.4.0.9 array_get() {#collection-method}

The array_get function retrieves a value from a deeply nested array using “dot” notation:

$array = ['products' => ['desk' => ['price' => 100]]];

$price = array_get($array, 'products.desk.price');

// 100

The array_get function also accepts a default value, which will be returned if the specific key is not found:

$discount = array_get($array, 'products.desk.discount', 0);

// 0

<a name=“method-array-has”></a>

34.4.0.10 array_has() {#collection-method}

The array_has function checks whether a given item or items exists in an array using “dot” notation:

$array = ['product' => ['name' => 'Desk', 'price' => 100]];

$contains = array_has($array, 'product.name');

// true

$contains = array_has($array, ['product.price', 'product.discount']);

// false

<a name=“method-array-last”></a>

34.4.0.11 array_last() {#collection-method}

The array_last function returns the last element of an array passing a given truth test:

$array = [100, 200, 300, 110];

$last = array_last($array, function ($value, $key) {
    return $value >= 150;
});

// 300

A default value may be passed as the third argument to the method. This value will be returned if no value passes the truth test:

$last = array_last($array, $callback, $default);

<a name=“method-array-only”></a>

34.4.0.12 array_only() {#collection-method}

The array_only function returns only the specified key / value pairs from the given array:

$array = ['name' => 'Desk', 'price' => 100, 'orders' => 10];

$slice = array_only($array, ['name', 'price']);

// ['name' => 'Desk', 'price' => 100]

<a name=“method-array-pluck”></a>

34.4.0.13 array_pluck() {#collection-method}

The array_pluck function retrieves all of the values for a given key from an array:

$array = [
    ['developer' => ['id' => 1, 'name' => 'Taylor']],
    ['developer' => ['id' => 2, 'name' => 'Abigail']],
];

$names = array_pluck($array, 'developer.name');

// ['Taylor', 'Abigail']

You may also specify how you wish the resulting list to be keyed:

$names = array_pluck($array, 'developer.name', 'developer.id');

// [1 => 'Taylor', 2 => 'Abigail']

<a name=“method-array-prepend”></a>

34.4.0.14 array_prepend() {#collection-method}

The array_prepend function will push an item onto the beginning of an array:

$array = ['one', 'two', 'three', 'four'];

$array = array_prepend($array, 'zero');

// ['zero', 'one', 'two', 'three', 'four']

If needed, you may specify the key that should be used for the value:

$array = ['price' => 100];

$array = array_prepend($array, 'Desk', 'name');

// ['name' => 'Desk', 'price' => 100]

<a name=“method-array-pull”></a>

34.4.0.15 array_pull() {#collection-method}

The array_pull function returns and removes a key / value pair from an array:

$array = ['name' => 'Desk', 'price' => 100];

$name = array_pull($array, 'name');

// $name: Desk

// $array: ['price' => 100]

A default value may be passed as the third argument to the method. This value will be returned if the key doesn’t exist:

$value = array_pull($array, $key, $default);

<a name=“method-array-random”></a>

34.4.0.16 array_random() {#collection-method}

The array_random function returns a random value from an array:

$array = [1, 2, 3, 4, 5];

$random = array_random($array);

// 4 - (retrieved randomly)

You may also specify the number of items to return as an optional second argument. Note that providing this argument will return an array, even if only one item is desired:

$items = array_random($array, 2);

// [2, 5] - (retrieved randomly)

<a name=“method-array-set”></a>

34.4.0.17 array_set() {#collection-method}

The array_set function sets a value within a deeply nested array using “dot” notation:

$array = ['products' => ['desk' => ['price' => 100]]];

array_set($array, 'products.desk.price', 200);

// ['products' => ['desk' => ['price' => 200]]]

<a name=“method-array-sort”></a>

34.4.0.18 array_sort() {#collection-method}

The array_sort function sorts an array by its values:

$array = ['Desk', 'Table', 'Chair'];

$sorted = array_sort($array);

// ['Chair', 'Desk', 'Table']

You may also sort the array by the results of the given Closure:

$array = [
    ['name' => 'Desk'],
    ['name' => 'Table'],
    ['name' => 'Chair'],
];

$sorted = array_values(array_sort($array, function ($value) {
    return $value['name'];
}));

/*
    [
        ['name' => 'Chair'],
        ['name' => 'Desk'],
        ['name' => 'Table'],
    ]
*/

<a name=“method-array-sort-recursive”></a>

34.4.0.19 array_sort_recursive() {#collection-method}

The array_sort_recursive function recursively sorts an array using the sort function:

$array = [
    ['Roman', 'Taylor', 'Li'],
    ['PHP', 'Ruby', 'JavaScript'],
];

$sorted = array_sort_recursive($array);

/*
    [
        ['Li', 'Roman', 'Taylor'],
        ['JavaScript', 'PHP', 'Ruby'],
    ]
*/

<a name=“method-array-where”></a>

34.4.0.20 array_where() {#collection-method}

The array_where function filters an array using the given Closure:

$array = [100, '200', 300, '400', 500];

$filtered = array_where($array, function ($value, $key) {
    return is_string($value);
});

// [1 => 200, 3 => 400]

<a name=“method-array-wrap”></a>

34.4.0.21 array_wrap() {#collection-method}

The array_wrap function wraps the given value in an array. If the given value is already an array it will not be changed:

$string = 'Laravel';

$array = array_wrap($string);

// ['Laravel']

If the given value is null, an empty array will be returned:

$nothing = null;

$array = array_wrap($nothing);

// []

<a name=“method-data-fill”></a>

34.4.0.22 data_fill() {#collection-method}

The data_fill function sets a missing value within a nested array or object using “dot” notation:

$data = ['products' => ['desk' => ['price' => 100]]];

data_fill($data, 'products.desk.price', 200);

// ['products' => ['desk' => ['price' => 100]]]

data_fill($data, 'products.desk.discount', 10);

// ['products' => ['desk' => ['price' => 100, 'discount' => 10]]]

This function also accepts asterisks as wildcards and will fill the target accordingly:

$data = [
    'products' => [
        ['name' => 'Desk 1', 'price' => 100],
        ['name' => 'Desk 2'],
    ],
];

data_fill($data, 'products.*.price', 200);

/*
    [
        'products' => [
            ['name' => 'Desk 1', 'price' => 100],
            ['name' => 'Desk 2', 'price' => 200],
        ],
    ]
*/

<a name=“method-data-get”></a>

34.4.0.23 data_get() {#collection-method}

The data_get function retrieves a value from a nested array or object using “dot” notation:

$data = ['products' => ['desk' => ['price' => 100]]];

$price = data_get($data, 'products.desk.price');

// 100

The data_get function also accepts a default value, which will be returned if the specified key is not found:

$discount = data_get($data, 'products.desk.discount', 0);

// 0

<a name=“method-data-set”></a>

34.4.0.24 data_set() {#collection-method}

The data_set function sets a value within a nested array or object using “dot” notation:

$data = ['products' => ['desk' => ['price' => 100]]];

data_set($data, 'products.desk.price', 200);

// ['products' => ['desk' => ['price' => 200]]]

This function also accepts wildcards and will set values on the target accordingly:

$data = [
    'products' => [
        ['name' => 'Desk 1', 'price' => 100],
        ['name' => 'Desk 2', 'price' => 150],
    ],
];

data_set($data, 'products.*.price', 200);

/*
    [
        'products' => [
            ['name' => 'Desk 1', 'price' => 200],
            ['name' => 'Desk 2', 'price' => 200],
        ],
    ]
*/

By default, any existing values are overwritten. If you wish to only set a value if it doesn’t exist, you may pass false as the third argument:

$data = ['products' => ['desk' => ['price' => 100]]];

data_set($data, 'products.desk.price', 200, false);

// ['products' => ['desk' => ['price' => 100]]]

<a name=“method-head”></a>

34.4.0.25 head() {#collection-method}

The head function returns the first element in the given array:

$array = [100, 200, 300];

$first = head($array);

// 100

<a name=“method-last”></a>

34.4.0.26 last() {#collection-method}

The last function returns the last element in the given array:

$array = [100, 200, 300];

$last = last($array);

// 300

<a name=“paths”></a>

34.5 Paths

<a name=“method-app-path”></a>

34.5.0.1 app_path() {#collection-method}

The app_path function returns the fully qualified path to the app directory. You may also use the app_path function to generate a fully qualified path to a file relative to the application directory:

$path = app_path();

$path = app_path('Http/Controllers/Controller.php');

<a name=“method-base-path”></a>

34.5.0.2 base_path() {#collection-method}

The base_path function returns the fully qualified path to the project root. You may also use the base_path function to generate a fully qualified path to a given file relative to the project root directory:

$path = base_path();

$path = base_path('vendor/bin');

<a name=“method-config-path”></a>

34.5.0.3 config_path() {#collection-method}

The config_path function returns the fully qualified path to the config directory. You may also use the config_path function to generate a fully qualified path to a given file within the application’s configuration directory:

$path = config_path();

$path = config_path('app.php');

<a name=“method-database-path”></a>

34.5.0.4 database_path() {#collection-method}

The database_path function returns the fully qualified path to the database directory. You may also use the database_path function to generate a fully qualified path to a given file within the database directory:

$path = database_path();

$path = database_path('factories/UserFactory.php');

<a name=“method-mix”></a>

34.5.0.5 mix() {#collection-method}

The mix function returns the path to a versioned Mix file:

$path = mix('css/app.css');

<a name=“method-public-path”></a>

34.5.0.6 public_path() {#collection-method}

The public_path function returns the fully qualified path to the public directory. You may also use the public_path function to generate a fully qualified path to a given file within the public directory:

$path = public_path();

$path = public_path('css/app.css');

<a name=“method-resource-path”></a>

34.5.0.7 resource_path() {#collection-method}

The resource_path function returns the fully qualified path to the resources directory. You may also use the resource_path function to generate a fully qualified path to a given file within the resources directory:

$path = resource_path();

$path = resource_path('assets/sass/app.scss');

<a name=“method-storage-path”></a>

34.5.0.8 storage_path() {#collection-method}

The storage_path function returns the fully qualified path to the storage directory. You may also use the storage_path function to generate a fully qualified path to a given file within the storage directory:

$path = storage_path();

$path = storage_path('app/file.txt');

<a name=“strings”></a>

34.6 Strings

<a name=“method-__“></a>

34.6.0.1 __() {#collection-method}

The __ function translates the given translation string or translation key using your localization files:

echo __('Welcome to our application');

echo __('messages.welcome');

If the specified translation string or key does not exist, the __ function will return the given value. So, using the example above, the __ function would return messages.welcome if that translation key does not exist.

<a name=“method-camel-case”></a>

34.6.0.2 camel_case() {#collection-method}

The camel_case function converts the given string to camelCase:

$converted = camel_case('foo_bar');

// fooBar

<a name=“method-class-basename”></a>

34.6.0.3 class_basename() {#collection-method}

The class_basename returns the class name of the given class with the class’ namespace removed:

$class = class_basename('Foo\Bar\Baz');

// Baz

<a name=“method-e”></a>

34.6.0.4 e() {#collection-method}

The e function runs PHP’s htmlspecialchars function with the double_encode option set to false:

echo e('<html>foo</html>');

// &lt;html&gt;foo&lt;/html&gt;

<a name=“method-ends-with”></a>

34.6.0.5 ends_with() {#collection-method}

The ends_with function determines if the given string ends with the given value:

$result = ends_with('This is my name', 'name');

// true

<a name=“method-kebab-case”></a>

34.6.0.6 kebab_case() {#collection-method}

The kebab_case function converts the given string to kebab-case:

$converted = kebab_case('fooBar');

// foo-bar

<a name=“method-preg-replace-array”></a>

34.6.0.7 preg_replace_array() {#collection-method}

The preg_replace_array function replaces a given pattern in the string sequentially using an array:

$string = 'The event will take place between :start and :end';

$replaced = preg_replace_array('/:[a-z_]+/', ['8:30', '9:00'], $string);

// The event will take place between 8:30 and 9:00

<a name=“method-snake-case”></a>

34.6.0.8 snake_case() {#collection-method}

The snake_case function converts the given string to snake_case:

$converted = snake_case('fooBar');

// foo_bar

<a name=“method-starts-with”></a>

34.6.0.9 starts_with() {#collection-method}

The starts_with function determines if the given string begins with the given value:

$result = starts_with('This is my name', 'This');

// true

<a name=“method-str-after”></a>

34.6.0.10 str_after() {#collection-method}

The str_after function returns everything after the given value in a string:

$slice = str_after('This is my name', 'This is');

// ' my name'

<a name=“method-str-before”></a>

34.6.0.11 str_before() {#collection-method}

The str_before function returns everything before the given value in a string:

$slice = str_before('This is my name', 'my name');

// 'This is '

<a name=“method-str-contains”></a>

34.6.0.12 str_contains() {#collection-method}

The str_contains function determines if the given string contains the given value (case sensitive):

$contains = str_contains('This is my name', 'my');

// true

You may also pass an array of values to determine if the given string contains any of the values:

$contains = str_contains('This is my name', ['my', 'foo']);

// true

<a name=“method-str-finish”></a>

34.6.0.13 str_finish() {#collection-method}

The str_finish function adds a single instance of the given value to a string if it does not already end with the value:

$adjusted = str_finish('this/string', '/');

// this/string/

$adjusted = str_finish('this/string/', '/');

// this/string/

<a name=“method-str-is”></a>

34.6.0.14 str_is() {#collection-method}

The str_is function determines if a given string matches a given pattern. Asterisks may be used to indicate wildcards:

$matches = str_is('foo*', 'foobar');

// true

$matches = str_is('baz*', 'foobar');

// false

<a name=“method-str-limit”></a>

34.6.0.15 str_limit() {#collection-method}

The str_limit function truncates the given string at the specified length:

$truncated = str_limit('The quick brown fox jumps over the lazy dog', 20);

// The quick brown fox...

You may also pass a third argument to change the string that will be appended to the end:

$truncated = str_limit('The quick brown fox jumps over the lazy dog', 20, ' (...)');

// The quick brown fox (...)

<a name=“method-str-plural”></a>

34.6.0.16 str_plural() {#collection-method}

The str_plural function converts a string to its plural form. This function currently only supports the English language:

$plural = str_plural('car');

// cars

$plural = str_plural('child');

// children

You may provide an integer as a second argument to the function to retrieve the singular or plural form of the string:

$plural = str_plural('child', 2);

// children

$plural = str_plural('child', 1);

// child

<a name=“method-str-random”></a>

34.6.0.17 str_random() {#collection-method}

The str_random function generates a random string of the specified length. This function uses PHP’s random_bytes function:

$random = str_random(40);

<a name=“method-str-replace-array”></a>

34.6.0.18 str_replace_array() {#collection-method}

The str_replace_array function replaces a given value in the string sequentially using an array:

$string = 'The event will take place between ? and ?';

$replaced = str_replace_array('?', ['8:30', '9:00'], $string);

// The event will take place between 8:30 and 9:00

<a name=“method-str-replace-first”></a>

34.6.0.19 str_replace_first() {#collection-method}

The str_replace_first function replaces the first occurrence of a given value in a string:

$replaced = str_replace_first('the', 'a', 'the quick brown fox jumps over the lazy dog');

// a quick brown fox jumps over the lazy dog

<a name=“method-str-replace-last”></a>

34.6.0.20 str_replace_last() {#collection-method}

The str_replace_last function replaces the last occurrence of a given value in a string:

$replaced = str_replace_last('the', 'a', 'the quick brown fox jumps over the lazy dog');

// the quick brown fox jumps over a lazy dog

<a name=“method-str-singular”></a>

34.6.0.21 str_singular() {#collection-method}

The str_singular function converts a string to its singular form. This function currently only supports the English language:

$singular = str_singular('cars');

// car

$singular = str_singular('children');

// child

<a name=“method-str-slug”></a>

34.6.0.22 str_slug() {#collection-method}

The str_slug function generates a URL friendly “slug” from the given string:

$slug = str_slug('Laravel 5 Framework', '-');

// laravel-5-framework

<a name=“method-str-start”></a>

34.6.0.23 str_start() {#collection-method}

The str_start function adds a single instance of the given value to a string if it does not already start with the value:

$adjusted = str_start('this/string', '/');

// /this/string

$adjusted = str_start('/this/string/', '/');

// /this/string

<a name=“method-studly-case”></a>

34.6.0.24 studly_case() {#collection-method}

The studly_case function converts the given string to StudlyCase:

$converted = studly_case('foo_bar');

// FooBar

<a name=“method-title-case”></a>

34.6.0.25 title_case() {#collection-method}

The title_case function converts the given string to Title Case:

$converted = title_case('a nice title uses the correct case');

// A Nice Title Uses The Correct Case

<a name=“method-trans”></a>

34.6.0.26 trans() {#collection-method}

The trans function translates the given translation key using your localization files:

echo trans('messages.welcome');

If the specified translation key does not exist, the trans function will return the given key. So, using the example above, the trans function would return messages.welcome if the translation key does not exist.

<a name=“method-trans-choice”></a>

34.6.0.27 trans_choice() {#collection-method}

The trans_choice function translates the given translation key with inflection:

echo trans_choice('messages.notifications', $unreadCount);

If the specified translation key does not exist, the trans_choice function will return the given key. So, using the example above, the trans_choice function would return messages.notifications if the translation key does not exist.

<a name=“urls”></a>

34.7 URLs

<a name=“method-action”></a>

34.7.0.1 action() {#collection-method}

The action function generates a URL for the given controller action. You do not need to pass the full namespace of the controller. Instead, pass the controller class name relative to the App\Http\Controllers namespace:

$url = action('HomeController@index');

If the method accepts route parameters, you may pass them as the second argument to the method:

$url = action('UserController@profile', ['id' => 1]);

<a name=“method-asset”></a>

34.7.0.2 asset() {#collection-method}

The asset function generates a URL for an asset using the current scheme of the request (HTTP or HTTPS):

$url = asset('img/photo.jpg');

<a name=“method-secure-asset”></a>

34.7.0.3 secure_asset() {#collection-method}

The secure_asset function generates a URL for an asset using HTTPS:

$url = secure_asset('img/photo.jpg');

<a name=“method-route”></a>

34.7.0.4 route() {#collection-method}

The route function generates a URL for the given named route:

$url = route('routeName');

If the route accepts parameters, you may pass them as the second argument to the method:

$url = route('routeName', ['id' => 1]);

By default, the route function generates an absolute URL. If you wish to generate a relative URL, you may pass false as the third argument:

$url = route('routeName', ['id' => 1], false);

<a name=“method-secure-url”></a>

34.7.0.5 secure_url() {#collection-method}

The secure_url function generates a fully qualified HTTPS URL to the given path:

$url = secure_url('user/profile');

$url = secure_url('user/profile', [1]);

<a name=“method-url”></a>

34.7.0.6 url() {#collection-method}

The url function generates a fully qualified URL to the given path:

$url = url('user/profile');

$url = url('user/profile', [1]);

If no path is provided, a Illuminate\Routing\UrlGenerator instance is returned:

$current = url()->current();

$full = url()->full();

$previous = url()->previous();

<a name=“miscellaneous”></a>

34.8 Miscellaneous

<a name=“method-abort”></a>

34.8.0.1 abort() {#collection-method}

The abort function throws an HTTP exception which will be rendered by the exception handler:

abort(403);

You may also provide the exception’s response text and custom response headers:

abort(403, 'Unauthorized.', $headers);

<a name=“method-abort-if”></a>

34.8.0.2 abort_if() {#collection-method}

The abort_if function throws an HTTP exception if a given boolean expression evaluates to true:

abort_if(! Auth::user()->isAdmin(), 403);

Like the abort method, you may also provide the exception’s response text as the third argument and an array of custom response headers as the fourth argument.

<a name=“method-abort-unless”></a>

34.8.0.3 abort_unless() {#collection-method}

The abort_unless function throws an HTTP exception if a given boolean expression evaluates to false:

abort_unless(Auth::user()->isAdmin(), 403);

Like the abort method, you may also provide the exception’s response text as the third argument and an array of custom response headers as the fourth argument.

<a name=“method-app”></a>

34.8.0.4 app() {#collection-method}

The app function returns the service container instance:

$container = app();

You may pass a class or interface name to resolve it from the container:

$api = app('HelpSpot\API');

<a name=“method-auth”></a>

34.8.0.5 auth() {#collection-method}

The auth function returns an authenticator instance. You may use it instead of the Auth facade for convenience:

$user = auth()->user();

If needed, you may specify which guard instance you would like to access:

$user = auth('admin')->user();

<a name=“method-back”></a>

34.8.0.6 back() {#collection-method}

The back function generates a redirect HTTP response to the user’s previous location:

return back($status = 302, $headers = [], $fallback = false);

return back();

<a name=“method-bcrypt”></a>

34.8.0.7 bcrypt() {#collection-method}

The bcrypt function hashes the given value using Bcrypt. You may use it as an alternative to the Hash facade:

$password = bcrypt('my-secret-password');

<a name=“method-broadcast”></a>

34.8.0.8 broadcast() {#collection-method}

The broadcast function broadcasts the given event to its listeners:

broadcast(new UserRegistered($user));

<a name=“method-blank”></a>

34.8.0.9 blank() {#collection-method}

The blank function returns whether the given value is “blank”:

blank('');
blank('   ');
blank(null);
blank(collect());

// true

blank(0);
blank(true);
blank(false);

// false

For the inverse of blank, see the filled method.

<a name=“method-cache”></a>

34.8.0.10 cache() {#collection-method}

The cache function may be used to get values from the cache. If the given key does not exist in the cache, an optional default value will be returned:

$value = cache('key');

$value = cache('key', 'default');

You may add items to the cache by passing an array of key / value pairs to the function. You should also pass the number of minutes or duration the cached value should be considered valid:

cache(['key' => 'value'], 5);

cache(['key' => 'value'], now()->addSeconds(10));

<a name=“method-class-uses-recursive”></a>

34.8.0.11 class_uses_recursive() {#collection-method}

The class_uses_recursive function returns all traits used by a class, including traits used by any subclasses:

$traits = class_uses_recursive(App\User::class);

<a name=“method-collect”></a>

34.8.0.12 collect() {#collection-method}

The collect function creates a collection instance from the given value:

$collection = collect(['taylor', 'abigail']);

<a name=“method-config”></a>

34.8.0.13 config() {#collection-method}

The config function gets the value of a configuration variable. The configuration values may be accessed using “dot” syntax, which includes the name of the file and the option you wish to access. A default value may be specified and is returned if the configuration option does not exist:

$value = config('app.timezone');

$value = config('app.timezone', $default);

You may set configuration variables at runtime by passing an array of key / value pairs:

config(['app.debug' => true]);

<a name=“method-cookie”></a>

The cookie function creates a new cookie instance:

$cookie = cookie('name', 'value', $minutes);

<a name=“method-csrf-field”></a>

34.8.0.15 csrf_field() {#collection-method}

The csrf_field function generates an HTML hidden input field containing the value of the CSRF token. For example, using Blade syntax:

{{ csrf_field() }}

<a name=“method-csrf-token”></a>

34.8.0.16 csrf_token() {#collection-method}

The csrf_token function retrieves the value of the current CSRF token:

$token = csrf_token();

<a name=“method-dd”></a>

34.8.0.17 dd() {#collection-method}

The dd function dumps the given variables and ends execution of the script:

dd($value);

dd($value1, $value2, $value3, ...);

If you do not want to halt the execution of your script, use the dump function instead.

<a name=“method-decrypt”></a>

34.8.0.18 decrypt() {#collection-method}

The decrypt function decrypts the given value using Laravel’s encrypter:

$decrypted = decrypt($encrypted_value);

<a name=“method-dispatch”></a>

34.8.0.19 dispatch() {#collection-method}

The dispatch function pushes the given job onto the Laravel job queue:

dispatch(new App\Jobs\SendEmails);

<a name=“method-dispatch-now”></a>

34.8.0.20 dispatch_now() {#collection-method}

The dispatch_now function runs the given job immediately and returns the value from its handle method:

$result = dispatch_now(new App\Jobs\SendEmails);

<a name=“method-dump”></a>

34.8.0.21 dump() {#collection-method}

The dump function dumps the given variables:

dump($value);

dump($value1, $value2, $value3, ...);

If you want to stop executing the script after dumping the variables, use the dd function instead.

<a name=“method-encrypt”></a>

34.8.0.22 encrypt() {#collection-method}

The encrypt function encrypts the given value using Laravel’s encrypter:

$encrypted = encrypt($unencrypted_value);

<a name=“method-env”></a>

34.8.0.23 env() {#collection-method}

The env function retrieves the value of an environment variable or returns a default value:

$env = env('APP_ENV');

// Returns 'production' if APP_ENV is not set...
$env = env('APP_ENV', 'production');

{note} If you execute the config:cache command during your deployment process, you should be sure that you are only calling the env function from within your configuration files. Once the configuration has been cached, the .env file will not be loaded and all calls to the env function will return null.

<a name=“method-event”></a>

34.8.0.24 event() {#collection-method}

The event function dispatches the given event to its listeners:

event(new UserRegistered($user));

<a name=“method-factory”></a>

34.8.0.25 factory() {#collection-method}

The factory function creates a model factory builder for a given class, name, and amount. It can be used while testing or seeding:

$user = factory(App\User::class)->make();

<a name=“method-filled”></a>

34.8.0.26 filled() {#collection-method}

The filled function returns whether the given value is not “blank”:

filled(0);
filled(true);
filled(false);

// true

filled('');
filled('   ');
filled(null);
filled(collect());

// false

For the inverse of filled, see the blank method.

<a name=“method-info”></a>

34.8.0.27 info() {#collection-method}

The info function will write information to the log:

info('Some helpful information!');

An array of contextual data may also be passed to the function:

info('User login attempt failed.', ['id' => $user->id]);

<a name=“method-logger”></a>

34.8.0.28 logger() {#collection-method}

The logger function can be used to write a debug level message to the log:

logger('Debug message');

An array of contextual data may also be passed to the function:

logger('User has logged in.', ['id' => $user->id]);

A logger instance will be returned if no value is passed to the function:

logger()->error('You are not allowed here.');

<a name=“method-method-field”></a>

34.8.0.29 method_field() {#collection-method}

The method_field function generates an HTML hidden input field containing the spoofed value of the form’s HTTP verb. For example, using Blade syntax:

<form method="POST">
    {{ method_field('DELETE') }}
</form>

<a name=“method-now”></a>

34.8.0.30 now() {#collection-method}

The now function creates a new Illuminate\Support\Carbon instance for the current time:

$now = now();

<a name=“method-old”></a>

34.8.0.31 old() {#collection-method}

The old function retrieves an old input value flashed into the session:

$value = old('value');

$value = old('value', 'default');

<a name=“method-optional”></a>

34.8.0.32 optional() {#collection-method}

The optional function accepts any argument and allows you to access properties or call methods on that object. If the given object is null, properties and methods will return null instead of causing an error:

return optional($user->address)->street;

{!! old('name', optional($user)->name) !!}

<a name=“method-policy”></a>

34.8.0.33 policy() {#collection-method}

The policy method retrieves a policy instance for a given class:

$policy = policy(App\User::class);

<a name=“method-redirect”></a>

34.8.0.34 redirect() {#collection-method}

The redirect function returns a redirect HTTP response, or returns the redirector instance if called with no arguments:

return redirect($to = null, $status = 302, $headers = [], $secure = null);

return redirect('/home');

return redirect()->route('route.name');

<a name=“method-report”></a>

34.8.0.35 report() {#collection-method}

The report function will report an exception using your exception handler’s report method:

report($e);

<a name=“method-request”></a>

34.8.0.36 request() {#collection-method}

The request function returns the current request instance or obtains an input item:

$request = request();

$value = request('key', $default);

<a name=“method-rescue”></a>

34.8.0.37 rescue() {#collection-method}

The rescue function executes the given Closure and catches any exceptions that occur during its execution. All exceptions that are caught will be sent to your exception handler’s report method; however, the request will continue processing:

return rescue(function () {
    return $this->method();
});

You may also pass a second argument to the rescue function. This argument will be the “default” value that should be returned if an exception occurs while executing the Closure:

return rescue(function () {
    return $this->method();
}, false);

return rescue(function () {
    return $this->method();
}, function () {
    return $this->failure();
});

<a name=“method-resolve”></a>

34.8.0.38 resolve() {#collection-method}

The resolve function resolves a given class or interface name to its instance using the service container:

$api = resolve('HelpSpot\API');

<a name=“method-response”></a>

34.8.0.39 response() {#collection-method}

The response function creates a response instance or obtains an instance of the response factory:

return response('Hello World', 200, $headers);

return response()->json(['foo' => 'bar'], 200, $headers);

<a name=“method-retry”></a>

34.8.0.40 retry() {#collection-method}

The retry function attempts to execute the given callback until the given maximum attempt threshold is met. If the callback does not throw an exception, its return value will be returned. If the callback throws an exception, it will automatically be retried. If the maximum attempt count is exceeded, the exception will be thrown:

return retry(5, function () {
    // Attempt 5 times while resting 100ms in between attempts...
}, 100);

<a name=“method-session”></a>

34.8.0.41 session() {#collection-method}

The session function may be used to get or set session values:

$value = session('key');

You may set values by passing an array of key / value pairs to the function:

session(['chairs' => 7, 'instruments' => 3]);

The session store will be returned if no value is passed to the function:

$value = session()->get('key');

session()->put('key', $value);

<a name=“method-tap”></a>

34.8.0.42 tap() {#collection-method}

The tap function accepts two arguments: an arbitrary $value and a Closure. The $value will be passed to the Closure and then be returned by the tap function. The return value of the Closure is irrelevant:

$user = tap(User::first(), function ($user) {
    $user->name = 'taylor';

    $user->save();
});

If no Closure is passed to the tap function, you may call any method on the given $value. The return value of the method you call will always be $value, regardless of the what the method actually returns in its definition. For example, the Eloquent update method typically returns an integer. However, we can force the method to return the model itself by chaining the update method call through the tap function:

$user = tap($user)->update([
    'name' => $name,
    'email' => $email,
]);

<a name=“method-today”></a>

34.8.0.43 today() {#collection-method}

The today function creates a new Illuminate\Support\Carbon instance for the current date:

$today = today();

<a name=“method-throw-if”></a>

34.8.0.44 throw_if() {#collection-method}

The throw_if function throws the given exception if a given boolean expression evaluates to true:

throw_if(! Auth::user()->isAdmin(), AuthorizationException::class);

throw_if(
    ! Auth::user()->isAdmin(),
    AuthorizationException::class,
    'You are not allowed to access this page'
);

<a name=“method-throw-unless”></a>

34.8.0.45 throw_unless() {#collection-method}

The throw_unless function throws the given exception if a given boolean expression evaluates to false:

throw_unless(Auth::user()->isAdmin(), AuthorizationException::class);

throw_unless(
    Auth::user()->isAdmin(),
    AuthorizationException::class,
    'You are not allowed to access this page'
);

<a name=“method-trait-uses-recursive”></a>

34.8.0.46 trait_uses_recursive() {#collection-method}

The trait_uses_recursive function returns all traits used by a trait:

$traits = trait_uses_recursive(\Illuminate\Notifications\Notifiable::class);

<a name=“method-transform”></a>

34.8.0.47 transform() {#collection-method}

The transform function executes a Closure on a given value if the value is not blank and returns the result of the Closure:

$callback = function ($value) {
    return $value * 2;
};

$result = transform(5, $callback);

// 10

A default value or Closure may also be passed as the third parameter to the method. This value will be returned if the given value is blank:

$result = transform(null, $callback, 'The value is blank');

// The value is blank

<a name=“method-validator”></a>

34.8.0.48 validator() {#collection-method}

The validator function creates a new validator instance with the given arguments. You may use it instead of the Validator facade for convenience:

$validator = validator($data, $rules, $messages);

<a name=“method-value”></a>

34.8.0.49 value() {#collection-method}

The value function returns the value it is given. However, if you pass a Closure to the function, the Closure will be executed then its result will be returned:

$result = value(true);

// true

$result = value(function () {
    return false;
});

// false

<a name=“method-view”></a>

34.8.0.50 view() {#collection-method}

The view function retrieves a view instance:

return view('auth.login');

<a name=“method-with”></a>

34.8.0.51 with() {#collection-method}

The with function returns the value it is given. If a Closure is passed as the second argument to the function, the Closure will be executed and its result will be returned:

$callback = function ($value) {
    return (is_numeric($value)) ? $value * 2 : 0;
};

$result = with(5, $callback);

// 10

$result = with(null, $callback);

// 0

$result = with(5, null);

// 5

35 Laravel Homestead

<a name=“introduction”></a>

35.1 Introduction

Laravel strives to make the entire PHP development experience delightful, including your local development environment. Vagrant provides a simple, elegant way to manage and provision Virtual Machines.

Laravel Homestead is an official, pre-packaged Vagrant box that provides you a wonderful development environment without requiring you to install PHP, a web server, and any other server software on your local machine. No more worrying about messing up your operating system! Vagrant boxes are completely disposable. If something goes wrong, you can destroy and re-create the box in minutes!

Homestead runs on any Windows, Mac, or Linux system, and includes the Nginx web server, PHP 7.2, PHP 7.1, PHP 7.0, PHP 5.6, MySQL, PostgreSQL, Redis, Memcached, Node, and all of the other goodies you need to develop amazing Laravel applications.

{note} If you are using Windows, you may need to enable hardware virtualization (VT-x). It can usually be enabled via your BIOS. If you are using Hyper-V on a UEFI system you may additionally need to disable Hyper-V in order to access VT-x.

<a name=“included-software”></a>

35.1.1 Included Software

<div class=“content-list” markdown=“1”>

  • Ubuntu 16.04
  • Git
  • PHP 7.2
  • PHP 7.1
  • PHP 7.0
  • PHP 5.6
  • Nginx
  • Apache (Optional)
  • MySQL
  • MariaDB (Optional)
  • Sqlite3
  • PostgreSQL
  • Composer
  • Node (With Yarn, Bower, Grunt, and Gulp)
  • Redis
  • Memcached
  • Beanstalkd
  • Mailhog
  • Elasticsearch (Optional)
  • ngrok
    </div>

<a name=“installation-and-setup”></a>

35.2 Installation & Setup

<a name=“first-steps”></a>

35.2.1 First Steps

Before launching your Homestead environment, you must install VirtualBox 5.2, VMWare, Parallels or Hyper-V as well as Vagrant. All of these software packages provide easy-to-use visual installers for all popular operating systems.

To use the VMware provider, you will need to purchase both VMware Fusion / Workstation and the VMware Vagrant plug-in. Though it is not free, VMware can provide faster shared folder performance out of the box.

To use the Parallels provider, you will need to install Parallels Vagrant plug-in. It is free of charge.

Because of Vagrant limitations, The Hyper-V provider ignores all networking settings.

35.2.1.1 Installing The Homestead Vagrant Box

Once VirtualBox / VMware and Vagrant have been installed, you should add the laravel/homestead box to your Vagrant installation using the following command in your terminal. It will take a few minutes to download the box, depending on your Internet connection speed:

vagrant box add laravel/homestead

If this command fails, make sure your Vagrant installation is up to date.

35.2.1.2 Installing Homestead

You may install Homestead by cloning the repository. Consider cloning the repository into a Homestead folder within your “home” directory, as the Homestead box will serve as the host to all of your Laravel projects:

git clone https://github.com/laravel/homestead.git ~/Homestead

You should check out a tagged version of Homestead since the master branch may not always be stable. You can find the latest stable version on the GitHub Release Page:

cd ~/Homestead

// Clone the desired release...
git checkout v7.1.2

Once you have cloned the Homestead repository, run the bash init.sh command from the Homestead directory to create the Homestead.yaml configuration file. The Homestead.yaml file will be placed in the Homestead directory:

// Mac / Linux...
bash init.sh

// Windows...
init.bat

<a name=“configuring-homestead”></a>

35.2.2 Configuring Homestead

35.2.2.1 Setting Your Provider

The provider key in your Homestead.yaml file indicates which Vagrant provider should be used: virtualbox, vmware_fusion, vmware_workstation, parallels or hyperv. You may set this to the provider you prefer:

provider: virtualbox

35.2.2.2 Configuring Shared Folders

The folders property of the Homestead.yaml file lists all of the folders you wish to share with your Homestead environment. As files within these folders are changed, they will be kept in sync between your local machine and the Homestead environment. You may configure as many shared folders as necessary:

folders:
    - map: ~/code
      to: /home/vagrant/code

If you are only creating a few sites, this generic mapping will work just fine. However, as the number of sites continue to grow, you may begin to experience performance problems. This problem can be painfully apparent on low-end machines or projects that contain a very large number of files. If you are experiencing this issue, try mapping every project to its own Vagrant folder:

folders:
    - map: ~/code/project1
      to: /home/vagrant/code/project1

    - map: ~/code/project2
      to: /home/vagrant/code/project2

To enable NFS, you only need to add a simple flag to your synced folder configuration:

folders:
    - map: ~/code
      to: /home/vagrant/code
      type: "nfs"

{note} When using NFS, you should consider installing the vagrant-bindfs plug-in. This plug-in will maintain the correct user / group permissions for files and directories within the Homestead box.

You may also pass any options supported by Vagrant’s Synced Folders by listing them under the options key:

folders:
    - map: ~/code
      to: /home/vagrant/code
      type: "rsync"
      options:
          rsync__args: ["--verbose", "--archive", "--delete", "-zz"]
          rsync__exclude: ["node_modules"]

35.2.2.3 Configuring Nginx Sites

Not familiar with Nginx? No problem. The sites property allows you to easily map a “domain” to a folder on your Homestead environment. A sample site configuration is included in the Homestead.yaml file. Again, you may add as many sites to your Homestead environment as necessary. Homestead can serve as a convenient, virtualized environment for every Laravel project you are working on:

sites:
    - map: homestead.test
      to: /home/vagrant/code/Laravel/public

If you change the sites property after provisioning the Homestead box, you should re-run vagrant reload --provision to update the Nginx configuration on the virtual machine.

35.2.2.4 The Hosts File

You must add the “domains” for your Nginx sites to the hosts file on your machine. The hosts file will redirect requests for your Homestead sites into your Homestead machine. On Mac and Linux, this file is located at /etc/hosts. On Windows, it is located at C:\Windows\System32\drivers\etc\hosts. The lines you add to this file will look like the following:

192.168.10.10  homestead.test

Make sure the IP address listed is the one set in your Homestead.yaml file. Once you have added the domain to your hosts file and launched the Vagrant box you will be able to access the site via your web browser:

http://homestead.test

<a name=“launching-the-vagrant-box”></a>

35.2.3 Launching The Vagrant Box

Once you have edited the Homestead.yaml to your liking, run the vagrant up command from your Homestead directory. Vagrant will boot the virtual machine and automatically configure your shared folders and Nginx sites.

To destroy the machine, you may use the vagrant destroy --force command.

<a name=“per-project-installation”></a>

35.2.4 Per Project Installation

Instead of installing Homestead globally and sharing the same Homestead box across all of your projects, you may instead configure a Homestead instance for each project you manage. Installing Homestead per project may be beneficial if you wish to ship a Vagrantfile with your project, allowing others working on the project to vagrant up.

To install Homestead directly into your project, require it using Composer:

composer require laravel/homestead --dev

Once Homestead has been installed, use the make command to generate the Vagrantfile and Homestead.yaml file in your project root. The make command will automatically configure the sites and folders directives in the Homestead.yaml file.

Mac / Linux:

php vendor/bin/homestead make

Windows:

vendor\\bin\\homestead make

Next, run the vagrant up command in your terminal and access your project at http://homestead.test in your browser. Remember, you will still need to add an /etc/hosts file entry for homestead.test or the domain of your choice.

<a name=“installing-mariadb”></a>

35.2.5 Installing MariaDB

If you prefer to use MariaDB instead of MySQL, you may add the mariadb option to your Homestead.yaml file. This option will remove MySQL and install MariaDB. MariaDB serves as a drop-in replacement for MySQL so you should still use the mysql database driver in your application’s database configuration:

box: laravel/homestead
ip: "192.168.10.10"
memory: 2048
cpus: 4
provider: virtualbox
mariadb: true

<a name=“installing-elasticsearch”></a>

35.2.6 Installing Elasticsearch

To install Elasticsearch, add the elasticsearch option to your Homestead.yaml file and specify a supported version. The default installation will create a cluster named ‘homestead’. You should never give Elasticsearch more than half of the operating system’s memory, so make sure your Homestead machine has at least twice the Elasticsearch allocation:

box: laravel/homestead
ip: "192.168.10.10"
memory: 4096
cpus: 4
provider: virtualbox
elasticsearch: 6

{tip} Check out the Elasticsearch documentation to learn how to customize your configuration.

<a name=“aliases”></a>

35.2.7 Aliases

You may add Bash aliases to your Homestead machine by modifying the aliases file within your Homestead directory:

alias c='clear'
alias ..='cd ..'

After you have updated the aliases file, you should re-provision the Homestead machine using the vagrant reload --provision command. This will ensure that your new aliases are available on the machine.

<a name=“daily-usage”></a>

35.3 Daily Usage

<a name=“accessing-homestead-globally”></a>

35.3.1 Accessing Homestead Globally

Sometimes you may want to vagrant up your Homestead machine from anywhere on your filesystem. You can do this on Mac / Linux systems by adding a Bash function to your Bash profile. On Windows, you may accomplish this by adding a “batch” file to your PATH. These scripts will allow you to run any Vagrant command from anywhere on your system and will automatically point that command to your Homestead installation:

35.3.1.1 Mac / Linux

function homestead() {
    ( cd ~/Homestead && vagrant $* )
}

Make sure to tweak the ~/Homestead path in the function to the location of your actual Homestead installation. Once the function is installed, you may run commands like homestead up or homestead ssh from anywhere on your system.

35.3.1.2 Windows

Create a homestead.bat batch file anywhere on your machine with the following contents:

@echo off

set cwd=%cd%
set homesteadVagrant=C:\Homestead

cd /d %homesteadVagrant% && vagrant %*
cd /d %cwd%

set cwd=
set homesteadVagrant=

Make sure to tweak the example C:\Homestead path in the script to the actual location of your Homestead installation. After creating the file, add the file location to your PATH. You may then run commands like homestead up or homestead ssh from anywhere on your system.

<a name=“connecting-via-ssh”></a>

35.3.2 Connecting Via SSH

You can SSH into your virtual machine by issuing the vagrant ssh terminal command from your Homestead directory.

But, since you will probably need to SSH into your Homestead machine frequently, consider adding the “function” described above to your host machine to quickly SSH into the Homestead box.

<a name=“connecting-to-databases”></a>

35.3.3 Connecting To Databases

A homestead database is configured for both MySQL and PostgreSQL out of the box. For even more convenience, Laravel’s .env file configures the framework to use this database out of the box.

To connect to your MySQL or PostgreSQL database from your host machine’s database client, you should connect to 127.0.0.1 and port 33060 (MySQL) or 54320 (PostgreSQL). The username and password for both databases is homestead / secret.

{note} You should only use these non-standard ports when connecting to the databases from your host machine. You will use the default 3306 and 5432 ports in your Laravel database configuration file since Laravel is running within the virtual machine.

<a name=“adding-additional-sites”></a>

35.3.4 Adding Additional Sites

Once your Homestead environment is provisioned and running, you may want to add additional Nginx sites for your Laravel applications. You can run as many Laravel installations as you wish on a single Homestead environment. To add an additional site, add the site to your Homestead.yaml file:

sites:
    - map: homestead.test
      to: /home/vagrant/code/Laravel/public
    - map: another.test
      to: /home/vagrant/code/another/public

If Vagrant is not automatically managing your “hosts” file, you may need to add the new site to that file as well:

192.168.10.10  homestead.test
192.168.10.10  another.test

Once the site has been added, run the vagrant reload --provision command from your Homestead directory.

<a name=“site-types”></a>

35.3.4.1 Site Types

Homestead supports several types of sites which allow you to easily run projects that are not based on Laravel. For example, we may easily add a Symfony application to Homestead using the symfony2 site type:

sites:
    - map: symfony2.test
      to: /home/vagrant/code/Symfony/web
      type: "symfony2"

The available site types are: apache, laravel (the default), proxy, silverstripe, statamic, symfony2, and symfony4.

<a name=“site-parameters”></a>

35.3.4.2 Site Parameters

You may add additional Nginx fastcgi_param values to your site via the params site directive. For example, we’ll add a FOO parameter with a value of BAR:

sites:
    - map: homestead.test
      to: /home/vagrant/code/Laravel/public
      params:
          - key: FOO
            value: BAR

<a name=“environment-variables”></a>

35.3.5 Environment Variables

You can set global environment variables by adding them to your Homestead.yaml file:

variables:
    - key: APP_ENV
      value: local
    - key: FOO
      value: bar

After updating the Homestead.yaml, be sure to re-provision the machine by running vagrant reload --provision. This will update the PHP-FPM configuration for all of the installed PHP versions and also update the environment for the vagrant user.

<a name=“configuring-cron-schedules”></a>

35.3.6 Configuring Cron Schedules

Laravel provides a convenient way to schedule Cron jobs by scheduling a single schedule:run Artisan command to be run every minute. The schedule:run command will examine the job schedule defined in your App\Console\Kernel class to determine which jobs should be run.

If you would like the schedule:run command to be run for a Homestead site, you may set the schedule option to true when defining the site:

sites:
    - map: homestead.test
      to: /home/vagrant/code/Laravel/public
      schedule: true

The Cron job for the site will be defined in the /etc/cron.d folder of the virtual machine.

<a name=“configuring-mailhog”></a>

35.3.7 Configuring Mailhog

Mailhog allows you to easily catch your outgoing email and examine it without actually sending the mail to its recipients. To get started, update your .env file to use the following mail settings:

MAIL_DRIVER=smtp
MAIL_HOST=localhost
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

<a name=“ports”></a>

35.3.8 Ports

By default, the following ports are forwarded to your Homestead environment:

  • **SSH:** 2222 → Forwards To 22
  • ngrok UI: 4040 → Forwards To 4040
  • **HTTP:** 8000 → Forwards To 80
  • **HTTPS:** 44300 → Forwards To 443
  • MySQL: 33060 → Forwards To 3306
  • PostgreSQL: 54320 → Forwards To 5432
  • Mailhog: 8025 → Forwards To 8025

35.3.8.1 Forwarding Additional Ports

If you wish, you may forward additional ports to the Vagrant box, as well as specify their protocol:

ports:
    - send: 50000
      to: 5000
    - send: 7777
      to: 777
      protocol: udp

<a name=“sharing-your-environment”></a>

35.3.9 Sharing Your Environment

Sometimes you may wish to share what you’re currently working on with coworkers or a client. Vagrant has a built-in way to support this via vagrant share; however, this will not work if you have multiple sites configured in your Homestead.yaml file.

To solve this problem, Homestead includes its own share command. To get started, SSH into your Homestead machine via vagrant ssh and run share homestead.test. This will share the homestead.test site from your Homestead.yaml configuration file. Of course, you may substitute any of your other configured sites for homestead.test:

share homestead.test

After running the command, you will see an Ngrok screen appear which contains the activity log and the publicly accessible URLs for the shared site. If you would like to specify a custom region, subdomain, or other Ngrok runtime option, you may add them to your share command:

share homestead.test -region=eu -subdomain=laravel

{note} Remember, Vagrant is inherently insecure and you are exposing your virtual machine to the Internet when running the share command.

<a name=“multiple-php-versions”></a>

35.3.10 Multiple PHP Versions

{note} This feature is only compatible with Nginx.

Homestead 6 introduced support for multiple versions of PHP on the same virtual machine. You may specify which version of PHP to use for a given site within your Homestead.yaml file. The available PHP versions are: “5.6”, “7.0”, “7.1” and “7.2” (the default):

sites:
    - map: homestead.test
      to: /home/vagrant/code/Laravel/public
      php: "5.6"

In addition, you may use any of the supported PHP versions via the CLI:

php5.6 artisan list
php7.0 artisan list
php7.1 artisan list
php7.2 artisan list

<a name=“web-servers”></a>

35.3.11 Web Servers

Homestead uses the Nginx web server by default. However, it can install Apache if apache is specified as a site type. While both web servers can be installed at the same time, they cannot both be running at the same time. The flip shell command is available to ease the process of switching between web servers. The flip command automatically determines which web server is running, shuts it off, and then starts the other server. To use this command, SSH into your Homestead machine and run the command in your terminal:

flip

<a name=“network-interfaces”></a>

35.4 Network Interfaces

The networks property of the Homestead.yaml configures network interfaces for your Homestead environment. You may configure as many interfaces as necessary:

networks:
    - type: "private_network"
      ip: "192.168.10.20"

To enable a bridged interface, configure a bridge setting and change the network type to public_network:

networks:
    - type: "public_network"
      ip: "192.168.10.20"
      bridge: "en1: Wi-Fi (AirPort)"

To enable DHCP, just remove the ip option from your configuration:

networks:
    - type: "public_network"
      bridge: "en1: Wi-Fi (AirPort)"

<a name=“updating-homestead”></a>

35.5 Updating Homestead

You can update Homestead in two simple steps. First, you should update the Vagrant box using the vagrant box update command:

vagrant box update

Next, you need to update the Homestead source code. If you cloned the repository you can git pull origin master at the location you originally cloned the repository.

If you have installed Homestead via your project’s composer.json file, you should ensure your composer.json file contains "laravel/homestead": "^7" and update your dependencies:

composer update

<a name=“provider-specific-settings”></a>

35.6 Provider Specific Settings

<a name=“provider-specific-virtualbox”></a>

35.6.1 VirtualBox

35.6.1.1 natdnshostresolver

By default, Homestead configures the natdnshostresolver setting to on. This allows Homestead to use your host operating system’s DNS settings. If you would like to override this behavior, add the following lines to your Homestead.yaml file:

provider: virtualbox
natdnshostresolver: off

If symbolic links are not working properly on your Windows machine, you may need to add the following block to your Vagrantfile:

config.vm.provider "virtualbox" do |v|
    v.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"]
end

36 Laravel Horizon

<a name=“introduction”></a>

36.1 Introduction

Horizon provides a beautiful dashboard and code-driven configuration for your Laravel powered Redis queues. Horizon allows you to easily monitor key metrics of your queue system such as job throughput, runtime, and job failures.

All of your worker configuration is stored in a single, simple configuration file, allowing your configuration to stay in source control where your entire team can collaborate.

<a name=“installation”></a>

36.2 Installation

{note} Due to its usage of async process signals, Horizon requires PHP 7.1+.

You may use Composer to install Horizon into your Laravel project:

composer require laravel/horizon

After installing Horizon, publish its assets using the vendor:publish Artisan command:

php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider"

<a name=“configuration”></a>

36.2.1 Configuration

After publishing Horizon’s assets, its primary configuration file will be located at config/horizon.php. This configuration file allows you to configure your worker options and each configuration option includes a description of its purpose, so be sure to thoroughly explore this file.

36.2.1.1 Balance Options

Horizon allows you to choose from three balancing strategies: simple, auto, and false. The simple strategy, which is the default, splits incoming jobs evenly between processes:

'balance' => 'simple',

The auto strategy adjusts the number of worker processes per queue based on the current workload of the queue. For example, if your notifications queue has 1,000 waiting jobs while your render queue is empty, Horizon will allocate more workers to your notifications queue until it is empty. When the balance option is set to false, the default Laravel behavior will be used, which processes queues in the order they are listed in your configuration.

<a name=“dashboard-authentication”></a>

36.2.2 Dashboard Authentication

Horizon exposes a dashboard at /horizon. By default, you will only be able to access this dashboard in the local environment. To define a more specific access policy for the dashboard, you should use the Horizon::auth method. The auth method accepts a callback which should return true or false, indicating whether the user should have access to the Horizon dashboard:

Horizon::auth(function ($request) {
    // return true / false;
});

<a name=“running-horizon”></a>

36.3 Running Horizon

Once you have configured your workers in the config/horizon.php configuration file, you may start Horizon using the horizon Artisan command. This single command will start all of your configured workers:

php artisan horizon

You may pause the Horizon process and instruct it to continue processing jobs using the horizon:pause and horizon:continue Artisan commands:

php artisan horizon:pause

php artisan horizon:continue

You may gracefully terminate the master Horizon process on your machine using the horizon:terminate Artisan command. Any jobs that Horizon is currently processing will be completed and then Horizon will exit:

php artisan horizon:terminate

<a name=“deploying-horizon”></a>

36.3.1 Deploying Horizon

If you are deploying Horizon to a live server, you should configure a process monitor to monitor the php artisan horizon command and restart it if it quits unexpectedly. When deploying fresh code to your server, you will need to instruct the master Horizon process to terminate so it can be restarted by your process monitor and receive your code changes.

You may gracefully terminate the master Horizon process on your machine using the horizon:terminate Artisan command. Any jobs that Horizon is currently processing will be completed and then Horizon will exit:

php artisan horizon:terminate

36.3.1.1 Supervisor Configuration

If you are using the Supervisor process monitor to manage your horizon process, the following configuration file should suffice:

[program:horizon]
process_name=%(program_name)s
command=php /home/forge/app.com/artisan horizon
autostart=true
autorestart=true
user=forge
redirect_stderr=true
stdout_logfile=/home/forge/app.com/horizon.log

{tip} If you are uncomfortable managing your own servers, consider using Laravel Forge. Forge provisions PHP 7+ servers with everything you need to run modern, robust Laravel applications with Horizon.

<a name=“tags”></a>

36.4 Tags

Horizon allows you to assign “tags” to jobs, including mailables, event broadcasts, notifications, and queued event listeners. In fact, Horizon will intelligently and automatically tag most jobs depending on the Eloquent models that are attached to the job. For example, take a look at the following job:

<?php

namespace App\Jobs;

use App\Video;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class RenderVideo implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * The video instance.
     *
     * @var \App\Video
     */
    public $video;

    /**
     * Create a new job instance.
     *
     * @param  \App\Video  $video
     * @return void
     */
    public function __construct(Video $video)
    {
        $this->video = $video;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //
    }
}

If this job is queued with an App\Video instance that has an id of 1, it will automatically receive the tag App\Video:1. This is because Horizon will examine the job’s properties for any Eloquent models. If Eloquent models are found, Horizon will intelligently tag the job using the model’s class name and primary key:

$video = App\Video::find(1);

App\Jobs\RenderVideo::dispatch($video);

36.4.0.1 Manually Tagging

If you would like to manually define the tags for one of your queueable objects, you may define a tags method on the class:

class RenderVideo implements ShouldQueue
{
    /**
     * Get the tags that should be assigned to the job.
     *
     * @return array
     */
    public function tags()
    {
        return ['render', 'video:'.$this->video->id];
    }
}

<a name=“notifications”></a>

36.5 Notifications

Note: Before using notifications, you should add the guzzlehttp/guzzle Composer package to your project. When configuring Horizon to send SMS notifications, you should also review the prerequisites for the Nexmo notification driver.

If you would like to be notified when one of your queues has a long wait time, you may use the Horizon::routeMailNotificationsTo, Horizon::routeSlackNotificationsTo, and Horizon::routeSmsNotificationsTo methods. You may call these methods from your application’s AppServiceProvider:

Horizon::routeMailNotificationsTo('example@example.com');
Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
Horizon::routeSmsNotificationsTo('15556667777');

36.5.0.1 Configuring Notification Wait Time Thresholds

You may configure how many seconds are considered a “long wait” within your config/horizon.php configuration file. The waits configuration option within this file allows you to control the long wait threshold for each connection / queue combination:

'waits' => [
    'redis:default' => 60,
],

<a name=“metrics”></a>

36.6 Metrics

Horizon includes a metrics dashboard which provides information on your job and queue wait times and throughput. In order to populate this dashboard, you should configure Horizon’s snapshot Artisan command to run every five minutes via your application’s scheduler:

/**
 * Define the application's command schedule.
 *
 * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
 * @return void
 */
protected function schedule(Schedule $schedule)
{
    $schedule->command('horizon:snapshot')->everyFiveMinutes();
}

37 HTTP Tests

<a name=“introduction”></a>

37.1 Introduction

Laravel provides a very fluent API for making HTTP requests to your application and examining the output. For example, take a look at the test defined below:

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;

class ExampleTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

The get method makes a GET request into the application, while the assertStatus method asserts that the returned response should have the given HTTP status code. In addition to this simple assertion, Laravel also contains a variety of assertions for inspecting the response headers, content, JSON structure, and more.

<a name=“customizing-request-headers”></a>

37.1.1 Customizing Request Headers

You may use the withHeaders method to customize the request’s headers before it is sent to the application. This allows you to add any custom headers you would like to the request:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->withHeaders([
            'X-Header' => 'Value',
        ])->json('POST', '/user', ['name' => 'Sally']);

        $response
            ->assertStatus(200)
            ->assertJson([
                'created' => true,
            ]);
    }
}

<a name=“session-and-authentication”></a>

37.2 Session / Authentication

Laravel provides several helpers for working with the session during HTTP testing. First, you may set the session data to a given array using the withSession method. This is useful for loading the session with data before issuing a request to your application:

<?php

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $response = $this->withSession(['foo' => 'bar'])
                         ->get('/');
    }
}

Of course, one common use of the session is for maintaining state for the authenticated user. The actingAs helper method provides a simple way to authenticate a given user as the current user. For example, we may use a model factory to generate and authenticate a user:

<?php

use App\User;

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $user = factory(User::class)->create();

        $response = $this->actingAs($user)
                         ->withSession(['foo' => 'bar'])
                         ->get('/');
    }
}

You may also specify which guard should be used to authenticate the given user by passing the guard name as the second argument to the actingAs method:

$this->actingAs($user, 'api')

<a name=“testing-json-apis”></a>

37.3 Testing JSON APIs

Laravel also provides several helpers for testing JSON APIs and their responses. For example, the json, get, post, put, patch, and delete methods may be used to issue requests with various HTTP verbs. You may also easily pass data and headers to these methods. To get started, let’s write a test to make a POST request to /user and assert that the expected data was returned:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->json('POST', '/user', ['name' => 'Sally']);

        $response
            ->assertStatus(200)
            ->assertJson([
                'created' => true,
            ]);
    }
}

{tip} The assertJson method converts the response to an array and utilizes PHPUnit::assertArraySubset to verify that the given array exists within the JSON response returned by the application. So, if there are other properties in the JSON response, this test will still pass as long as the given fragment is present.

<a name=“verifying-exact-match”></a>

37.3.1 Verifying An Exact JSON Match

If you would like to verify that the given array is an exact match for the JSON returned by the application, you should use the assertExactJson method:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->json('POST', '/user', ['name' => 'Sally']);

        $response
            ->assertStatus(200)
            ->assertExactJson([
                'created' => true,
            ]);
    }
}

<a name=“testing-file-uploads”></a>

37.4 Testing File Uploads

The Illuminate\Http\UploadedFile class provides a fake method which may be used to generate dummy files or images for testing. This, combined with the Storage facade’s fake method greatly simplifies the testing of file uploads. For example, you may combine these two features to easily test an avatar upload form:

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;

class ExampleTest extends TestCase
{
    public function testAvatarUpload()
    {
        Storage::fake('avatars');

        $response = $this->json('POST', '/avatar', [
            'avatar' => UploadedFile::fake()->image('avatar.jpg')
        ]);

        // Assert the file was stored...
        Storage::disk('avatars')->assertExists('avatar.jpg');

        // Assert a file does not exist...
        Storage::disk('avatars')->assertMissing('missing.jpg');
    }
}

37.4.0.1 Fake File Customization

When creating files using the fake method, you may specify the width, height, and size of the image in order to better test your validation rules:

UploadedFile::fake()->image('avatar.jpg', $width, $height)->size(100);

In addition to creating images, you may create files of any other type using the create method:

UploadedFile::fake()->create('document.pdf', $sizeInKilobytes);

<a name=“available-assertions”></a>

37.5 Available Assertions

<a name=“response-assertions”></a>

37.5.1 Response Assertions

Laravel provides a variety of custom assertion methods for your PHPUnit tests. These assertions may be accessed on the response that is returned from the json, get, post, put, and delete test methods:

<style>
.collection-method-list > p {
column-count: 3; -moz-column-count: 3; -webkit-column-count: 3;
column-gap: 2em; -moz-column-gap: 2em; -webkit-column-gap: 2em;
}

.collection-method-list a {
    display: block;
}

</style>

<div class=“collection-method-list” markdown=“1”>

assertCookie
assertCookieExpired
assertCookieMissing
assertDontSee
assertDontSeeText
assertExactJson
assertHeader
assertHeaderMissing
assertJson
assertJsonFragment
assertJsonMissing
assertJsonMissingExact
assertJsonStructure
assertJsonValidationErrors
assertPlainCookie
assertRedirect
assertSee
assertSeeText
assertSessionHas
assertSessionHasAll
assertSessionHasErrors
assertSessionHasErrorsIn
assertSessionMissing
assertStatus
assertSuccessful
assertViewHas
assertViewHasAll
assertViewIs
assertViewMissing

</div>

<a name=“assert-cookie”></a>

37.5.1.1 assertCookie

Assert that the response contains the given cookie:

$response->assertCookie($cookieName, $value = null);

<a name=“assert-cookie-expired”></a>

37.5.1.2 assertCookieExpired

Assert that the response contains the given cookie and it is expired:

$response->assertCookieExpired($cookieName);

<a name=“assert-cookie-missing”></a>

37.5.1.3 assertCookieMissing

Assert that the response does not contains the given cookie:

$response->assertCookieMissing($cookieName);

<a name=“assert-dont-see”></a>

37.5.1.4 assertDontSee

Assert that the given string is not contained within the response:

$response->assertDontSee($value);

<a name=“assert-dont-see-text”></a>

37.5.1.5 assertDontSeeText

Assert that the given string is not contained within the response text:

$response->assertDontSeeText($value);

<a name=“assert-exact-json”></a>

37.5.1.6 assertExactJson

Assert that the response contains an exact match of the given JSON data:

$response->assertExactJson(array $data);

<a name=“assert-header”></a>

37.5.1.7 assertHeader

Assert that the given header is present on the response:

$response->assertHeader($headerName, $value = null);

<a name=“assert-header-missing”></a>

37.5.1.8 assertHeaderMissing

Assert that the given header is not present on the response:

$response->assertHeaderMissing($headerName);

<a name=“assert-json”></a>

37.5.1.9 assertJson

Assert that the response contains the given JSON data:

$response->assertJson(array $data);

<a name=“assert-json-fragment”></a>

37.5.1.10 assertJsonFragment

Assert that the response contains the given JSON fragment:

$response->assertJsonFragment(array $data);

<a name=“assert-json-missing”></a>

37.5.1.11 assertJsonMissing

Assert that the response does not contain the given JSON fragment:

$response->assertJsonMissing(array $data);

<a name=“assert-json-missing-exact”></a>

37.5.1.12 assertJsonMissingExact

Assert that the response does not contain the exact JSON fragment:

$response->assertJsonMissingExact(array $data);

<a name=“assert-json-structure”></a>

37.5.1.13 assertJsonStructure

Assert that the response has a given JSON structure:

$response->assertJsonStructure(array $structure);

<a name=“assert-json-validation-errors”></a>

37.5.1.14 assertJsonValidationErrors

Assert that the response has the given JSON validation errors for the given keys:

$response->assertJsonValidationErrors($keys);

<a name=“assert-plain-cookie”></a>

37.5.1.15 assertPlainCookie

Assert that the response contains the given cookie (unencrypted):

$response->assertPlainCookie($cookieName, $value = null);

<a name=“assert-redirect”></a>

37.5.1.16 assertRedirect

Assert that the response is a redirect to a given URI:

$response->assertRedirect($uri);

<a name=“assert-see”></a>

37.5.1.17 assertSee

Assert that the given string is contained within the response:

$response->assertSee($value);

<a name=“assert-see-text”></a>

37.5.1.18 assertSeeText

Assert that the given string is contained within the response text:

$response->assertSeeText($value);

<a name=“assert-session-has”></a>

37.5.1.19 assertSessionHas

Assert that the session contains the given piece of data:

$response->assertSessionHas($key, $value = null);

<a name=“assert-session-has-all”></a>

37.5.1.20 assertSessionHasAll

Assert that the session has a given list of values:

$response->assertSessionHasAll($key, $value = null);

<a name=“assert-session-has-errors”></a>

37.5.1.21 assertSessionHasErrors

Assert that the session contains an error for the given field:

$response->assertSessionHasErrors(array $keys, $format = null, $errorBag = 'default');

<a name=“assert-session-has-errors-in”></a>

37.5.1.22 assertSessionHasErrorsIn

Assert that the session has the given errors:

$response->assertSessionHasErrorsIn($errorBag, $keys = [], $format = null);

<a name=“assert-session-missing”></a>

37.5.1.23 assertSessionMissing

Assert that the session does not contain the given key:

$response->assertSessionMissing($key);

<a name=“assert-status”></a>

37.5.1.24 assertStatus

Assert that the response has a given code:

$response->assertStatus($code);

<a name=“assert-successful”></a>

37.5.1.25 assertSuccessful

Assert that the response has a successful status code:

$response->assertSuccessful();

<a name=“assert-view-has”></a>

37.5.1.26 assertViewHas

Assert that the response view was given a piece of data:

$response->assertViewHas($key, $value = null);

<a name=“assert-view-has-all”></a>

37.5.1.27 assertViewHasAll

Assert that the response view has a given list of data:

$response->assertViewHasAll(array $data);

<a name=“assert-view-is”></a>

37.5.1.28 assertViewIs

Assert that the given view was returned by the route:

$response->assertViewIs($value);

<a name=“assert-view-missing”></a>

37.5.1.29 assertViewMissing

Assert that the response view is missing a piece of bound data:

$response->assertViewMissing($key);

<a name=“authentication-assertions”></a>

37.5.2 Authentication Assertions

Laravel also provides a variety of authentication related assertions for your PHPUnit tests:

Method Description
$this->assertAuthenticated($guard = null); Assert that the user is authenticated.
$this->assertGuest($guard = null); Assert that the user is not authenticated.
$this->assertAuthenticatedAs($user, $guard = null); Assert that the given user is authenticated.
$this->assertCredentials(array $credentials, $guard = null); Assert that the given credentials are valid.
$this->assertInvalidCredentials(array $credentials, $guard = null); Assert that the given credentials are invalid.

38 Installation

<a name=“installation”></a>

38.1 Installation

{video} Are you a visual learner? Laracasts provides a free, thorough introduction to Laravel for newcomers to the framework. It’s a great place to start your journey.

<a name=“server-requirements”></a>

38.1.1 Server Requirements

The Laravel framework has a few system requirements. Of course, all of these requirements are satisfied by the Laravel Homestead virtual machine, so it’s highly recommended that you use Homestead as your local Laravel development environment.

However, if you are not using Homestead, you will need to make sure your server meets the following requirements:

<div class=“content-list” markdown=“1”>

  • PHP >= 7.0.0
  • OpenSSL PHP Extension
  • PDO PHP Extension
  • Mbstring PHP Extension
  • Tokenizer PHP Extension
  • XML PHP Extension
    </div>

<a name=“installing-laravel”></a>

38.1.2 Installing Laravel

Laravel utilizes Composer to manage its dependencies. So, before using Laravel, make sure you have Composer installed on your machine.

38.1.2.1 Via Laravel Installer

First, download the Laravel installer using Composer:

composer global require "laravel/installer"

Make sure to place composer’s system-wide vendor bin directory in your $PATH so the laravel executable can be located by your system. This directory exists in different locations based on your operating system; however, some common locations include:

<div class=“content-list” markdown=“1”>

  • macOS: $HOME/.composer/vendor/bin
  • GNU / Linux Distributions: $HOME/.config/composer/vendor/bin
    </div>

Once installed, the laravel new command will create a fresh Laravel installation in the directory you specify. For instance, laravel new blog will create a directory named blog containing a fresh Laravel installation with all of Laravel’s dependencies already installed:

laravel new blog

38.1.2.2 Via Composer Create-Project

Alternatively, you may also install Laravel by issuing the Composer create-project command in your terminal:

composer create-project --prefer-dist laravel/laravel blog "5.5.*"

38.1.2.3 Local Development Server

If you have PHP installed locally and you would like to use PHP’s built-in development server to serve your application, you may use the serve Artisan command. This command will start a development server at http://localhost:8000:

php artisan serve

Of course, more robust local development options are available via Homestead and Valet.

<a name=“configuration”></a>

38.1.3 Configuration

38.1.3.1 Public Directory

After installing Laravel, you should configure your web server’s document / web root to be the public directory. The index.php in this directory serves as the front controller for all HTTP requests entering your application.

38.1.3.2 Configuration Files

All of the configuration files for the Laravel framework are stored in the config directory. Each option is documented, so feel free to look through the files and get familiar with the options available to you.

38.1.3.3 Directory Permissions

After installing Laravel, you may need to configure some permissions. Directories within the storage and the bootstrap/cache directories should be writable by your web server or Laravel will not run. If you are using the Homestead virtual machine, these permissions should already be set.

38.1.3.4 Application Key

The next thing you should do after installing Laravel is set your application key to a random string. If you installed Laravel via Composer or the Laravel installer, this key has already been set for you by the php artisan key:generate command.

Typically, this string should be 32 characters long. The key can be set in the .env environment file. If you have not renamed the .env.example file to .env, you should do that now. If the application key is not set, your user sessions and other encrypted data will not be secure!

38.1.3.5 Additional Configuration

Laravel needs almost no other configuration out of the box. You are free to get started developing! However, you may wish to review the config/app.php file and its documentation. It contains several options such as timezone and locale that you may wish to change according to your application.

You may also want to configure a few additional components of Laravel, such as:

<div class=“content-list” markdown=“1”>

<a name=“web-server-configuration”></a>

38.2 Web Server Configuration

<a name=“pretty-urls”></a>

38.2.1 Pretty URLs

38.2.1.1 Apache

Laravel includes a public/.htaccess file that is used to provide URLs without the index.php front controller in the path. Before serving Laravel with Apache, be sure to enable the mod_rewrite module so the .htaccess file will be honored by the server.

If the .htaccess file that ships with Laravel does not work with your Apache installation, try this alternative:

Options +FollowSymLinks
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

38.2.1.2 Nginx

If you are using Nginx, the following directive in your site configuration will direct all requests to the index.php front controller:

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

Of course, when using Homestead or Valet, pretty URLs will be automatically configured.

The MIT License (MIT)
Copyright © Taylor Otwell

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

39 Request Lifecycle

<a name=“introduction”></a>

39.1 Introduction

When using any tool in the “real world”, you feel more confident if you understand how that tool works. Application development is no different. When you understand how your development tools function, you feel more comfortable and confident using them.

The goal of this document is to give you a good, high-level overview of how the Laravel framework works. By getting to know the overall framework better, everything feels less “magical” and you will be more confident building your applications. If you don’t understand all of the terms right away, don’t lose heart! Just try to get a basic grasp of what is going on, and your knowledge will grow as you explore other sections of the documentation.

<a name=“lifecycle-overview”></a>

39.2 Lifecycle Overview

39.2.1 First Things

The entry point for all requests to a Laravel application is the public/index.php file. All requests are directed to this file by your web server (Apache / Nginx) configuration. The index.php file doesn’t contain much code. Rather, it is a starting point for loading the rest of the framework.

The index.php file loads the Composer generated autoloader definition, and then retrieves an instance of the Laravel application from bootstrap/app.php script. The first action taken by Laravel itself is to create an instance of the application / service container.

39.2.2 HTTP / Console Kernels

Next, the incoming request is sent to either the HTTP kernel or the console kernel, depending on the type of request that is entering the application. These two kernels serve as the central location that all requests flow through. For now, let’s just focus on the HTTP kernel, which is located in app/Http/Kernel.php.

The HTTP kernel extends the Illuminate\Foundation\Http\Kernel class, which defines an array of bootstrappers that will be run before the request is executed. These bootstrappers configure error handling, configure logging, detect the application environment, and perform other tasks that need to be done before the request is actually handled.

The HTTP kernel also defines a list of HTTP middleware that all requests must pass through before being handled by the application. These middleware handle reading and writing the HTTP session, determining if the application is in maintenance mode, verifying the CSRF token, and more.

The method signature for the HTTP kernel’s handle method is quite simple: receive a Request and return a Response. Think of the Kernel as being a big black box that represents your entire application. Feed it HTTP requests and it will return HTTP responses.

39.2.2.1 Service Providers

One of the most important Kernel bootstrapping actions is loading the service providers for your application. All of the service providers for the application are configured in the config/app.php configuration file’s providers array. First, the register method will be called on all providers, then, once all providers have been registered, the boot method will be called.

Service providers are responsible for bootstrapping all of the framework’s various components, such as the database, queue, validation, and routing components. Since they bootstrap and configure every feature offered by the framework, service providers are the most important aspect of the entire Laravel bootstrap process.

39.2.2.2 Dispatch Request

Once the application has been bootstrapped and all service providers have been registered, the Request will be handed off to the router for dispatching. The router will dispatch the request to a route or controller, as well as run any route specific middleware.

<a name=“focus-on-service-providers”></a>

39.3 Focus On Service Providers

Service providers are truly the key to bootstrapping a Laravel application. The application instance is created, the service providers are registered, and the request is handed to the bootstrapped application. It’s really that simple!

Having a firm grasp of how a Laravel application is built and bootstrapped via service providers is very valuable. Of course, your application’s default service providers are stored in the app/Providers directory.

By default, the AppServiceProvider is fairly empty. This provider is a great place to add your application’s own bootstrapping and service container bindings. Of course, for large applications, you may wish to create several service providers, each with a more granular type of bootstrapping.

40 Localization

<a name=“introduction”></a>

40.1 Introduction

Laravel’s localization features provide a convenient way to retrieve strings in various languages, allowing you to easily support multiple languages within your application. Language strings are stored in files within the resources/lang directory. Within this directory there should be a subdirectory for each language supported by the application:

/resources
    /lang
        /en
            messages.php
        /es
            messages.php

All language files return an array of keyed strings. For example:

<?php

return [
    'welcome' => 'Welcome to our application'
];

40.1.1 Configuring The Locale

The default language for your application is stored in the config/app.php configuration file. Of course, you may modify this value to suit the needs of your application. You may also change the active language at runtime using the setLocale method on the App facade:

Route::get('welcome/{locale}', function ($locale) {
    App::setLocale($locale);

    //
});

You may configure a “fallback language”, which will be used when the active language does not contain a given translation string. Like the default language, the fallback language is also configured in the config/app.php configuration file:

'fallback_locale' => 'en',

40.1.1.1 Determining The Current Locale

You may use the getLocale and isLocale methods on the App facade to determine the current locale or check if the locale is a given value:

$locale = App::getLocale();

if (App::isLocale('en')) {
    //
}

<a name=“defining-translation-strings”></a>

40.2 Defining Translation Strings

<a name=“using-short-keys”></a>

40.2.1 Using Short Keys

Typically, translation strings are stored in files within the resources/lang directory. Within this directory there should be a subdirectory for each language supported by the application:

/resources
    /lang
        /en
            messages.php
        /es
            messages.php

All language files return an array of keyed strings. For example:

<?php

// resources/lang/en/messages.php

return [
    'welcome' => 'Welcome to our application'
];

<a name=“using-translation-strings-as-keys”></a>

40.2.2 Using Translation Strings As Keys

For applications with heavy translation requirements, defining every string with a “short key” can become quickly confusing when referencing them in your views. For this reason, Laravel also provides support for defining translation strings using the “default” translation of the string as the key.

Translation files that use translation strings as keys are stored as JSON files in the resources/lang directory. For example, if your application has a Spanish translation, you should create a resources/lang/es.json file:

{
    "I love programming.": "Me encanta programar."
}

<a name=“retrieving-translation-strings”></a>

40.3 Retrieving Translation Strings

You may retrieve lines from language files using the __ helper function. The __ method accepts the file and key of the translation string as its first argument. For example, let’s retrieve the welcome translation string from the resources/lang/messages.php language file:

echo __('messages.welcome');

echo __('I love programming.');

Of course if you are using the Blade templating engine, you may use the {{ }} syntax to echo the translation string or use the @lang directive:

{{ __('messages.welcome') }}

@lang('messages.welcome')

If the specified translation string does not exist, the __ function will return the translation string key. So, using the example above, the __ function would return messages.welcome if the translation string does not exist.

<a name=“replacing-parameters-in-translation-strings”></a>

40.3.1 Replacing Parameters In Translation Strings

If you wish, you may define place-holders in your translation strings. All place-holders are prefixed with a :. For example, you may define a welcome message with a place-holder name:

'welcome' => 'Welcome, :name',

To replace the place-holders when retrieving a translation string, pass an array of replacements as the second argument to the __ function:

echo __('messages.welcome', ['name' => 'dayle']);

If your place-holder contains all capital letters, or only has its first letter capitalized, the translated value will be capitalized accordingly:

'welcome' => 'Welcome, :NAME', // Welcome, DAYLE
'goodbye' => 'Goodbye, :Name', // Goodbye, Dayle

<a name=“pluralization”></a>

40.3.2 Pluralization

Pluralization is a complex problem, as different languages have a variety of complex rules for pluralization. By using a “pipe” character, you may distinguish singular and plural forms of a string:

'apples' => 'There is one apple|There are many apples',

You may even create more complex pluralization rules which specify translation strings for multiple number ranges:

'apples' => '{0} There are none|[1,19] There are some|[20,*] There are many',

After defining a translation string that has pluralization options, you may use the trans_choice function to retrieve the line for a given “count”. In this example, since the count is greater than one, the plural form of the translation string is returned:

echo trans_choice('messages.apples', 10);

You may also define place-holder attributes in pluralization strings. These place-holders may be replaced by passing an array as the third argument to the trans_choice function:

'minutes_ago' => '{1} :value minute ago|[2,*] :value minutes ago',

echo trans_choice('time.minutes_ago', 5, ['value' => 5]);

<a name=“overriding-package-language-files”></a>

40.4 Overriding Package Language Files

Some packages may ship with their own language files. Instead of changing the package’s core files to tweak these lines, you may override them by placing files in the resources/lang/vendor/{package}/{locale} directory.

So, for example, if you need to override the English translation strings in messages.php for a package named skyrim/hearthfire, you should place a language file at: resources/lang/vendor/hearthfire/en/messages.php. Within this file, you should only define the translation strings you wish to override. Any translation strings you don’t override will still be loaded from the package’s original language files.

41 Mail

<a name=“introduction”></a>

41.1 Introduction

Laravel provides a clean, simple API over the popular SwiftMailer library with drivers for SMTP, Mailgun, SparkPost, Amazon SES, PHP’s mail function, and sendmail, allowing you to quickly get started sending mail through a local or cloud based service of your choice.

<a name=“driver-prerequisites”></a>

41.1.1 Driver Prerequisites

The API based drivers such as Mailgun and SparkPost are often simpler and faster than SMTP servers. If possible, you should use one of these drivers. All of the API drivers require the Guzzle HTTP library, which may be installed via the Composer package manager:

composer require guzzlehttp/guzzle

41.1.1.1 Mailgun Driver

To use the Mailgun driver, first install Guzzle, then set the driver option in your config/mail.php configuration file to mailgun. Next, verify that your config/services.php configuration file contains the following options:

'mailgun' => [
    'domain' => 'your-mailgun-domain',
    'secret' => 'your-mailgun-key',
],

41.1.1.2 SparkPost Driver

To use the SparkPost driver, first install Guzzle, then set the driver option in your config/mail.php configuration file to sparkpost. Next, verify that your config/services.php configuration file contains the following options:

'sparkpost' => [
    'secret' => 'your-sparkpost-key',
],

41.1.1.3 SES Driver

To use the Amazon SES driver you must first install the Amazon AWS SDK for PHP. You may install this library by adding the following line to your composer.json file’s require section and running the composer update command:

"aws/aws-sdk-php": "~3.0"

Next, set the driver option in your config/mail.php configuration file to ses and verify that your config/services.php configuration file contains the following options:

'ses' => [
    'key' => 'your-ses-key',
    'secret' => 'your-ses-secret',
    'region' => 'ses-region',  // e.g. us-east-1
],

<a name=“generating-mailables”></a>

41.2 Generating Mailables

In Laravel, each type of email sent by your application is represented as a “mailable” class. These classes are stored in the app/Mail directory. Don’t worry if you don’t see this directory in your application, since it will be generated for you when you create your first mailable class using the make:mail command:

php artisan make:mail OrderShipped

<a name=“writing-mailables”></a>

41.3 Writing Mailables

All of a mailable class’ configuration is done in the build method. Within this method, you may call various methods such as from, subject, view, and attach to configure the email’s presentation and delivery.

<a name=“configuring-the-sender”></a>

41.3.1 Configuring The Sender

41.3.1.1 Using The from Method

First, let’s explore configuring the sender of the email. Or, in other words, who the email is going to be “from”. There are two ways to configure the sender. First, you may use the from method within your mailable class’ build method:

/**
 * Build the message.
 *
 * @return $this
 */
public function build()
{
    return $this->from('example@example.com')
                ->view('emails.orders.shipped');
}

41.3.1.2 Using A Global from Address

However, if your application uses the same “from” address for all of its emails, it can become cumbersome to call the from method in each mailable class you generate. Instead, you may specify a global “from” address in your config/mail.php configuration file. This address will be used if no other “from” address is specified within the mailable class:

'from' => ['address' => 'example@example.com', 'name' => 'App Name'],

<a name=“configuring-the-view”></a>

41.3.2 Configuring The View

Within a mailable class’ build method, you may use the view method to specify which template should be used when rendering the email’s contents. Since each email typically uses a Blade template to render its contents, you have the full power and convenience of the Blade templating engine when building your email’s HTML:

/**
 * Build the message.
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped');
}

{tip} You may wish to create a resources/views/emails directory to house all of your email templates; however, you are free to place them wherever you wish within your resources/views directory.

41.3.2.1 Plain Text Emails

If you would like to define a plain-text version of your email, you may use the text method. Like the view method, the text method accepts a template name which will be used to render the contents of the email. You are free to define both a HTML and plain-text version of your message:

/**
 * Build the message.
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped')
                ->text('emails.orders.shipped_plain');
}

<a name=“view-data”></a>

41.3.3 View Data

41.3.3.1 Via Public Properties

Typically, you will want to pass some data to your view that you can utilize when rendering the email’s HTML. There are two ways you may make data available to your view. First, any public property defined on your mailable class will automatically be made available to the view. So, for example, you may pass data into your mailable class’ constructor and set that data to public properties defined on the class:

<?php

namespace App\Mail;

use App\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class OrderShipped extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * The order instance.
     *
     * @var Order
     */
    public $order;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped');
    }
}

Once the data has been set to a public property, it will automatically be available in your view, so you may access it like you would access any other data in your Blade templates:

<div>
    Price: {{ $order->price }}
</div>

41.3.3.2 Via The with Method:

If you would like to customize the format of your email’s data before it is sent to the template, you may manually pass your data to the view via the with method. Typically, you will still pass data via the mailable class’ constructor; however, you should set this data to protected or private properties so the data is not automatically made available to the template. Then, when calling the with method, pass an array of data that you wish to make available to the template:

<?php

namespace App\Mail;

use App\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class OrderShipped extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * The order instance.
     *
     * @var Order
     */
    protected $order;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped')
                    ->with([
                        'orderName' => $this->order->name,
                        'orderPrice' => $this->order->price,
                    ]);
    }
}

Once the data has been passed to the with method, it will automatically be available in your view, so you may access it like you would access any other data in your Blade templates:

<div>
    Price: {{ $orderPrice }}
</div>

<a name=“attachments”></a>

41.3.4 Attachments

To add attachments to an email, use the attach method within the mailable class’ build method. The attach method accepts the full path to the file as its first argument:

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped')
                    ->attach('/path/to/file');
    }

When attaching files to a message, you may also specify the display name and / or MIME type by passing an array as the second argument to the attach method:

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped')
                    ->attach('/path/to/file', [
                        'as' => 'name.pdf',
                        'mime' => 'application/pdf',
                    ]);
    }

41.3.4.1 Raw Data Attachments

The attachData method may be used to attach a raw string of bytes as an attachment. For example, you might use this method if you have generated a PDF in memory and want to attach it to the email without writing it to disk. The attachData method accepts the raw data bytes as its first argument, the name of the file as its second argument, and an array of options as its third argument:

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped')
                    ->attachData($this->pdf, 'name.pdf', [
                        'mime' => 'application/pdf',
                    ]);
    }

<a name=“inline-attachments”></a>

41.3.5 Inline Attachments

Embedding inline images into your emails is typically cumbersome; however, Laravel provides a convenient way to attach images to your emails and retrieving the appropriate CID. To embed an inline image, use the embed method on the $message variable within your email template. Laravel automatically makes the $message variable available to all of your email templates, so you don’t need to worry about passing it in manually:

<body>
    Here is an image:

    <img src="{{ $message->embed($pathToFile) }}">
</body>

{note} $message variable is not available in markdown messages.

41.3.5.1 Embedding Raw Data Attachments

If you already have a raw data string you wish to embed into an email template, you may use the embedData method on the $message variable:

<body>
    Here is an image from raw data:

    <img src="{{ $message->embedData($data, $name) }}">
</body>

<a name=“customizing-the-swiftmailer-message”></a>

41.3.6 Customizing The SwiftMailer Message

The withSwiftMessage method of the Mailable base class allows you to register a callback which will be invoked with the raw SwiftMailer message instance before sending the message. This gives you an opportunity to customize the message before it is delivered:

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        $this->view('emails.orders.shipped');

        $this->withSwiftMessage(function ($message) {
            $message->getHeaders()
                    ->addTextHeader('Custom-Header', 'HeaderValue');
        });
    }

<a name=“markdown-mailables”></a>

41.4 Markdown Mailables

Markdown mailable messages allow you to take advantage of the pre-built templates and components of mail notifications in your mailables. Since the messages are written in Markdown, Laravel is able to render beautiful, responsive HTML templates for the messages while also automatically generating a plain-text counterpart.

<a name=“generating-markdown-mailables”></a>

41.4.1 Generating Markdown Mailables

To generate a mailable with a corresponding Markdown template, you may use the --markdown option of the make:mail Artisan command:

php artisan make:mail OrderShipped --markdown=emails.orders.shipped

Then, when configuring the mailable within its build method, call the markdown method instead of the view method. The markdown methods accepts the name of the Markdown template and an optional array of data to make available to the template:

/**
 * Build the message.
 *
 * @return $this
 */
public function build()
{
    return $this->from('example@example.com')
                ->markdown('emails.orders.shipped');
}

<a name=“writing-markdown-messages”></a>

41.4.2 Writing Markdown Messages

Markdown mailables use a combination of Blade components and Markdown syntax which allow you to easily construct mail messages while leveraging Laravel’s pre-crafted components:

@component('mail::message')
# Order Shipped

Your order has been shipped!

@component('mail::button', ['url' => $url])
View Order
@endcomponent

Thanks,<br>
{{ config('app.name') }}
@endcomponent

{tip} Do not use excess indentation when writing Markdown emails. Markdown parsers will render indented content as code blocks.

41.4.2.1 Button Component

The button component renders a centered button link. The component accepts two arguments, a url and an optional color. Supported colors are blue, green, and red. You may add as many button components to a message as you wish:

@component('mail::button', ['url' => $url, 'color' => 'green'])
View Order
@endcomponent

41.4.2.2 Panel Component

The panel component renders the given block of text in a panel that has a slightly different background color than the rest of the message. This allows you to draw attention to a given block of text:

@component('mail::panel')
This is the panel content.
@endcomponent

41.4.2.3 Table Component

The table component allows you to transform a Markdown table into an HTML table. The component accepts the Markdown table as its content. Table column alignment is supported using the default Markdown table alignment syntax:

@component('mail::table')
| Laravel       | Table         | Example  |
| ------------- |:-------------:| --------:|
| Col 2 is      | Centered      | $10      |
| Col 3 is      | Right-Aligned | $20      |
@endcomponent

<a name=“customizing-the-components”></a>

41.4.3 Customizing The Components

You may export all of the Markdown mail components to your own application for customization. To export the components, use the vendor:publish Artisan command to publish the laravel-mail asset tag:

php artisan vendor:publish --tag=laravel-mail

This command will publish the Markdown mail components to the resources/views/vendor/mail directory. The mail directory will contain a html and a markdown directory, each containing their respective representations of every available component. You are free to customize these components however you like.

41.4.3.1 Customizing The CSS

After exporting the components, the resources/views/vendor/mail/html/themes directory will contain a default.css file. You may customize the CSS in this file and your styles will automatically be in-lined within the HTML representations of your Markdown mail messages.

{tip} If you would like to build an entirely new theme for the Markdown components, write a new CSS file within the html/themes directory and change the theme option of your mail configuration file.

<a name=“previewing-mailables-in-the-browser”></a>

41.5 Previewing Mailables In The Browser

When designing a mailable’s template, it is convenient to quickly preview the rendered mailable in your browser like a typical Blade template. For this reason, Laravel allows you to return any mailable directly from a route Closure or controller. When a mailable is returned, it will be rendered and displayed in the browser, allowing you to quickly preview its design without needing to send it to an actual email address:

Route::get('/mailable', function () {
    $invoice = App\Invoice::find(1);

    return new App\Mail\InvoicePaid($invoice);
});

<a name=“sending-mail”></a>

41.6 Sending Mail

To send a message, use the to method on the Mail facade. The to method accepts an email address, a user instance, or a collection of users. If you pass an object or collection of objects, the mailer will automatically use their email and name properties when setting the email recipients, so make sure these attributes are available on your objects. Once you have specified your recipients, you may pass an instance of your mailable class to the send method:

<?php

namespace App\Http\Controllers;

use App\Order;
use App\Mail\OrderShipped;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Http\Controllers\Controller;

class OrderController extends Controller
{
    /**
     * Ship the given order.
     *
     * @param  Request  $request
     * @param  int  $orderId
     * @return Response
     */
    public function ship(Request $request, $orderId)
    {
        $order = Order::findOrFail($orderId);

        // Ship order...

        Mail::to($request->user())->send(new OrderShipped($order));
    }
}

Of course, you are not limited to just specifying the “to” recipients when sending a message. You are free to set “to”, “cc”, and “bcc” recipients all within a single, chained method call:

Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->send(new OrderShipped($order));

<a name=“queueing-mail”></a>

41.6.1 Queueing Mail

41.6.1.1 Queueing A Mail Message

Since sending email messages can drastically lengthen the response time of your application, many developers choose to queue email messages for background sending. Laravel makes this easy using its built-in unified queue API. To queue a mail message, use the queue method on the Mail facade after specifying the message’s recipients:

Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->queue(new OrderShipped($order));

This method will automatically take care of pushing a job onto the queue so the message is sent in the background. Of course, you will need to configure your queues before using this feature.

41.6.1.2 Delayed Message Queueing

If you wish to delay the delivery of a queued email message, you may use the later method. As its first argument, the later method accepts a DateTime instance indicating when the message should be sent:

$when = now()->addMinutes(10);

Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->later($when, new OrderShipped($order));

41.6.1.3 Pushing To Specific Queues

Since all mailable classes generated using the make:mail command make use of the Illuminate\Bus\Queueable trait, you may call the onQueue and onConnection methods on any mailable class instance, allowing you to specify the connection and queue name for the message:

$message = (new OrderShipped($order))
                ->onConnection('sqs')
                ->onQueue('emails');

Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->queue($message);

41.6.1.4 Queueing By Default

If you have mailable classes that you want to always be queued, you may implement the ShouldQueue contract on the class. Now, even if you call the send method when mailing, the mailable will still be queued since it implements the contract:

use Illuminate\Contracts\Queue\ShouldQueue;

class OrderShipped extends Mailable implements ShouldQueue
{
    //
}

<a name=“mail-and-local-development”></a>

41.7 Mail & Local Development

When developing an application that sends email, you probably don’t want to actually send emails to live email addresses. Laravel provides several ways to “disable” the actual sending of emails during local development.

41.7.0.1 Log Driver

Instead of sending your emails, the log mail driver will write all email messages to your log files for inspection. For more information on configuring your application per environment, check out the configuration documentation.

41.7.0.2 Universal To

Another solution provided by Laravel is to set a universal recipient of all emails sent by the framework. This way, all the emails generated by your application will be sent to a specific address, instead of the address actually specified when sending the message. This can be done via the to option in your config/mail.php configuration file:

'to' => [
    'address' => 'example@example.com',
    'name' => 'Example'
],

41.7.0.3 Mailtrap

Finally, you may use a service like Mailtrap and the smtp driver to send your email messages to a “dummy” mailbox where you may view them in a true email client. This approach has the benefit of allowing you to actually inspect the final emails in Mailtrap’s message viewer.

<a name=“events”></a>

41.8 Events

Laravel fires two events during the process of sending mail messages. The MessageSending event is fired prior to a message being sent, while the MessageSent event is fired after a message has been sent. Remember, these events are fired when the mail is being sent, not when it is queued. You may register an event listener for this event in your EventServiceProvider:

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'Illuminate\Mail\Events\MessageSending' => [
        'App\Listeners\LogSendingMessage',
    ],
    'Illuminate\Mail\Events\MessageSent' => [
        'App\Listeners\LogSentMessage',
    ],
];

42 Middleware

<a name=“introduction”></a>

42.1 Introduction

Middleware provide a convenient mechanism for filtering HTTP requests entering your application. For example, Laravel includes a middleware that verifies the user of your application is authenticated. If the user is not authenticated, the middleware will redirect the user to the login screen. However, if the user is authenticated, the middleware will allow the request to proceed further into the application.

Of course, additional middleware can be written to perform a variety of tasks besides authentication. A CORS middleware might be responsible for adding the proper headers to all responses leaving your application. A logging middleware might log all incoming requests to your application.

There are several middleware included in the Laravel framework, including middleware for authentication and CSRF protection. All of these middleware are located in the app/Http/Middleware directory.

<a name=“defining-middleware”></a>

42.2 Defining Middleware

To create a new middleware, use the make:middleware Artisan command:

php artisan make:middleware CheckAge

This command will place a new CheckAge class within your app/Http/Middleware directory. In this middleware, we will only allow access to the route if the supplied age is greater than 200. Otherwise, we will redirect the users back to the home URI.

<?php

namespace App\Http\Middleware;

use Closure;

class CheckAge
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->age <= 200) {
            return redirect('home');
        }

        return $next($request);
    }
}

As you can see, if the given age is less than or equal to 200, the middleware will return an HTTP redirect to the client; otherwise, the request will be passed further into the application. To pass the request deeper into the application (allowing the middleware to “pass”), call the $next callback with the $request.

It’s best to envision middleware as a series of “layers” HTTP requests must pass through before they hit your application. Each layer can examine the request and even reject it entirely.

42.2.1 Before & After Middleware

Whether a middleware runs before or after a request depends on the middleware itself. For example, the following middleware would perform some task before the request is handled by the application:

<?php

namespace App\Http\Middleware;

use Closure;

class BeforeMiddleware
{
    public function handle($request, Closure $next)
    {
        // Perform action

        return $next($request);
    }
}

However, this middleware would perform its task after the request is handled by the application:

<?php

namespace App\Http\Middleware;

use Closure;

class AfterMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        // Perform action

        return $response;
    }
}

<a name=“registering-middleware”></a>

42.3 Registering Middleware

<a name=“global-middleware”></a>

42.3.1 Global Middleware

If you want a middleware to run during every HTTP request to your application, list the middleware class in the $middleware property of your app/Http/Kernel.php class.

<a name=“assigning-middleware-to-routes”></a>

42.3.2 Assigning Middleware To Routes

If you would like to assign middleware to specific routes, you should first assign the middleware a key in your app/Http/Kernel.php file. By default, the $routeMiddleware property of this class contains entries for the middleware included with Laravel. To add your own, append it to this list and assign it a key of your choosing. For example:

// Within App\Http\Kernel Class...

protected $routeMiddleware = [
    'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];

Once the middleware has been defined in the HTTP kernel, you may use the middleware method to assign middleware to a route:

Route::get('admin/profile', function () {
    //
})->middleware('auth');

You may also assign multiple middleware to the route:

Route::get('/', function () {
    //
})->middleware('first', 'second');

When assigning middleware, you may also pass the fully qualified class name:

use App\Http\Middleware\CheckAge;

Route::get('admin/profile', function () {
    //
})->middleware(CheckAge::class);

<a name=“middleware-groups”></a>

42.3.3 Middleware Groups

Sometimes you may want to group several middleware under a single key to make them easier to assign to routes. You may do this using the $middlewareGroups property of your HTTP kernel.

Out of the box, Laravel comes with web and api middleware groups that contain common middleware you may want to apply to your web UI and API routes:

/**
 * The application's route middleware groups.
 *
 * @var array
 */
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        'throttle:60,1',
        'auth:api',
    ],
];

Middleware groups may be assigned to routes and controller actions using the same syntax as individual middleware. Again, middleware groups make it more convenient to assign many middleware to a route at once:

Route::get('/', function () {
    //
})->middleware('web');

Route::group(['middleware' => ['web']], function () {
    //
});

{tip} Out of the box, the web middleware group is automatically applied to your routes/web.php file by the RouteServiceProvider.

<a name=“middleware-parameters”></a>

42.4 Middleware Parameters

Middleware can also receive additional parameters. For example, if your application needs to verify that the authenticated user has a given “role” before performing a given action, you could create a CheckRole middleware that receives a role name as an additional argument.

Additional middleware parameters will be passed to the middleware after the $next argument:

<?php

namespace App\Http\Middleware;

use Closure;

class CheckRole
{
    /**
     * Handle the incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string  $role
     * @return mixed
     */
    public function handle($request, Closure $next, $role)
    {
        if (! $request->user()->hasRole($role)) {
            // Redirect...
        }

        return $next($request);
    }

}

Middleware parameters may be specified when defining the route by separating the middleware name and parameters with a :. Multiple parameters should be delimited by commas:

Route::put('post/{id}', function ($id) {
    //
})->middleware('role:editor');

<a name=“terminable-middleware”></a>

42.5 Terminable Middleware

Sometimes a middleware may need to do some work after the HTTP response has been sent to the browser. For example, the “session” middleware included with Laravel writes the session data to storage after the response has been sent to the browser. If you define a terminate method on your middleware, it will automatically be called after the response is sent to the browser.

<?php

namespace Illuminate\Session\Middleware;

use Closure;

class StartSession
{
    public function handle($request, Closure $next)
    {
        return $next($request);
    }

    public function terminate($request, $response)
    {
        // Store the session data...
    }
}

The terminate method should receive both the request and the response. Once you have defined a terminable middleware, you should add it to the list of route or global middleware in the app/Http/Kernel.php file.

When calling the terminate method on your middleware, Laravel will resolve a fresh instance of the middleware from the service container. If you would like to use the same middleware instance when the handle and terminate methods are called, register the middleware with the container using the container’s singleton method.

43 Database: Migrations

<a name=“introduction”></a>

43.1 Introduction

Migrations are like version control for your database, allowing your team to easily modify and share the application’s database schema. Migrations are typically paired with Laravel’s schema builder to easily build your application’s database schema. If you have ever had to tell a teammate to manually add a column to their local database schema, you’ve faced the problem that database migrations solve.

The Laravel Schema facade provides database agnostic support for creating and manipulating tables across all of Laravel’s supported database systems.

<a name=“generating-migrations”></a>

43.2 Generating Migrations

To create a migration, use the make:migration Artisan command:

php artisan make:migration create_users_table

The new migration will be placed in your database/migrations directory. Each migration file name contains a timestamp which allows Laravel to determine the order of the migrations.

The --table and --create options may also be used to indicate the name of the table and whether the migration will be creating a new table. These options pre-fill the generated migration stub file with the specified table:

php artisan make:migration create_users_table --create=users

php artisan make:migration add_votes_to_users_table --table=users

If you would like to specify a custom output path for the generated migration, you may use the --path option when executing the make:migration command. The given path should be relative to your application’s base path.

<a name=“migration-structure”></a>

43.3 Migration Structure

A migration class contains two methods: up and down. The up method is used to add new tables, columns, or indexes to your database, while the down method should reverse the operations performed by the up method.

Within both of these methods you may use the Laravel schema builder to expressively create and modify tables. To learn about all of the methods available on the Schema builder, check out its documentation. For example, this migration example creates a flights table:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateFlightsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('flights', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('airline');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('flights');
    }
}

<a name=“running-migrations”></a>

43.4 Running Migrations

To run all of your outstanding migrations, execute the migrate Artisan command:

php artisan migrate

{note} If you are using the Homestead virtual machine, you should run this command from within your virtual machine.

43.4.0.1 Forcing Migrations To Run In Production

Some migration operations are destructive, which means they may cause you to lose data. In order to protect you from running these commands against your production database, you will be prompted for confirmation before the commands are executed. To force the commands to run without a prompt, use the --force flag:

php artisan migrate --force

<a name=“rolling-back-migrations”></a>

43.4.1 Rolling Back Migrations

To rollback the latest migration operation, you may use the rollback command. This command rolls back the last “batch” of migrations, which may include multiple migration files:

php artisan migrate:rollback

You may rollback a limited number of migrations by providing the step option to the rollback command. For example, the following command will rollback the last five migrations:

php artisan migrate:rollback --step=5

The migrate:reset command will roll back all of your application’s migrations:

php artisan migrate:reset

43.4.1.1 Rollback & Migrate In Single Command

The migrate:refresh command will roll back all of your migrations and then execute the migrate command. This command effectively re-creates your entire database:

php artisan migrate:refresh

// Refresh the database and run all database seeds...
php artisan migrate:refresh --seed

You may rollback & re-migrate a limited number of migrations by providing the step option to the refresh command. For example, the following command will rollback & re-migrate the last five migrations:

php artisan migrate:refresh --step=5

43.4.1.2 Drop All Tables & Migrate

The migrate:fresh command will drop all tables from the database and then execute the migrate command:

php artisan migrate:fresh

php artisan migrate:fresh --seed

<a name=“tables”></a>

43.5 Tables

<a name=“creating-tables”></a>

43.5.1 Creating Tables

To create a new database table, use the create method on the Schema facade. The create method accepts two arguments. The first is the name of the table, while the second is a Closure which receives a Blueprint object that may be used to define the new table:

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
});

Of course, when creating the table, you may use any of the schema builder’s column methods to define the table’s columns.

43.5.1.1 Checking For Table / Column Existence

You may easily check for the existence of a table or column using the hasTable and hasColumn methods:

if (Schema::hasTable('users')) {
    //
}

if (Schema::hasColumn('users', 'email')) {
    //
}

43.5.1.2 Database Connection & Table Options

If you want to perform a schema operation on a database connection that is not your default connection, use the connection method:

Schema::connection('foo')->create('users', function (Blueprint $table) {
    $table->increments('id');
});

You may use the following commands on the schema builder to define the table’s options:

Command Description
$table->engine = 'InnoDB'; Specify the table storage engine (MySQL).
$table->charset = 'utf8'; Specify a default character set for the table (MySQL).
$table->collation = 'utf8_unicode_ci'; Specify a default collation for the table (MySQL).
$table->temporary(); Create a temporary table (except SQL Server).

<a name=“renaming-and-dropping-tables”></a>

43.5.2 Renaming / Dropping Tables

To rename an existing database table, use the rename method:

Schema::rename($from, $to);

To drop an existing table, you may use the drop or dropIfExists methods:

Schema::drop('users');

Schema::dropIfExists('users');

43.5.2.1 Renaming Tables With Foreign Keys

Before renaming a table, you should verify that any foreign key constraints on the table have an explicit name in your migration files instead of letting Laravel assign a convention based name. Otherwise, the foreign key constraint name will refer to the old table name.

<a name=“columns”></a>

43.6 Columns

<a name=“creating-columns”></a>

43.6.1 Creating Columns

The table method on the Schema facade may be used to update existing tables. Like the create method, the table method accepts two arguments: the name of the table and a Closure that receives a Blueprint instance you may use to add columns to the table:

Schema::table('users', function (Blueprint $table) {
    $table->string('email');
});

43.6.1.1 Available Column Types

Of course, the schema builder contains a variety of column types that you may specify when building your tables:

Command Description
$table->bigIncrements('id'); Auto-incrementing UNSIGNED BIGINT (primary key) equivalent column.
$table->bigInteger('votes'); BIGINT equivalent column.
$table->binary('data'); BLOB equivalent column.
$table->boolean('confirmed'); BOOLEAN equivalent column.
$table->char('name', 100); CHAR equivalent column with an optional length.
$table->date('created_at'); DATE equivalent column.
$table->dateTime('created_at'); DATETIME equivalent column.
$table->dateTimeTz('created_at'); DATETIME (with timezone) equivalent column.
$table->decimal('amount', 8, 2); DECIMAL equivalent column with a precision (total digits) and scale (decimal digits).
$table->double('amount', 8, 2); DOUBLE equivalent column with a precision (total digits) and scale (decimal digits).
$table->enum('level', ['easy', 'hard']); ENUM equivalent column.
$table->float('amount', 8, 2); FLOAT equivalent column with a precision (total digits) and scale (decimal digits).
$table->geometry('positions'); GEOMETRY equivalent column.
$table->geometryCollection('positions'); GEOMETRYCOLLECTION equivalent column.
$table->increments('id'); Auto-incrementing UNSIGNED INTEGER (primary key) equivalent column.
$table->integer('votes'); INTEGER equivalent column.
$table->ipAddress('visitor'); IP address equivalent column.
$table->json('options'); JSON equivalent column.
$table->jsonb('options'); JSONB equivalent column.
$table->lineString('positions'); LINESTRING equivalent column.
$table->longText('description'); LONGTEXT equivalent column.
$table->macAddress('device'); MAC address equivalent column.
$table->mediumIncrements('id'); Auto-incrementing UNSIGNED MEDIUMINT (primary key) equivalent column.
$table->mediumInteger('votes'); MEDIUMINT equivalent column.
$table->mediumText('description'); MEDIUMTEXT equivalent column.
$table->morphs('taggable'); Adds taggable_id UNSIGNED INTEGER and taggable_type VARCHAR equivalent columns.
$table->multiLineString('positions'); MULTILINESTRING equivalent column.
$table->multiPoint('positions'); MULTIPOINT equivalent column.
$table->multiPolygon('positions'); MULTIPOLYGON equivalent column.
$table->nullableMorphs('taggable'); Adds nullable versions of morphs() columns.
$table->nullableTimestamps(); Alias of timestamps() method.
$table->point('position'); POINT equivalent column.
$table->polygon('positions'); POLYGON equivalent column.
$table->rememberToken(); Adds a nullable remember_token VARCHAR(100) equivalent column.
$table->smallIncrements('id'); Auto-incrementing UNSIGNED SMALLINT (primary key) equivalent column.
$table->smallInteger('votes'); SMALLINT equivalent column.
$table->softDeletes(); Adds a nullable deleted_at TIMESTAMP equivalent column for soft deletes.