laravel certification
Architecture [ Service Container Binding and Resolution ] { dependency injection, Simple Bindings, Binding A Singleton, Binding Instances, Binding Primitives, Binding Interfaces To Implementations, Contextual Binding, Tagging, Extending Bindings, The Make Method, Automatic Injection, Container Events, PSR-11 }
Introduction The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection: class dependencies are "injected" into the class via the constructor or, in some cases, "setter" methods. However, since the dependency 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 the dependency when testing our application. Binding Basics Almost all of your service container bindings will be registered within service providers. 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. 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. 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')); }); Binding Instances You may also bind an existing object instance into the container using the instancemethod. 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); 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); Binding Interfaces To Implementations $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 EventPusherinterface in a constructor, or any other location where dependencies are injected by the service container. Contextual Binding Sometimes you may have two classes that utilize the same interface, but you wish to inject different implementations into each class. $this->app->when(PhotoController::class) ->needs(Filesystem::class) ->give(function () { return Storage::disk('local'); }); $this->app->when([VideoController::class, UploadController::class]) ->needs(Filesystem::class) ->give(function () { return Storage::disk('s3'); }); 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 taggedmethod: $this->app->bind('ReportAggregator', function ($app) { return new ReportAggregator($app->tagged('reports')); }); 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); }); Resolving The make Method You may use the make method to resolve a class instance out of the container. The makemethod 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]); 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. 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. 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'); // }); An exception is thrown if the given identifier can't be resolved. The exception will be an instance of Psr\Container\NotFoundExceptionInterface if the identifier was never bound. If the identifier was bound but was unable to be resolved, an instance of Psr\Container\ContainerExceptionInterface will be thrown.
Middleware [ Defining / Registering Middleware ] { Defining Middleware, Before & After Middleware, Global Middleware, Assigning Middleware To Routes, Middleware Groups, Sorting Middleware }
Middleware provide a convenient mechanism for filtering HTTP requests entering your application. 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. Defining Middleware To create a new middleware, use the make:middleware Artisan command public function handle($request, Closure $next) { if ($request->age <= 200) { return redirect('home'); } return $next($request); } To pass the request deeper into the application (allowing the middleware to "pass"), call the $next callback with the $request. 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: 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: public function handle($request, Closure $next) { $response = $next($request); // Perform action return $response; } 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. 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 $routeMiddlewareproperty 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: Once the middleware has been defined in the HTTP kernel, you may use the middlewaremethod 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); 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 () { // }); Out of the box, the web middleware group is automatically applied to your routes/web.php file by the RouteServiceProvider. Sorting Middleware Rarely, you may need your middleware to execute in a specific order but not have control over their order when they are assigned to the route. In this case, you may specify your middleware priority using the $middlewarePriority property of your app/Http/Kernel.php file: Terminable Middleware Sometimes a middleware may need to do some work after the HTTP response has been prepared. For example, the "session" middleware included with Laravel writes the session data to storage after the response has been fully prepared. If you define a terminate method on your middleware, it will automatically be called after the response is ready to be sent to the browser 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
Requests [ PSR-7 Requests ] { symfony/psr-http-message-bridge, zendframework/zend-diactoros, Psr\Http\Message\ServerRequestInterface }
The PSR-7 standard specifies interfaces for HTTP messages, including requests and responses. If you would like to obtain an instance of a PSR-7 request instead of a Laravel request, you will first need to install a few libraries. Laravel uses the Symfony HTTP Message Bridge component to convert typical Laravel requests and responses into PSR-7 compatible implementations: composer require symfony/psr-http-message-bridge composer require zendframework/zend-diactoros Once you have installed these libraries, you may obtain a PSR-7 request by type-hinting the request interface on your route Closure or controller method: use Psr\Http\Message\ServerRequestInterface; Route::get('/', function (ServerRequestInterface $request) { // }); If you return a PSR-7 response instance from a route or controller, it will automatically be converted back to a Laravel response instance and be displayed by the framework.
Validation [ Custom Rules ] { Rule Objects, Using Closures, Using Extensions }
Using Rule Objects Laravel provides a variety of helpful validation rules; however, you may wish to specify some of your own. One method of registering custom validation rules is using rule objects. To generate a new rule object, you may use the make:rule Artisan command. Let's use this command to generate a rule that verifies a string is uppercase. Laravel will place the new rule in the app/Rules directory php artisan make:rule Uppercase Once the rule has been created, we are ready to define its behavior. A rule object contains two methods: passes and message. The passes method receives the attribute value and name, and should return true or false depending on whether the attribute value is valid or not. The message method should return the validation error message that should be used when validation fails: public function passes($attribute, $value) { return strtoupper($value) === $value; } /** * Get the validation error message. * * @return string */ public function message() { return 'The :attribute must be uppercase.'; } You may call the trans helper from your message method if you would like to return an error message from your translation files: /** * Get the validation error message. * * @return string */ public function message() { return trans('validation.uppercase'); } Once the rule has been defined, you may attach it to a validator by passing an instance of the rule object with your other validation rules: use App\Rules\Uppercase; $request->validate([ 'name' => ['required', 'string', new Uppercase], ]); Using Closures If you only need the functionality of a custom rule once throughout your application, you may use a Closure instead of a rule object. The Closure receives the attribute's name, the attribute's value, and a $fail callback that should be called if validation fails: $validator = Validator::make($request->all(), [ 'title' => [ 'required', 'max:255', function ($attribute, $value, $fail) { if ($value === 'foo') { $fail($attribute.' is invalid.'); } }, ], ]); Using Extensions Another method of registering custom validation rules is using the extend method on the Validator facade. Let's use this method within a service provider to register a custom validation rule: Validator::extend('foo', function ($attribute, $value, $parameters, $validator) { return $value == 'foo'; }); The custom validator Closure receives four arguments: the name of the $attributebeing validated, the $value of the attribute, an array of $parameters passed to the rule, and the Validator instance. You may also pass a class and method to the extend method instead of a Closure: Validator::extend('foo', 'FooValidator@validate'); Defining The Error Message You will also need to define an error message for your custom rule. You can do so either using an inline custom message array or by adding an entry in the validation language file. This message should be placed in the first level of the array, not within the customarray, which is only for attribute-specific error messages: "foo" => "Your input was invalid!", "accepted" => "The :attribute must be accepted.", // The rest of the validation error messages... When creating a custom validation rule, you may sometimes need to define custom placeholder replacements for error messages. You may do so by creating a custom Validator as described above then making a call to the replacer method on the Validator facade. You may do this within the boot method of a service provider: Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) { return str_replace(...); }); Implicit Extensions By default, when an attribute being validated is not present or contains an empty string, normal validation rules, including custom extensions, are not run. For example, the unique rule will not be run against an empty string: $rules = ['name' => 'unique:users,name']; $input = ['name' => '']; Validator::make($input, $rules)->passes(); // true For a rule to run even when an attribute is empty, the rule must imply that the attribute is required. To create such an "implicit" extension, use the Validator::extendImplicit()method: Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) { return $value == 'foo'; }); An "implicit" extension only implies that the attribute is required. Whether it actually invalidates a missing or empty attribute is up to you.
Security [ XSS Protection ] { {{ }} htmlspecialchars }
Blade {{ }} statements are automatically sent through PHP's htmlspecialchars function to prevent XSS attacks.
Responses [ Encryption ]
By default, all cookies generated by Laravel are encrypted and signed so that they can't be modified or read by the client. If you would like to disable encryption for a subset of cookies generated by your application, you may use the $except property of the App\Http\Middleware\EncryptCookies middleware, which is located in the app/Http/Middleware directory: /** * The names of the cookies that should not be encrypted. * * @var array */ protected $except = [ 'cookie_name', ];
URL Generation [ Default Values ] { URL::defaults(['locale' => $request->user()->locale]); }
For some applications, you may wish to specify request-wide default values for certain URL parameters. For example, imagine many of your routes define a {locale}parameter: Route::get('/{locale}/posts', function () { // })->name('post.index') It is cumbersome to always pass the locale every time you call the route helper. So, you may use the URL::defaults method to define a default value for this parameter that will always be applied during the current request. You may wish to call this method from a route middleware so that you have access to the current request: public function handle($request, Closure $next) { URL::defaults(['locale' => $request->user()->locale]); return $next($request); } Once the default value for the locale parameter has been set, you are no longer required to pass its value when generating URLs via the route helper.
Controllers [ 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 When registering routes for single action controllers, you do not need to specify a method: Route::get('user/{id}', 'ShowProfile'); You may generate an invokable controller by using the --invokable option of the make:controller Artisan command: php artisan make:controller ShowProfile --invokable
Mail [ Generating Mailables ] { app/Mail directory; php artisan make:mail OrderShipped }
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
Requests [ Retrieving Input ] { Input Trimming & Normalization, Retrieving All Input Data, Retrieving An Input Value, Retrieving Input From The Query String, Retrieving Input Via Dynamic Properties, Retrieving JSON Input Values, Retrieving A Portion Of The Input Data, Determining If An Input Value Is Present, Old Input, Flashing Input To The Session, Flashing Input Then Redirecting, Retrieving Old Input, Retrieving Cookies From Requests }
Input Trimming & Normalization By default, Laravel includes the TrimStrings and ConvertEmptyStringsToNull middleware in your application's global middleware stack. These middleware are listed in the stack by the App\Http\Kernel class. These middleware will automatically trim all incoming string fields on the request, as well as convert any empty string fields to null. This allows you to not have to worry about these normalization concerns in your routes and controllers. If you would like to disable this behavior, you may remove the two middleware from your application's middleware stack by removing them from the $middleware property of your App\Http\Kernel class. Retrieving All Input Data You may also retrieve all of the input data as an array using the all method: $input = $request->all(); You may call the input method without any arguments in order to retrieve all of the input values as an associative array: $input = $request->input(); Retrieving An Input Value Using a few simple methods, you may access all of the user input from your Illuminate\Http\Request instance without worrying about which HTTP verb was used for the request. Regardless of the HTTP verb, the input method may be used to retrieve user input: $name = $request->input('name'); You may pass a default value as the second argument to the input method. This value will be returned if the requested input value is not present on the request: $name = $request->input('name', 'Sally'); When working with forms that contain array inputs, use "dot" notation to access the arrays: $name = $request->input('products.0.name'); $names = $request->input('products.*.name'); Retrieving Input From The Query String While the input method retrieves values from entire request payload (including the query string), the query method will only retrieve values from the query string: $name = $request->query('name'); If the requested query string value data is not present, the second argument to this method will be returned: $name = $request->query('name', 'Helen'); You may call the query method without any arguments in order to retrieve all of the query string values as an associative array: $query = $request->query(); Retrieving Input Via Dynamic Properties You may also access user input using dynamic properties on the Illuminate\Http\Request instance. For example, if one of your application's forms contains a name field, you may access the value of the field like so: $name = $request->name; When using dynamic properties, Laravel will first look for the parameter's value in the request payload. If it is not present, Laravel will search for the field in the route parameters. Retrieving JSON Input Values When sending JSON requests to your application, you may access the JSON data via the input method as long as the Content-Type header of the request is properly set to application/json. You may even use "dot" syntax to dig into JSON arrays: $name = $request->input('user.name'); Retrieving A Portion Of The Input Data If you need to retrieve a subset of the input data, you may use the only and exceptmethods. Both of these methods accept a single array or a dynamic list of arguments: $input = $request->only(['username', 'password']); $input = $request->only('username', 'password'); $input = $request->except(['credit_card']); $input = $request->except('credit_card'); The only method returns all of the key / value pairs that you request; however, it will not return key / value pairs that are not present on the request. Determining If An Input Value Is Present You should use the has method to determine if a value is present on the request. The has method returns true if the value is present on the request: if ($request->has('name')) { // } When given an array, the has method will determine if all of the specified values are present: if ($request->has(['name', 'email'])) { // } If you would like to determine if a value is present on the request and is not empty, you may use the filled method: if ($request->filled('name')) { // } Old Input Laravel allows you to keep input from one request during the next request. This feature is particularly useful for re-populating forms after detecting validation errors. However, if you are using Laravel's included validation features, it is unlikely you will need to manually use these methods, as some of Laravel's built-in validation facilities will call them automatically. Flashing Input To The Session The flash method on the Illuminate\Http\Request class will flash the current input to the session so that it is available during the user's next request to the application: $request->flash(); You may also use the flashOnly and flashExcept methods to flash a subset of the request data to the session. These methods are useful for keeping sensitive information such as passwords out of the session: $request->flashOnly(['username', 'email']); $request->flashExcept('password'); Flashing Input Then Redirecting Since you often will want to flash input to the session and then redirect to the previous page, you may easily chain input flashing onto a redirect using the withInput method: return redirect('form')->withInput(); return redirect('form')->withInput( $request->except('password') ); Retrieving Old Input To retrieve flashed input from the previous request, use the old method on the Requestinstance. The old method will pull the previously flashed input data from the session: $username = $request->old('username'); Laravel also provides a global old helper. If you are displaying old input within a Blade template, it is more convenient to use the old helper. If no old input exists for the given field, null will be returned: <input type="text" name="username" value="{{ old('username') }}"> Retrieving Cookies From Requests All cookies created by the Laravel framework are encrypted and signed with an authentication code, meaning they will be considered invalid if they have been changed by the client. To retrieve a cookie value from the request, use the cookiemethod on a Illuminate\Http\Request instance: $value = $request->cookie('name'); Alternatively, you may use the Cookie facade to access cookie values: $value = Cookie::get('name');
Security [ CSRF Protection ] { cross-site request forgery(CSRF), @csrf, VerifyCsrfToken middleware, which is included in the web middleware group, $except property of the VerifyCsrfToken middleware, X-CSRF-TOKEN request header, XSRF-TOKEN cookie - X-XSRF-TOKEN request header }
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 Blade directive to generate the token field: <form method="POST" action="/profile"> @csrf ... </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. 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/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. 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: protected $except = [ 'stripe/*', 'http://example.com/foo/bar', 'http://example.com/foo/*', ]; The CSRF middleware is automatically disabled when running tests. X-CSRF-TOKEN In addition to checking for the CSRF token as a POST parameter, the VerifyCsrfTokenmiddleware 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') } }); By default, the resources/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. 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-TOKENheader.
Security [ Encryption / Hashing ] { uses OpenSSL to provide AES-256 and AES-128 encryption, message authentication code (MAC), key option in your config/app.php, [ 'secret' => encrypt($request->secret) ], Crypt::encryptString('Hello world.'); Crypt::decryptString($encrypted); $decrypted = decrypt($encryptedValue); Hash facade provides secure Bcrypt and Argon2, Hash::make('password', [ 'memory' => 1024, 'time' => 2, 'threads' => 2, ]); Hash::check('plain-text', $hashedPassword), Hash::needsRehash($hashed)}
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. Configuration Before using Laravel's encrypter, you must set a key option in your config/app.phpconfiguration 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. Using The Encrypter 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: public function storeSecret(Request $request, $id) { $user = User::findOrFail($id); $user->fill([ 'secret' => encrypt($request->secret) ])->save(); } 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 Cryptfacade: use Illuminate\Support\Facades\Crypt; $encrypted = Crypt::encryptString('Hello world.'); $decrypted = Crypt::decryptString($encrypted); 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) { // } Introduction The Laravel Hash facade provides secure Bcrypt and Argon2 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 use Bcrypt for registration and authentication by default. 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. Configuration The default hashing driver for your application is configured in the config/hashing.phpconfiguration file. There are currently three supported drivers: Bcrypt and Argon2(Argon2i and Argon2id variants). The Argon2i driver requires PHP 7.2.0 or greater and the Argon2id driver requires PHP 7.3.0 or greater. Basic Usage You may hash a password by calling the make method on the Hash facade: public function update(Request $request) { // Validate the new password length... $request->user()->fill([ 'password' => Hash::make($request->newPassword) ])->save(); } Adjusting The Bcrypt Work Factor If you are using the Bcrypt algorithm, the make method allows you to manage the work factor of the algorithm using the rounds option; however, the default is acceptable for most applications: $hashed = Hash::make('password', [ 'rounds' => 12 ]); Adjusting The Argon2 Work Factor If you are using the Argon2 algorithm, the make method allows you to manage the work factor of the algorithm using the memory, time, and threads options; however, the defaults are acceptable for most applications: $hashed = Hash::make('password', [ 'memory' => 1024, 'time' => 2, 'threads' => 2, ]); For more information on these options, check out the official PHP documentation. 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... } 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'); }
Frontend [ Localization ] { resources/lang, App::setLocale($locale); App::getLocale(); echo __('messages.welcome'); echo __('I love programming.'); {{ __('messages.welcome') }} @lang('messages.welcome'), 'welcome' => 'Welcome, :name' trans_choice('messages.apples', 10); resources/lang/vendor/{package}/{locale} }
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: return [ 'welcome' => 'Welcome to our application' ]; Configuring The Locale The default language for your application is stored in the config/app.php configuration file. 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', 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')) { // } Defining Translation Strings 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: // resources/lang/en/messages.php return [ 'welcome' => 'Welcome to our application' ]; 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." } 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.'); 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. The @lang directive does not escape any output. You are fully responsible for escaping your own output when using this directive. Replacing Parameters In Translation Strings If you wish, you may define placeholders in your translation strings. All placeholders are prefixed with a :. For example, you may define a welcome message with a placeholder name: 'welcome' => 'Welcome, :name', To replace the placeholders when retrieving a translation string, pass an array of replacements as the second argument to the __ function: echo __('messages.welcome', ['name' => 'dayle']); If your placeholder 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 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 placeholder attributes in pluralization strings. These placeholders may be replaced by passing an array as the third argument to the trans_choicefunction: 'minutes_ago' => '{1} :value minute ago|[2,*] :value minutes ago', echo trans_choice('time.minutes_ago', 5, ['value' => 5]); If you would like to display the integer value that was passed to the trans_choicefunction, you may use the :count placeholder: 'apples' => '{0} There are none|{1} There is one|[2,*] There are :count', 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.
Routing [ Rate Limiting ] { throttle middleware, Dynamic Rate Limiting }
Laravel includes a middleware to rate limit access to routes within your application. To get started, assign the throttle middleware to a route or a group of routes. The throttle middleware accepts two parameters that determine the maximum number of requests that can be made in a given number of minutes. For example, let's specify that an authenticated user may access the following group of routes 60 times per minute: Route::middleware('auth:api', 'throttle:60,1')->group(function () { Route::get('/user', function () { // }); }); Dynamic Rate Limiting You may specify a dynamic request maximum based on an attribute of the authenticated User model. For example, if your User model contains a rate_limitattribute, you may pass the name of the attribute to the throttle middleware so that it is used to calculate the maximum request count: Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () { Route::get('/user', function () { // }); });
Frontend [ Asset Compilation ] { Node.js and NPM, npm install, npm run dev, npm run production, npm run watch, npm run watch-poll, mix.less(), mix.sass(), mix.stylus(), mix.styles(), sourceMaps(), mix.js(), extract(['vue']), mix.react(), mix.scripts(), mix.babel(), mix.webpackConfig(), mix.copy(), mix.copyDirectory(), version(), mix.inProduction(), mix.browserSync(); process.env.MIX_SENTRY_DSN_PUBLIC, mix.disableNotifications() }
Laravel Mix provides a fluent API for defining Webpack build steps for your Laravel application using several common CSS and JavaScript pre-processors. Through simple method chaining, you can fluently define your asset pipeline Installing Node Before triggering Mix, you must first ensure that Node.js and NPM are installed on your machine. Running Mix Mix is a configuration layer on top of Webpack, so to run your Mix tasks you only need to execute one of the NPM scripts that is included with the default Laravel package.jsonfile: // Run all Mix tasks... npm run dev // Run all Mix tasks and minify output... npm run production Watching Assets For Changes The npm run watch command will continue running in your terminal and watch all relevant files for changes. Webpack will then automatically recompile your assets when it detects a change: npm run watch You may find that in certain environments Webpack isn't updating when your files change. If this is the case on your system, consider using the watch-poll command: npm run watch-poll Working With Stylesheets The webpack.mix.js file is your entry point for all asset compilation. Think of it as a light configuration wrapper around Webpack. Mix tasks can be chained together to define exactly how your assets should be compiled Less The less method may be used to compile Less into CSS. Let's compile our primary app.less file to public/css/app.css. mix.less('resources/less/app.less', 'public/css'); Multiple calls to the less method may be used to compile multiple files: mix.less('resources/less/app.less', 'public/css') .less('resources/less/admin.less', 'public/css'); If you wish to customize the file name of the compiled CSS, you may pass a full file path as the second argument to the less method: mix.less('resources/less/app.less', 'public/stylesheets/styles.css'); If you need to override the underlying Less plug-in options, you may pass an object as the third argument to mix.less(): mix.less('resources/less/app.less', 'public/css', { strictMath: true }); Sass The sass method allows you to compile Sass into CSS. You may use the method like so: mix.sass('resources/sass/app.scss', 'public/css'); Again, like the less method, you may compile multiple Sass files into their own respective CSS files and even customize the output directory of the resulting CSS: mix.sass('resources/sass/app.sass', 'public/css') .sass('resources/sass/admin.sass', 'public/css/admin'); Additional Node-Sass plug-in options may be provided as the third argument: mix.sass('resources/sass/app.sass', 'public/css', { precision: 5 }); Stylus Similar to Less and Sass, the stylus method allows you to compile Stylus into CSS: mix.stylus('resources/stylus/app.styl', 'public/css'); You may also install additional Stylus plug-ins, such as Rupture. First, install the plug-in in question through NPM (npm install rupture) and then require it in your call to mix.stylus(): mix.stylus('resources/stylus/app.styl', 'public/css', { use: [ require('rupture')() ] }); PostCSS PostCSS, a powerful tool for transforming your CSS, is included with Laravel Mix out of the box. By default, Mix leverages the popular Autoprefixer plug-in to automatically apply all necessary CSS3 vendor prefixes. However, you're free to add any additional plug-ins that are appropriate for your application. First, install the desired plug-in through NPM and then reference it in your webpack.mix.js file: mix.sass('resources/sass/app.scss', 'public/css') .options({ postCss: [ require('postcss-css-variables')() ] }); Plain CSS If you would just like to concatenate some plain CSS stylesheets into a single file, you may use the styles method. mix.styles([ 'public/css/vendor/normalize.css', 'public/css/vendor/videojs.css' ], 'public/css/all.css'); URL Processing Because Laravel Mix is built on top of Webpack, it's important to understand a few Webpack concepts. For CSS compilation, Webpack will rewrite and optimize any url()calls within your stylesheets. While this might initially sound strange, it's an incredibly powerful piece of functionality. Imagine that we want to compile Sass that includes a relative URL to an image: .example { background: url('../images/example.png'); } Absolute paths for any given url() will be excluded from URL-rewriting. For example, url('/images/thing.png') or url('http://example.com/images/thing.png') won't be modified. By default, Laravel Mix and Webpack will find example.png, copy it to your public/imagesfolder, and then rewrite the url() within your generated stylesheet. As such, your compiled CSS will be: .example { background: url(/images/example.png?d41d8cd98f00b204e9800998ecf8427e); } As useful as this feature may be, it's possible that your existing folder structure is already configured in a way you like. If this is the case, you may disable url() rewriting like so: mix.sass('resources/app/app.scss', 'public/css') .options({ processCssUrls: false }); With this addition to your webpack.mix.js file, Mix will no longer match any url() or copy assets to your public directory. In other words, the compiled CSS will look just like how you originally typed it: .example { background: url("../images/thing.png"); } Source Maps Though disabled by default, source maps may be activated by calling the mix.sourceMaps() method in your webpack.mix.js file. Though it comes with a compile/performance cost, this will provide extra debugging information to your browser's developer tools when using compiled assets. mix.js('resources/js/app.js', 'public/js') .sourceMaps(); Working With JavaScript Mix provides several features to help you work with your JavaScript files, such as compiling ECMAScript 2015, module bundling, minification, and concatenating plain JavaScript files. Even better, this all works seamlessly, without requiring an ounce of custom configuration: mix.js('resources/js/app.js', 'public/js'); With this single line of code, you may now take advantage of: ES2015 syntax, Modules Compilation of .vue files Minification for production environments. Vendor Extraction One potential downside to bundling all application-specific JavaScript with your vendor libraries is that it makes long-term caching more difficult. For example, a single update to your application code will force the browser to re-download all of your vendor libraries even if they haven't changed. If you intend to make frequent updates to your application's JavaScript, you should consider extracting all of your vendor libraries into their own file. This way, a change to your application code will not affect the caching of your large vendor.js file. Mix's extract method makes this a breeze: mix.js('resources/js/app.js', 'public/js') .extract(['vue']) The extract method accepts an array of all libraries or modules that you wish to extract into a vendor.js file. Using the above snippet as an example, Mix will generate the following files: public/js/manifest.js: The Webpack manifest runtime public/js/vendor.js: Your vendor libraries public/js/app.js: Your application code To avoid JavaScript errors, be sure to load these files in the proper order React Mix can automatically install the Babel plug-ins necessary for React support. To get started, replace your mix.js() call with mix.react(): mix.react('resources/js/app.jsx', 'public/js'); Behind the scenes, Mix will download and include the appropriate babel-preset-reactBabel plug-in. Vanilla JS Similar to combining stylesheets with mix.styles(), you may also combine and minify any number of JavaScript files with the scripts() method: mix.scripts([ 'public/js/admin.js', 'public/js/dashboard.js' ], 'public/js/all.js'); This option is particularly useful for legacy projects where you don't require Webpack compilation for your JavaScript. A slight variation of mix.scripts() is mix.babel(). Its method signature is identical to scripts; however, the concatenated file will receive Babel compilation, which translates any ES2015 code to vanilla JavaScript that all browsers will understand. Custom Webpack Configuration Behind the scenes, Laravel Mix references a pre-configured webpack.config.js file to get you up and running as quickly as possible. Occasionally, you may need to manually modify this file. You might have a special loader or plug-in that needs to be referenced, or maybe you prefer to use Stylus instead of Sass. In such instances, you have two choices: Merging Custom Configuration Mix provides a useful webpackConfig method that allows you to merge any short Webpack configuration overrides. This is a particularly appealing choice, as it doesn't require you to copy and maintain your own copy of the webpack.config.js file. The webpackConfig method accepts an object, which should contain any Webpack-specific configuration that you wish to apply. mix.webpackConfig({ resolve: { modules: [ path.resolve(__dirname, 'vendor/laravel/spark/resources/assets/js') ] } }); Custom Configuration Files If you would like to completely customize your Webpack configuration, copy the node_modules/laravel-mix/setup/webpack.config.js file to your project's root directory. Next, point all of the --config references in your package.json file to the newly copied configuration file. If you choose to take this approach to customization, any future upstream updates to Mix's webpack.config.js must be manually merged into your customized file. Copying Files & Directories The copy method may be used to copy files and directories to new locations. This can be useful when a particular asset within your node_modules directory needs to be relocated to your public folder. mix.copy('node_modules/foo/bar.css', 'public/css/bar.css'); When copying a directory, the copy method will flatten the directory's structure. To maintain the directory's original structure, you should use the copyDirectory method instead: mix.copyDirectory('resources/img', 'public/img'); Versioning / Cache Busting Many developers suffix their compiled assets with a timestamp or unique token to force browsers to load the fresh assets instead of serving stale copies of the code. Mix can handle this for you using the version method. The version method will automatically append a unique hash to the filenames of all compiled files, allowing for more convenient cache busting: mix.js('resources/js/app.js', 'public/js') .version(); After generating the versioned file, you won't know the exact file name. So, you should use Laravel's global mix function within your views to load the appropriately hashed asset. The mix function will automatically determine the current name of the hashed file src="{{ mix('/js/app.js') }}" Because versioned files are usually unnecessary in development, you may instruct the versioning process to only run during npm run production: mix.js('resources/js/app.js', 'public/js'); if (mix.inProduction()) { mix.version(); } Browsersync Reloading BrowserSync can automatically monitor your files for changes, and inject your changes into the browser without requiring a manual refresh. You may enable support by calling the mix.browserSync() method: mix.browserSync('my-domain.test'); // Or... // https://browsersync.io/docs/options mix.browserSync({ proxy: 'my-domain.test' }); You may pass either a string (proxy) or object (BrowserSync settings) to this method. Next, start Webpack's dev server using the npm run watch command. Now, when you modify a script or PHP file, watch as the browser instantly refreshes the page to reflect your changes. Environment Variables You may inject environment variables into Mix by prefixing a key in your .env file with MIX_: MIX_SENTRY_DSN_PUBLIC=http://example.com After the variable has been defined in your .env file, you may access via the process.env object. If the value changes while you are running a watch task, you will need to restart the task: process.env.MIX_SENTRY_DSN_PUBLIC Notifications When available, Mix will automatically display OS notifications for each bundle. This will give you instant feedback, as to whether the compilation was successful or not. However, there may be instances when you'd prefer to disable these notifications. One such example might be triggering Mix on your production server. Notifications may be deactivated, via the disableNotifications method. mix.disableNotifications();
File Storage [ Configuration / Drivers ] { FlysystemPHP package by Frank de Jonge; config/filesystems.php; public disk uses the local driver and stores these files in storage/app/public; symbolic link from public/storage to storage/app/public; SFTP: league/flysystem-sftp ~1.0; Amazon S3: league/flysystem-aws-s3-v3 ~1.0; Rackspace: league/flysystem-rackspace ~1.0; CachedAdapter: league/flysystem-cached-adapter ~1.0; }
Laravel provides a powerful filesystem abstraction thanks to the wonderful FlysystemPHP 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. 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. You may configure as many disks as you like, and may even have multiple disks that use the same driver. 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 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'); 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'); Driver Prerequisites Composer Packages Before using the SFTP, S3, or Rackspace drivers, you will need to install the appropriate package via Composer: SFTP: league/flysystem-sftp ~1.0 Amazon S3: league/flysystem-aws-s3-v3 ~1.0 Rackspace: league/flysystem-rackspace ~1.0 An absolute must for performance is to use a cached adapter. You will need an additional package for this: CachedAdapter: league/flysystem-cached-adapter ~1.0 S3 Driver Configuration The S3 driver configuration information is located in your config/filesystems.phpconfiguration 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. 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, ], SFTP Driver Configuration Laravel's Flysystem integrations works great with SFTP; however, a sample configuration is not included with the framework's default filesystems.phpconfiguration file. If you need to configure a SFTP filesystem, you may use the example configuration below: 'sftp' => [ 'driver' => 'sftp', 'host' => 'example.com', 'username' => 'your-username', 'password' => 'your-password', // Settings for SSH key based authentication... // 'privateKey' => '/path/to/privateKey', // 'password' => 'encryption-password', // Optional SFTP Settings... // 'port' => 22, // 'root' => '', // 'timeout' => 30, ], Rackspace Driver Configuration Laravel's Flysystem integrations works great with Rackspace; however, a sample configuration is not included with the framework's default filesystems.phpconfiguration 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', ], Caching To enable caching for a given disk, you may add a cache directive to the disk's configuration options. The cache option should be an array of caching options containing the disk name, the expire time in seconds, and the cache prefix: 's3' => [ 'driver' => 's3', // Other Disk Options... 'cache' => [ 'store' => 'memcached', 'expire' => 600, 'prefix' => 'cache-prefix', ], ],
Responses [ Redirects ] { redirect('home/dashboard'), back()->withInput(), redirect()->route('profile', ['id' => 1]), Parameters Via Eloquent Models, redirect()->action('HomeController@index'), redirect()->away('https://www.google.com'), }
Redirect responses are instances of the Illuminate\Http\RedirectResponse class, and contain the proper headers needed to redirect the user to another URL. There are several ways to generate a RedirectResponse instance. The simplest method is to use the global redirect helper: Route::get('dashboard', function () { return redirect('home/dashboard'); }); Sometimes you may wish to redirect the user to their previous location, such as when a submitted form is invalid. You may do so by using the global back helper function. Since this feature utilizes the session, make sure the route calling the back function is using the web middleware group or has all of the session middleware applied: Route::post('user/profile', function () { // Validate the request... return back()->withInput(); }); Redirecting To Named Routes When you call the redirect helper with no parameters, an instance of Illuminate\Routing\Redirector is returned, allowing you to call any method on the Redirector instance. For example, to generate a RedirectResponse to a named route, you may use the route method: return redirect()->route('login'); If your route has parameters, you may pass them as the second argument to the routemethod: // For a route with the following URI: profile/{id} return redirect()->route('profile', ['id' => 1]); If you are redirecting to a route with an "ID" parameter that is being populated from an Eloquent model, you may pass the model itself. The ID will be extracted automatically: // For a route with the following URI: profile/{id} return redirect()->route('profile', [$user]); If you would like to customize the value that is placed in the route parameter, you should override the getRouteKey method on your Eloquent model: /** * Get the value of the model's route key. * * @return mixed */ public function getRouteKey() { return $this->slug; } Redirecting To Controller Actions You may also generate redirects to controller actions. To do so, pass the controller and action name to the action method. Remember, you do not need to specify the full namespace to the controller since Laravel's RouteServiceProvider will automatically set the base controller namespace: return redirect()->action('HomeController@index'); If your controller route requires parameters, you may pass them as the second argument to the action method: return redirect()->action( 'UserController@profile', ['id' => 1] ); Redirecting To External Domains Sometimes you may need to redirect to a domain outside of your application. You may do so by calling the away method, which creates a RedirectResponse without any additional URL encoding, validation, or verification: return redirect()->away('https://www.google.com');
Sessions [ Storing Data ] { $request->session()->put('key', 'value'); session(['key' => 'value']); $request->session()->push('user.teams', 'developers'); $value = $request->session()->pull('key', 'default');}
To store data in the session, you will typically use the put method or the session helper // Via a request instance... $request->session()->put('key', 'value'); // Via the global helper... session(['key' => 'value']); Pushing To Array Session Values The push method may be used to push a new value onto a session value that is an array. For example, if the user.teams key contains an array of team names, you may push a new value onto the array like so: $request->session()->push('user.teams', 'developers'); Retrieving & Deleting An Item The pull method will retrieve and delete an item from the session in a single statement: $value = $request->session()->pull('key', 'default');
Package Development [ Commands ] { if ($this->app->runningInConsole()) { $this->commands([ FooCommand::class, BarCommand::class, ]); } }
To register your package's Artisan commands with Laravel, you may use the commandsmethod. This method expects an array of command class names. Once the commands have been registered, you may execute them using the Artisan CLI: /** * Bootstrap the application services. * * @return void */ public function boot() { if ($this->app->runningInConsole()) { $this->commands([ FooCommand::class, BarCommand::class, ]); } }
PHP [ Autoloading Standards ]
todo
PHP [ Composer ]
todo
PHP [ Version 7.1+ ]
todo
Architecture [ HTTP Verbs ]
The router allows you to register routes that respond to any HTTP verb: Route::get($uri,$callback); Route::post($uri, $callback); Route::put($uri, $callback); Route::patch($uri, $callback); Route::delete($uri, $callback); Route::options($uri, $callback); Sometimes you may need to register a route that responds to multiple HTTP verbs. You may do so using the match method. Or, you may even register a route that responds to all HTTP verbs using the any method: Route::match(['get', 'post'], '/', function () { // }); Route::any('foo', function () { // });
Controllers [ 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' ]); Actions Handled By Resource Controller Verb URI ActionRoute 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 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 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 Blade directive can create this field for you: <form action="/foo/bar" method="POST"> @method('PUT') </form> 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('photos', 'PhotoController')->only([ 'index', 'show' ]); Route::resource('photos', 'PhotoController')->except([ 'create', 'store', 'update', 'destroy' ]); 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('photos', 'PhotoController'); You may register many API resource controllers at once by passing an array to the apiResources method: Route::apiResources([ 'photos' => 'PhotoController', 'posts' => 'PostController' ]); To quickly generate an API resource controller that does not include the create or editmethods, use the --api switch when executing the make:controller command: php artisan make:controller API/PhotoController --api 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('photos', 'PhotoController')->names([ 'create' => 'photos.build' ]); 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 using the parameters method. The array passed into the parameters method should be an associative array of resource names and parameter names: Route::resource('users', 'AdminUserController')->parameters([ 'users' => 'admin_user' ]); The example above generates the following URIs for the resource's show route: /users/{admin_user} 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::resourceVerbsmethod. 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 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'); 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.
Validation [ Error Messages ] { MessageBag, $errors->first('email'); $errors->get('email'); $errors->get('attachments.*'); $errors->all(); $errors->has('email'), Validator::make($input, $rules, $messages); :attribute placeholders; custom message for attribute/rule 'email.required' }
After calling the errors method on a Validator instance, you will receive an Illuminate\Support\MessageBag instance, which has a variety of convenient methods for working with error messages. The $errors variable that is automatically made available to all views is also an instance of the MessageBag class. Retrieving The First Error Message For A Field To retrieve the first error message for a given field, use the first method: $errors = $validator->errors(); echo $errors->first('email'); Retrieving All Error Messages For A Field If you need to retrieve an array of all the messages for a given field, use the getmethod: foreach ($errors->get('email') as $message) { // } If you are validating an array form field, you may retrieve all of the messages for each of the array elements using the * character: foreach ($errors->get('attachments.*') as $message) { // } Retrieving All Error Messages For All Fields To retrieve an array of all messages for all fields, use the all method: foreach ($errors->all() as $message) { // } Determining If Messages Exist For A Field The has method may be used to determine if any error messages exist for a given field: if ($errors->has('email')) { // } Custom Error Messages If needed, you may use custom error messages for validation instead of the defaults. There are several ways to specify custom messages. First, you may pass the custom messages as the third argument to the Validator::make method: $messages = [ 'required' => 'The :attribute field is required.', ]; $validator = Validator::make($input, $rules, $messages); In this example, the :attribute placeholder will be replaced by the actual name of the field under validation. You may also utilize other placeholders in validation messages. For example: $messages = [ 'same' => 'The :attribute and :other must match.', 'size' => 'The :attribute must be exactly :size.', 'between' => 'The :attribute value :input is not between :min - :max.', 'in' => 'The :attribute must be one of the following types: :values', ]; Specifying A Custom Message For A Given Attribute Sometimes you may wish to specify a custom error message only for a specific field. You may do so using "dot" notation. Specify the attribute's name first, followed by the rule: $messages = [ 'email.required' => 'We need to know your e-mail address!', ]; Specifying Custom Messages In Language Files In most cases, you will probably specify your custom messages in a language file instead of passing them directly to the Validator. To do so, add your messages to custom array in the resources/lang/xx/validation.php language file. 'custom' => [ 'email' => [ 'required' => 'We need to know your e-mail address!', ], ], Specifying Custom Attributes In Language Files If you would like the :attribute portion of your validation message to be replaced with a custom attribute name, you may specify the custom name in the attributes array of your resources/lang/xx/validation.php language file: 'attributes' => [ 'email' => 'email address', ], Specifying Custom Values In Language Files Sometimes you may need the :value portion of your validation message to be replaced with a custom representation of the value. For example, consider the following rule that specifies that a credit card number is required if the payment_typehas a value of cc: $request->validate([ 'credit_card_number' => 'required_if:payment_type,cc' ]); If this validation rule fails, it will produce the following error message: The credit card number field is required when payment type is cc. Instead of displaying cc as the payment type value, you may specify a custom value representation in your validation language file by defining a values array: 'values' => [ 'payment_type' => [ 'cc' => 'credit card' ], ], Now if the validation rule fails it will produce the following message: The credit card number field is required when payment type is credit card.
Task Scheduling [ Preventing Task Overlaps ] { withoutOverlapping(); withoutOverlapping(10);}
By default, scheduled tasks will be run even if the previous instance of the task is still running. To prevent this, you may use the withoutOverlapping method: $schedule->command('emails:send')->withoutOverlapping(); In this example, the emails:send Artisan command will be run every minute if it is not already running. The withoutOverlapping method is especially useful if you have tasks that vary drastically in their execution time, preventing you from predicting exactly how long a given task will take. If needed, you may specify how many minutes must pass before the "without overlapping" lock expires. By default, the lock will expire after 24 hours: $schedule->command('emails:send')->withoutOverlapping(10);
Caching [ Cache Tags ] { not supported when using the file or database cache drivers; Cache::tags(['people', 'artists'])->put('John', $john, $minutes); Cache::tags(['people', 'authors'])->put('Anne', $anne, $minutes); $john = Cache::tags(['people', 'artists'])->get('John'); $anne = Cache::tags(['people', 'authors'])->get('Anne'); Cache::tags(['people', 'authors'])->flush(); Cache::tags('authors')->flush()}
Cache tags are not supported when using the file or database cache drivers. Furthermore, when using multiple tags with caches that are stored "forever", performance will be best with a driver such as memcached, which automatically purges stale records. Storing Tagged Cache Items Cache tags allow you to tag related items in the cache and then flush all cached values that have been assigned a given tag. You may access a tagged cache by passing in an ordered array of tag names. For example, let's access a tagged cache and put value in the cache: Cache::tags(['people', 'artists'])->put('John', $john, $minutes); Cache::tags(['people', 'authors'])->put('Anne', $anne, $minutes); 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'); 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 Annewould be removed, but not John: Cache::tags('authors')->flush();
Websockets [ Client Events ] { Echo.private('chat') .whisper('typing', { name: this.user.name }); Echo.private('chat') .listenForWhisper('typing', (e) => { console.log(e.name); }); }
Client Events When using Pusher Channels, you must enable the "Client Events" option in the "App Settings" section of your application dashboard in order to send client events. Sometimes you may wish to broadcast an event to other connected clients without hitting your Laravel application at all. This can be particularly useful for things like "typing" notifications, where you want to alert users of your application that another user is typing a message on a given screen. To broadcast client events, you may use Echo's whisper method: 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); });
Controllers [ Route Caching ] { route:cache, route:clear }
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
Package Development [ Resources ] { $this->publishes([ __DIR__.'/path/to/config/courier.php' => config_path('courier.php'), ]); $value = config('courier.option'); You should not define Closures in your configuration files; public function register() { $this->mergeConfigFrom( __DIR__.'/path/to/config/courier.php', 'courier' );} public function boot() { $this->loadRoutesFrom(__DIR__.'/routes.php'); }; public function boot() { $this->loadMigrationsFrom(__DIR__.'/path/to/migrations'); }; public function boot() { $this->loadFactoriesFrom(__DIR__.'/path/to/factories'); }; factory(Package\Namespace\Model::class)->create(); public function boot() { $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier'); }; echo trans('courier::messages.welcome'); $this->publishes([ __DIR__.'/path/to/translations' => resource_path('lang/vendor/courier'), ]); public function boot() { $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier'); } Route::get('admin', function () { return view('courier::admin'); }); resources/views/vendor/courier; $this->publishes([ __DIR__.'/path/to/views' => resource_path('views/vendor/courier'), ]); $this->loadViewComponentsAs('courier', [ Alert::class, Button::class, ]); }
Configuration Typically, you will need to publish your package's configuration file to the application's own config directory. This will allow users of your package to easily override your default configuration options. To allow your configuration files to be published, call the publishes method from the boot method of your service provider: /** * Bootstrap any application services. * * @return void */ public function boot() { $this->publishes([ __DIR__.'/path/to/config/courier.php' => config_path('courier.php'), ]); } Now, when users of your package execute Laravel's vendor:publish command, your file will be copied to the specified publish location. Once your configuration has been published, its values may be accessed like any other configuration file: $value = config('courier.option'); You should not define Closures in your configuration files. They can not be serialized correctly when users execute the config:cache Artisan command. Default Package Configuration You may also merge your own package configuration file with the application's published copy. This will allow your users to define only the options they actually want to override in the published copy of the configuration. To merge the configurations, use the mergeConfigFrom method within your service provider's register method: /** * Register any application services. * * @return void */ public function register() { $this->mergeConfigFrom( __DIR__.'/path/to/config/courier.php', 'courier' ); } This method only merges the first level of the configuration array. If your users partially define a multi-dimensional configuration array, the missing options will not be merged. Routes If your package contains routes, you may load them using the loadRoutesFrom method. This method will automatically determine if the application's routes are cached and will not load your routes file if the routes have already been cached: /** * Bootstrap any application services. * * @return void */ public function boot() { $this->loadRoutesFrom(__DIR__.'/routes.php'); } Migrations If your package contains database migrations, you may use the loadMigrationsFrommethod to inform Laravel how to load them. The loadMigrationsFrom method accepts the path to your package's migrations as its only argument: /** * Bootstrap any application services. * * @return void */ public function boot() { $this->loadMigrationsFrom(__DIR__.'/path/to/migrations'); } Once your package's migrations have been registered, they will automatically be run when the php artisan migrate command is executed. You do not need to export them to the application's main database/migrations directory. Factories If your package contains database factories, you may use the loadFactoriesFrommethod to inform Laravel how to load them. The loadFactoriesFrom method accepts the path to your package's factories as its only argument: /** * Bootstrap any application services. * * @return void */ public function boot() { $this->loadFactoriesFrom(__DIR__.'/path/to/factories'); } Once your package's factories have been registered, you can use them in your application: factory(Package\Namespace\Model::class)->create(); Translations If your package contains translation files, you may use the loadTranslationsFrommethod to inform Laravel how to load them. For example, if your package is named courier, you should add the following to your service provider's boot method: /** * Bootstrap any application services. * * @return void */ public function boot() { $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier'); } Package translations are referenced using the package::file.line syntax convention. So, you may load the courier package's welcome line from the messages file like so: echo trans('courier::messages.welcome'); Publishing Translations If you would like to publish your package's translations to the application's resources/lang/vendor directory, you may use the service provider's publishes method. The publishes method accepts an array of package paths and their desired publish locations. For example, to publish the translation files for the courier package, you may do the following: /** * Bootstrap any application services. * * @return void */ public function boot() { $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier'); $this->publishes([ __DIR__.'/path/to/translations' => resource_path('lang/vendor/courier'), ]); } Now, when users of your package execute Laravel's vendor:publish Artisan command, your package's translations will be published to the specified publish location. Views To register your package's views with Laravel, you need to tell Laravel where the views are located. You may do this using the service provider's loadViewsFrom method. The loadViewsFrom method accepts two arguments: the path to your view templates and your package's name. For example, if your package's name is courier, you would add the following to your service provider's boot method: /** * Bootstrap any application services. * * @return void */ public function boot() { $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier'); } Package views are referenced using the package::view syntax convention. So, once your view path is registered in a service provider, you may load the admin view from the courier package like so: Route::get('admin', function () { return view('courier::admin'); }); Overriding Package Views When you use the loadViewsFrom method, Laravel actually registers two locations for your views: the application's resources/views/vendor directory and the directory you specify. So, using the courier example, Laravel will first check if a custom version of the view has been provided by the developer in resources/views/vendor/courier. Then, if the view has not been customized, Laravel will search the package view directory you specified in your call to loadViewsFrom. This makes it easy for package users to customize / override your package's views. Publishing Views If you would like to make your views available for publishing to the application's resources/views/vendor directory, you may use the service provider's publishes method. The publishes method accepts an array of package view paths and their desired publish locations: /** * Bootstrap any application services. * * @return void */ public function boot() { $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier'); $this->publishes([ __DIR__.'/path/to/views' => resource_path('views/vendor/courier'), ]); } Now, when users of your package execute Laravel's vendor:publish Artisan command, your package's views will be copied to the specified publish location. View Components If your package contains view components, you may use the loadViewComponentsAsmethod to inform Laravel how to load them. The loadViewComponentsAs method accepts two arguments: the tag prefix for your view components and an array of your view components class. For example, if your package's prefix is courier and you have Alertand Button view components, you would add the following to your service provider's boot method: /** * Bootstrap any application services. * * @return void */ public function boot() { $this->loadViewComponentsAs('courier', [ Alert::class, Button::class, ]); } Once your view components are registered in a service provider, you may reference them in your view like so: <x-courier-alert /> <x-courier-button />
Artisan Console [ Command I/O ] { email:send {user}, email:send {user?}, email:send {user=foo}, email:send {user} {--queue}, email:send {user} {--queue=}, email:send {user} {--queue=default}, email:send {user} {--Q|queue}, email:send {user*}, email:send {user} {--id=*}, 'email:send {user : The ID of the user} {--queue= : Whether the job should be queued}', $this->argument('user'); $this->arguments(); $this->option('queue'); $this->options(); $this->ask('What is your name?'); $this->secret('What is the password?'); $this->confirm('Do you wish to continue?'); $this->anticipate('What is your name?', ['Taylor', 'Dayle']); $this->anticipate('What is your name?', function ($input) { // Return auto-completion options... }); $this->choice('What is your name?', ['Taylor', 'Dayle'], $defaultIndex); $this->choice( 'What is your name?', ['Taylor', 'Dayle'], $defaultIndex, $maxAttempts = null, $allowMultipleSelections = false ); $this->info('Display this on the screen'); $this->error('Something went wrong!'); $this->line('Display this on the screen'); $this->table($headers, $users); $this->output->createProgressBar(count($users)); $bar->start(); $bar->advance(); $bar->finish();}
Defining Input Expectations When writing console commands, it is common to gather input from the user through arguments or options. Laravel makes it very convenient to define the input you expect from the user using the signature property on your commands. The signature property allows you to define the name, arguments, and options for the command in a single, expressive, route-like syntax. Arguments All user supplied arguments and options are wrapped in curly braces. In the following example, the command defines one required argument: user: /** * 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} 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 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} 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} 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 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}'; Command I/O Retrieving Input While your command is executing, you will obviously need to access the values for the arguments and options accepted by your command. To do so, you may use the argument and option methods: /** * 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. 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?'); 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?')) { // } 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']); Alternatively, you may pass a Closure as the second argument to the anticipatemethod. The Closure will be called each time the user types an input character. The Closure should accept a string parameter containing the user's input so far, and return an array of options for auto-completion: $name = $this->anticipate('What is your name?', function ($input) { // Return auto-completion options... }); Multiple Choice Questions If you need to give the user a predefined set of choices, you may use the choicemethod. 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); In addition, the choice method accepts optional fourth and fifth arguments for determining the maximum number of attempts to select a valid response and whether multiple selections are permitted: $name = $this->choice( 'What is your name?', ['Taylor', 'Dayle'], $defaultIndex, $maxAttempts = null, $allowMultipleSelections = false ); Writing Output To send output to the console, use the line, info, comment, question and errormethods. 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'); 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); 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)); $bar->start(); foreach ($users as $user) { $this->performTask($user); $bar->advance(); } $bar->finish();
Events [ Subscribing to Events ] { 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; 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 }
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 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' ); } } 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: 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', ]; }
Queues [ Creating / Dispatching Jobs ] { app/Jobs; php artisan make:job ProcessPodcast; Illuminate\Contracts\Queue\ShouldQueue; handle method which is called when the job is processed by the queue; SerializesModels trait that the job is using, Eloquent models will be gracefully serialized and unserialized when the job is processing. If your queued job accepts an Eloquent model in its constructor, only the identifier for the model will be serialized onto the queue; $this->app->bindMethod(ProcessPodcast::class.'@handle', function ($job, $app) { return $job->handle($app->make(AudioProcessor::class)); }); Binary data, such as raw image contents, should be passed through the base64_encode function before being passed to a queued job; ProcessPodcast::dispatch($podcast); ProcessPodcast::dispatch($podcast) ->delay(now()->addMinutes(10)); ProcessPodcast::dispatchNow($podcast); ProcessPodcast::withChain([ new OptimizePodcast, new ReleasePodcast ])->dispatch(); ProcessPodcast::withChain([ new OptimizePodcast, new ReleasePodcast ])->dispatch()->allOnConnection('redis')->allOnQueue('podcasts'); ProcessPodcast::dispatch($podcast)->onQueue('processing'); ProcessPodcast::dispatch($podcast)->onConnection('sqs'); ProcessPodcast::dispatch($podcast) ->onConnection('sqs') ->onQueue('processing'); php artisan queue:work --tries=3; public $tries = 5; public function retryUntil() { return now()->addSeconds(5); }; php artisan queue:work --timeout=30; public $timeout = 120; Redis::throttle('key')->allow(10)->every(60)->then(function () { // Job logic... }, function () { // Could not obtain lock... return $this->release(10); }); Redis::funnel('key')->limit(1)->then(function () { // Job logic... }, function () { // Could not obtain lock... return $this->release(10); }); $podcast = App\Podcast::find(1); dispatch(function () use ($podcast) { $podcast->publish(); }); Using the before and after methods on the Queue facade, you may specify callbacks to be executed before or after a queued job is processed. Using the looping method on the Queue facade, you may specify callbacks that execute before the worker attempts to fetch a job from a queue. }
Generating Job Classes By default, all of the queueable jobs for your application are stored in the app/Jobsdirectory. If the app/Jobs directory doesn't exist, it will be created when you run the make:job Artisan command. You may generate a new queued job using the Artisan CLI: php artisan make:job ProcessPodcast The generated class will implement the Illuminate\Contracts\Queue\ShouldQueueinterface, indicating to Laravel that the job should be pushed onto the queue to run asynchronously. Class Structure Job classes are very simple, normally containing only a handle method which is called when the job is processed by the queue. To get started, let's take a look at an example job class. In this example, we'll pretend we manage a podcast publishing service and need to process the uploaded podcast files before they are published: namespace App\Jobs; use App\Podcast; use App\AudioProcessor; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; class ProcessPodcast implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $podcast; /** * Create a new job instance. * * @param Podcast $podcast * @return void */ public function __construct(Podcast $podcast) { $this->podcast = $podcast; } /** * Execute the job. * * @param AudioProcessor $processor * @return void */ public function handle(AudioProcessor $processor) { // Process uploaded podcast... } } In this example, note that we were able to pass an Eloquent model directly into the queued job's constructor. Because of the SerializesModels trait that the job is using, Eloquent models will be gracefully serialized and unserialized when the job is processing. If your queued job accepts an Eloquent model in its constructor, only the identifier for the model will be serialized onto the queue. When the job is actually handled, the queue system will automatically re-retrieve the full model instance from the database. It's all totally transparent to your application and prevents issues that can arise from serializing full Eloquent model instances. The handle method is called when the job is processed by the queue. Note that we are able to type-hint dependencies on the handle method of the job. The Laravel service container automatically injects these dependencies. If you would like to take total control over how the container injects dependencies into the handle method, you may use the container's bindMethod method. The bindMethodmethod accepts a callback which receives the job and the container. Within the callback, you are free to invoke the handle method however you wish. Typically, you should call this method from a service provider: use App\Jobs\ProcessPodcast; $this->app->bindMethod(ProcessPodcast::class.'@handle', function ($job, $app) { return $job->handle($app->make(AudioProcessor::class)); }); Binary data, such as raw image contents, should be passed through the base64_encode function before being passed to a queued job. Otherwise, the job may not properly serialize to JSON when being placed on the queue. Dispatching Jobs Once you have written your job class, you may dispatch it using the dispatch method on the job itself. The arguments passed to the dispatch method will be given to the job's constructor: namespace App\Http\Controllers; use App\Jobs\ProcessPodcast; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class PodcastController extends Controller { /** * Store a new podcast. * * @param Request $request * @return Response */ public function store(Request $request) { // Create podcast... ProcessPodcast::dispatch($podcast); } } Delayed Dispatching If you would like to delay the execution of a queued job, you may use the delay method when dispatching a job. For example, let's specify that a job should not be available for processing until 10 minutes after it has been dispatched: namespace App\Http\Controllers; use App\Jobs\ProcessPodcast; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class PodcastController extends Controller { /** * Store a new podcast. * * @param Request $request * @return Response */ public function store(Request $request) { // Create podcast... ProcessPodcast::dispatch($podcast) ->delay(now()->addMinutes(10)); } } The Amazon SQS queue service has a maximum delay time of 15 minutes. Synchronous Dispatching If you would like to dispatch a job immediately (synchronously), you may use the dispatchNow method. When using this method, the job will not be queued and will be run immediately within the current process: use Illuminate\Http\Request; use App\Jobs\ProcessPodcast; use App\Http\Controllers\Controller; class PodcastController extends Controller { /** * Store a new podcast. * * @param Request $request * @return Response */ public function store(Request $request) { // Create podcast... ProcessPodcast::dispatchNow($podcast); } } Job Chaining Job chaining allows you to specify a list of queued jobs that should be run in sequence. If one job in the sequence fails, the rest of the jobs will not be run. To execute a queued job chain, you may use the withChain method on any of your dispatchable jobs: ProcessPodcast::withChain([ new OptimizePodcast, new ReleasePodcast ])->dispatch(); Deleting jobs using the $this->delete() method will not prevent chained jobs from being processed. The chain will only stop executing if a job in the chain fails. Chain Connection & Queue If you would like to specify the default connection and queue that should be used for the chained jobs, you may use the allOnConnection and allOnQueue methods. These methods specify the queue connection and queue name that should be used unless the queued job is explicitly assigned a different connection / queue: ProcessPodcast::withChain([ new OptimizePodcast, new ReleasePodcast ])->dispatch()->allOnConnection('redis')->allOnQueue('podcasts'); Customizing The Queue & Connection Dispatching To A Particular Queue By pushing jobs to different queues, you may "categorize" your queued jobs and even prioritize how many workers you assign to various queues. Keep in mind, this does not push jobs to different queue "connections" as defined by your queue configuration file, but only to specific queues within a single connection. To specify the queue, use the onQueue method when dispatching the job: namespace App\Http\Controllers; use App\Jobs\ProcessPodcast; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class PodcastController extends Controller { /** * Store a new podcast. * * @param Request $request * @return Response */ public function store(Request $request) { // Create podcast... ProcessPodcast::dispatch($podcast)->onQueue('processing'); } } Dispatching To A Particular Connection If you are working with multiple queue connections, you may specify which connection to push a job to. To specify the connection, use the onConnection method when dispatching the job: namespace App\Http\Controllers; use App\Jobs\ProcessPodcast; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class PodcastController extends Controller { /** * Store a new podcast. * * @param Request $request * @return Response */ public function store(Request $request) { // Create podcast... ProcessPodcast::dispatch($podcast)->onConnection('sqs'); } } You may chain the onConnection and onQueue methods to specify the connection and the queue for a job: ProcessPodcast::dispatch($podcast) ->onConnection('sqs') ->onQueue('processing'); Specifying Max Job Attempts / Timeout Values Max Attempts One approach to specifying the maximum number of times a job may be attempted is via the --tries switch on the Artisan command line: php artisan queue:work --tries=3 However, you may take a more granular approach by defining the maximum number of attempts on the job class itself. If the maximum number of attempts is specified on the job, it will take precedence over the value provided on the command line: namespace App\Jobs; class ProcessPodcast implements ShouldQueue { /** * The number of times the job may be attempted. * * @var int */ public $tries = 5; } Time Based Attempts As an alternative to defining how many times a job may be attempted before it fails, you may define a time at which the job should timeout. This allows a job to be attempted any number of times within a given time frame. To define the time at which a job should timeout, add a retryUntil method to your job class: /** * Determine the time at which the job should timeout. * * @return \DateTime */ public function retryUntil() { return now()->addSeconds(5); } You may also define a retryUntil method on your queued event listeners. Timeout The timeout feature is optimized for PHP 7.1+ and the pcntlPHP extension. Likewise, the maximum number of seconds that jobs can run may be specified using the --timeout switch on the Artisan command line: php artisan queue:work --timeout=30 However, you may also define the maximum number of seconds a job should be allowed to run on the job class itself. If the timeout is specified on the job, it will take precedence over any timeout specified on the command line: namespace App\Jobs; class ProcessPodcast implements ShouldQueue { /** * The number of seconds the job can run before timing out. * * @var int */ public $timeout = 120; } Rate Limiting This feature requires that your application can interact with a Redis server. If your application interacts with Redis, you may throttle your queued jobs by time or concurrency. This feature can be of assistance when your queued jobs are interacting with APIs that are also rate limited. For example, using the throttle method, you may throttle a given type of job to only run 10 times every 60 seconds. If a lock can not be obtained, you should typically release the job back onto the queue so it can be retried later: Redis::throttle('key')->allow(10)->every(60)->then(function () { // Job logic... }, function () { // Could not obtain lock... return $this->release(10); }); In the example above, the key may be any string that uniquely identifies the type of job you would like to rate limit. For example, you may wish to construct the key based on the class name of the job and the IDs of the Eloquent models it operates on. Releasing a throttled job back onto the queue will still increment the job's total number of attempts. Alternatively, you may specify the maximum number of workers that may simultaneously process a given job. This can be helpful when a queued job is modifying a resource that should only be modified by one job at a time. For example, using the funnel method, you may limit jobs of a given type to only be processed by one worker at a time: Redis::funnel('key')->limit(1)->then(function () { // Job logic... }, function () { // Could not obtain lock... return $this->release(10); }); When using rate limiting, the number of attempts your job will need to run successfully can be hard to determine. Therefore, it is useful to combine rate limiting with time based attempts. Error Handling If an exception is thrown while the job is being processed, the job will automatically be released back onto the queue so it may be attempted again. The job will continue to be released until it has been attempted the maximum number of times allowed by your application. The maximum number of attempts is defined by the --tries switch used on the queue:work Artisan command. Alternatively, the maximum number of attempts may be defined on the job class itself. More information on running the queue worker can be found below. Queueing Closures Instead of dispatching a job class to the queue, you may also dispatch a Closure. This is great for quick, simple tasks that need to be executed outside of the current request cycle: $podcast = App\Podcast::find(1); dispatch(function () use ($podcast) { $podcast->publish(); }); When dispatching Closures to the queue, the Closure's code contents is cryptographically signed so it can not be modified in transit. Job Events Using the before and after methods on the Queue facade, you may specify callbacks to be executed before or after a queued job is processed. These callbacks are a great opportunity to perform additional logging or increment statistics for a dashboard. Typically, you should call these methods from a service provider. For example, we may use the AppServiceProvider that is included with Laravel: namespace App\Providers; use Illuminate\Support\Facades\Queue; use Illuminate\Support\ServiceProvider; use Illuminate\Queue\Events\JobProcessed; use Illuminate\Queue\Events\JobProcessing; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { Queue::before(function (JobProcessing $event) { // $event->connectionName // $event->job // $event->job->payload() }); Queue::after(function (JobProcessed $event) { // $event->connectionName // $event->job // $event->job->payload() }); } /** * Register the service provider. * * @return void */ public function register() { // } } Using the looping method on the Queue facade, you may specify callbacks that execute before the worker attempts to fetch a job from a queue. For example, you might register a Closure to rollback any transactions that were left open by a previously failed job: Queue::looping(function () { while (DB::transactionLevel() > 0) { DB::rollBack(); } });
Notifications [ Creating Notifications ] { notifications should be short, informational messages that notify users of something that occurred in your application; php artisan make:notification InvoicePaid }
In addition to support for sending email, Laravel provides support for sending notifications across a variety of delivery channels, including mail, SMS (via Nexmo), and Slack. Notifications may also be stored in a database so they may be displayed in your web interface. Typically, notifications should be short, informational messages that notify users of something that occurred in your application. For example, if you are writing a billing application, you might send an "Invoice Paid" notification to your users via the email and SMS channels. Creating Notifications In Laravel, each notification is represented by a single class (typically stored in the app/Notifications directory). Don't worry if you don't see this directory in your application, it will be created for you when you run the make:notification Artisan command: php artisan make:notification InvoicePaid This command will place a fresh notification class in your app/Notifications directory. Each notification class contains a via method and a variable number of message building methods (such as toMail or toDatabase) that convert the notification to a message optimized for that particular channel.
Database [ Pagination ] { DB::table('users')->paginate(15); DB::table('users')->simplePaginate(15); App\User::paginate(15); Illuminate\Pagination\Paginator or Illuminate\Pagination\LengthAwarePaginator; Paginator corresponds to the simplePaginate method on the query builder and Eloquent, while the LengthAwarePaginator corresponds to the paginate method $users->links(); The withPath method allows you to customize the URI used by the paginator when generating links; $users->appends(['sort' => 'votes'])->links(); $users->fragment('foo')->links(); $users->onEachSide(5)->links(); Route::get('users', function () { return App\User::paginate(); }); $paginator->links('view.name', ['foo' => 'bar']); Paginator::defaultView('view-name'); Paginator::defaultSimpleView('view-name'); }
In other frameworks, pagination can be very painful. Laravel's paginator is integrated with the query builder and Eloquent ORM and provides convenient, easy-to-use pagination of database results out of the box. The HTML generated by the paginator is compatible with the Bootstrap CSS framework. Basic Usage Paginating Query Builder Results There are several ways to paginate items. The simplest is by using the paginate method on the query builder or an Eloquent query. The paginate method automatically takes care of setting the proper limit and offset based on the current page being viewed by the user. By default, the current page is detected by the value of the page query string argument on the HTTP request. This value is automatically detected by Laravel, and is also automatically inserted into links generated by the paginator. In this example, the only argument passed to the paginate method is the number of items you would like displayed "per page". In this case, let's specify that we would like to display 15 items per page: namespace App\Http\Controllers; use Illuminate\Support\Facades\DB; use App\Http\Controllers\Controller; class UserController extends Controller { /** * Show all of the users for the application. * * @return Response */ public function index() { $users = DB::table('users')->paginate(15); return view('user.index', ['users' => $users]); } } Currently, pagination operations that use a groupBystatement cannot be executed efficiently by Laravel. If you need to use a groupBy with a paginated result set, it is recommended that you query the database and create a paginator manually. "Simple Pagination" If you only need to display simple "Next" and "Previous" links in your pagination view, you may use the simplePaginate method to perform a more efficient query. This is very useful for large datasets when you do not need to display a link for each page number when rendering your view: $users = DB::table('users')->simplePaginate(15); Paginating Eloquent Results You may also paginate Eloquent queries. In this example, we will paginate the Usermodel with 15 items per page. As you can see, the syntax is nearly identical to paginating query builder results: $users = App\User::paginate(15); You may call paginate after setting other constraints on the query, such as whereclauses: $users = User::where('votes', '>', 100)->paginate(15); You may also use the simplePaginate method when paginating Eloquent models: $users = User::where('votes', '>', 100)->simplePaginate(15); Manually Creating A Paginator Sometimes you may wish to create a pagination instance manually, passing it an array of items. You may do so by creating either an Illuminate\Pagination\Paginator or Illuminate\Pagination\LengthAwarePaginator instance, depending on your needs. The Paginator class does not need to know the total number of items in the result set; however, because of this, the class does not have methods for retrieving the index of the last page. The LengthAwarePaginator accepts almost the same arguments as the Paginator; however, it does require a count of the total number of items in the result set. In other words, the Paginator corresponds to the simplePaginate method on the query builder and Eloquent, while the LengthAwarePaginator corresponds to the paginatemethod. When manually creating a paginator instance, you should manually "slice" the array of results you pass to the paginator. If you're unsure how to do this, check out the array_slice PHP function. Displaying Pagination Results When calling the paginate method, you will receive an instance of Illuminate\Pagination\LengthAwarePaginator. When calling the simplePaginate method, you will receive an instance of Illuminate\Pagination\Paginator. These objects provide several methods that describe the result set. In addition to these helpers methods, the paginator instances are iterators and may be looped as an array. So, once you have retrieved the results, you may display the results and render the page links using Blade: <div class="container"> @foreach ($users as $user) {{ $user->name }} @endforeach </div> {{ $users->links() }} The links method will render the links to the rest of the pages in the result set. Each of these links will already contain the proper page query string variable. Remember, the HTML generated by the links method is compatible with the Bootstrap CSS framework. Customizing The Paginator URI The withPath method allows you to customize the URI used by the paginator when generating links. For example, if you want the paginator to generate links like http://example.com/custom/url?page=N, you should pass custom/url to the withPathmethod: Route::get('users', function () { $users = App\User::paginate(15); $users->withPath('custom/url'); // }); Appending To Pagination Links You may append to the query string of pagination links using the appends method. For example, to append sort=votes to each pagination link, you should make the following call to appends: {{ $users->appends(['sort' => 'votes'])->links() }} If you wish to append a "hash fragment" to the paginator's URLs, you may use the fragment method. For example, to append #foo to the end of each pagination link, make the following call to the fragment method: {{ $users->fragment('foo')->links() }} Adjusting The Pagination Link Window You may control how many additional links are displayed on each side of the paginator's URL "window". By default, three links are displayed on each side of the primary paginator links. However, you may control this number using the onEachSidemethod: {{ $users->onEachSide(5)->links() }} Converting Results To JSON The Laravel paginator result classes implement the Illuminate\Contracts\Support\Jsonable Interface contract and expose the toJsonmethod, so it's very easy to convert your pagination results to JSON. You may also convert a paginator instance to JSON by returning it from a route or controller action: Route::get('users', function () { return App\User::paginate(); }); The JSON from the paginator will include meta information such as total, current_page, last_page, and more. The actual result objects will be available via the data key in the JSON array. Here is an example of the JSON created by returning a paginator instance from a route: { "total": 50, "per_page": 15, "current_page": 1, "last_page": 4, "first_page_url": "http://laravel.app?page=1", "last_page_url": "http://laravel.app?page=4", "next_page_url": "http://laravel.app?page=2", "prev_page_url": null, "path": "http://laravel.app", "from": 1, "to": 15, "data":[ { // Result Object }, { // Result Object } ] } Customizing The Pagination View By default, the views rendered to display the pagination links are compatible with the Bootstrap CSS framework. However, if you are not using Bootstrap, you are free to define your own views to render these links. When calling the links method on a paginator instance, pass the view name as the first argument to the method: {{ $paginator->links('view.name') }} // Passing data to the view... {{ $paginator->links('view.name', ['foo' => 'bar']) }} However, the easiest way to customize the pagination views is by exporting them to your resources/views/vendor directory using the vendor:publish command: php artisan vendor:publish --tag=laravel-pagination This command will place the views in the resources/views/vendor/pagination directory. The bootstrap-4.blade.php file within this directory corresponds to the default pagination view. You may edit this file to modify the pagination HTML. If you would like to designate a different file as the default pagination view, you may use the paginator's defaultView and defaultSimpleView methods within your AppServiceProvider: use Illuminate\Pagination\Paginator; public function boot() { Paginator::defaultView('view-name'); Paginator::defaultSimpleView('view-name'); } Paginator Instance Methods Each paginator instance provides additional pagination information via the following methods: $results->count() Get the number of items for the current page. $results->currentPage() Get the current page number. $results->firstItem() Get the result number of the first item in the results. $results->getOptions() Get the paginator options. $results->getUrlRange($start, $end) Create a range of pagination URLs. $results->hasMorePages() Determine if there are enough items to split into multiple pages. $results->lastItem() Get the result number of the last item in the results. $results->lastPage() Get the page number of the last available page. (Not available when using simplePaginate). $results->nextPageUrl() Get the URL for the next page. $results->onFirstPage() Determine if the paginator is on the first page. $results->perPage() The number of items to be shown per page. $results->previousPageUrl() Get the URL for the previous page. $results->total() Determine the total number of matching items in the data store. (Not available when using simplePaginate). $results->url($page) Get the URL for a given page number.
Validation [ Form Requests ] { artisan make:request, $request->validated(); withValidator, $validator->after, authorize(), messages(), attributes()}
For more complex validation scenarios, you may wish to create a "form request". Form requests are custom request classes that contain validation logic. To create a form request class, use the make:request Artisan CLI command: php artisan make:request StoreBlogPost The generated class will be placed in the app/Http/Requests directory. If this directory does not exist, it will be created when you run the make:request command. Let's add a few validation rules to the rules method: public function rules() { return [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]; } So, how are the validation rules evaluated? All you need to do is type-hint the request on your controller method. The incoming form request is validated before the controller method is called, meaning you do not need to clutter your controller with any validation logic: public function store(StoreBlogPost $request) { // The incoming request is valid... // Retrieve the validated input data... $validated = $request->validated(); } If validation fails, a redirect response will be generated to send the user back to their previous location. The errors will also be flashed to the session so they are available for display. If the request was an AJAX request, a HTTP response with a 422 status code will be returned to the user including a JSON representation of the validation errors. Adding After Hooks To Form Requests If you would like to add an "after" hook to a form request, you may use the withValidator method. This method receives the fully constructed validator, allowing you to call any of its methods before the validation rules are actually evaluate public function withValidator($validator) { $validator->after(function ($validator) { if ($this->somethingElseIsInvalid()) { $validator->errors()->add('field', 'Something is wrong with this field!'); } }); } Authorizing Form Requests The form request class also contains an authorize method. Within this method, you may check if the authenticated user actually has the authority to update a given resource. For example, you may determine if a user actually owns a blog comment they are attempting to update public function authorize() { $comment = Comment::find($this->route('comment')); return $comment && $this->user()->can('update', $comment); } Since all form requests extend the base Laravel request class, we may use the usermethod to access the currently authenticated user. Also note the call to the routemethod in the example above. This method grants you access to the URI parameters defined on the route being called, such as the {comment} parameter in the example below: Route::post('comment/{comment}'); If the authorize method returns false, a HTTP response with a 403 status code will automatically be returned and your controller method will not execute. If you plan to have authorization logic in another part of your application, return truefrom the authorize method: Customizing The Error Messages You may customize the error messages used by the form request by overriding the messages method. This method should return an array of attribute / rule pairs and their corresponding error messages: public function messages() { return [ 'title.required' => 'A title is required', 'body.required' => 'A message is required', ]; } Customizing The Validation Attributes If you would like the :attribute portion of your validation message to be replaced with a custom attribute name, you may specify the custom names by overriding the attributes method. This method should return an array of attribute / name pairs: public function attributes() { return [ 'email' => 'email address', ]; }
Notifications [ Mail Notifications ] { define a toMail method on the notification class. This method will receive a $notifiable entity and should return a Illuminate\Notifications\Messages\MailMessage or use the view method to specify a custom template that should be used to render the notification email; In addition, you may return a mailable object from the toMail method; When using the error method on a mail message, the call to action button will be red instead of blue; You may customize which email address is used to deliver the notification by defining a routeNotificationForMail method on the entity; If you would like to specify an explicit subject for the message, you may call the subject method when building your message; php artisan vendor:publish --tag=laravel-notifications. After running this command, the mail notification templates will be located in the resources/views/vendor/notificationsdirectory }
Formatting Mail Messages If a notification supports being sent as an email, you should define a toMail method on the notification class. This method will receive a $notifiable entity and should return a Illuminate\Notifications\Messages\MailMessage instance. Mail messages may contain lines of text as well as a "call to action". Let's take a look at an example toMail method: /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $url = url('/invoice/'.$this->invoice->id); return (new MailMessage) ->greeting('Hello!') ->line('One of your invoices has been paid!') ->action('View Invoice', $url) ->line('Thank you for using our application!'); } Note we are using $this->invoice->id in our toMail method. You may pass any data your notification needs to generate its message into the notification's constructor. In this example, we register a greeting, a line of text, a call to action, and then another line of text. These methods provided by the MailMessage object make it simple and fast to format small transactional emails. The mail channel will then translate the message components into a nice, responsive HTML email template with a plain-text counterpart. Here is an example of an email generated by the mail channel When sending mail notifications, be sure to set the namevalue in your config/app.php configuration file. This value will be used in the header and footer of your mail notification messages. Other Notification Formatting Options Instead of defining the "lines" of text in the notification class, you may use the viewmethod to specify a custom template that should be used to render the notification email: /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { return (new MailMessage)->view( 'emails.name', ['invoice' => $this->invoice] ); } In addition, you may return a mailable object from the toMail method: use App\Mail\InvoicePaid as Mailable; /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return Mailable */ public function toMail($notifiable) { return (new Mailable($this->invoice))->to($this->user->email); } Error Messages Some notifications inform users of errors, such as a failed invoice payment. You may indicate that a mail message is regarding an error by calling the error method when building your message. When using the error method on a mail message, the call to action button will be red instead of blue: /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Message */ public function toMail($notifiable) { return (new MailMessage) ->error() ->subject('Notification Subject') ->line('...'); } Customizing The Recipient When sending notifications via the mail channel, the notification system will automatically look for an email property on your notifiable entity. You may customize which email address is used to deliver the notification by defining a routeNotificationForMail method on the entity: namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * Route notifications for the mail channel. * * @param \Illuminate\Notifications\Notification $notification * @return string */ public function routeNotificationForMail($notification) { return $this->email_address; } } Customizing The Subject By default, the email's subject is the class name of the notification formatted to "title case". So, if your notification class is named InvoicePaid, the email's subject will be Invoice Paid. If you would like to specify an explicit subject for the message, you may call the subject method when building your message: /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { return (new MailMessage) ->subject('Notification Subject') ->line('...'); } Customizing The Templates You can modify the HTML and plain-text template used by mail notifications by publishing the notification package's resources. After running this command, the mail notification templates will be located in the resources/views/vendor/notificationsdirectory: php artisan vendor:publish --tag=laravel-notifications
Task Scheduling [ Scheduling Artisan Commands ] { task schedule is defined in the app/Console/Kernel.php file's schedule method; * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1; $schedule->command('emails:send --force')->daily(); $schedule->command(EmailsCommand::class, ['--force'])->daily(); }
In the past, you may have generated a Cron entry for each task you needed to schedule on your server. However, this can quickly become a pain, because your task schedule is no longer in source control and you must SSH into your server to add additional Cron entries. Laravel's command scheduler allows you to fluently and expressively define your command schedule within Laravel itself. When using the scheduler, only a single Cron entry is needed on your server. Your task schedule is defined in the app/Console/Kernel.php file's schedule method. To help you get started, a simple example is defined within the method. Starting The Scheduler When using the scheduler, you only need to add the following Cron entry to your server. If you do not know how to add Cron entries to your server, consider using a service such as Laravel Forge which can manage the Cron entries for you: * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1 This Cron will call the Laravel command scheduler every minute. When the schedule:run command is executed, Laravel will evaluate your scheduled tasks and runs the tasks that are due. Defining Schedules You may define all of your scheduled tasks in the schedule method of the App\Console\Kernel class. To get started, let's look at an example of scheduling a task. In this example, we will schedule a Closure to be called every day at midnight. Within the Closure we will execute a database query to clear a table: namespace App\Console; use Illuminate\Support\Facades\DB; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ // ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->call(function () { DB::table('recent_users')->delete(); })->daily(); } } In addition to scheduling using Closures, you may also use invokable objects. Invokable objects are simple PHP classes that contain an __invoke method: $schedule->call(new DeleteRecentUsers)->daily(); Scheduling Artisan Commands In addition to scheduling Closure calls, you may also schedule Artisan commands and operating system commands. For example, you may use the command method to schedule an Artisan command using either the command's name or class: $schedule->command('emails:send --force')->daily(); $schedule->command(EmailsCommand::class, ['--force'])->daily();
Queues [ Supervisor ] { Supervisor is a process monitor for the Linux operating system, and will automatically restart your queue:work process if it fails. }
Installing Supervisor Supervisor is a process monitor for the Linux operating system, and will automatically restart your queue:work process if it fails. To install Supervisor on Ubuntu, you may use the following command: sudo apt-get install supervisor If configuring Supervisor yourself sounds overwhelming, consider using Laravel Forge, which will automatically install and configure Supervisor for your Laravel projects. Configuring Supervisor Supervisor configuration files are typically stored in the /etc/supervisor/conf.ddirectory. Within this directory, you may create any number of configuration files that instruct supervisor how your processes should be monitored. For example, let's create a laravel-worker.conf file that starts and monitors a queue:work process: [program:laravel-worker] process_name=%(program_name)s_%(process_num)02d command=php /home/forge/app.com/artisan queue:work sqs --sleep=3 --tries=3 autostart=true autorestart=true user=forge numprocs=8 redirect_stderr=true stdout_logfile=/home/forge/app.com/worker.log In this example, the numprocs directive will instruct Supervisor to run 8 queue:workprocesses and monitor all of them, automatically restarting them if they fail. You should change the queue:work sqs portion of the command directive to reflect your desired queue connection. Starting Supervisor Once the configuration file has been created, you may update the Supervisor configuration and start the processes using the following commands: sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start laravel-worker:*
Websockets [ Receiving Events ] { npm install --save laravel-echo pusher-js; import Echo from "laravel-echo" window.Echo = new Echo({ broadcaster: 'pusher', key: 'your-pusher-channels-key' }); const client = require('pusher-js'); window.Echo = new Echo({ broadcaster: 'pusher', key: 'your-pusher-channels-key', client: client }); Echo.channel('orders') .listen('OrderShipped', (e) => { console.log(e.order.name); }); Echo.leaveChannel('orders'); Echo.leave('orders'); window.Echo = new Echo({ broadcaster: 'pusher', key: 'your-pusher-channels-key', namespace: 'App.Other.Namespace' }); Echo.channel('orders') .listen('.Namespace\\Event\\Class', (e) => { // }); Echo.private(`App.User.${userId}`) .notification((notification) => { console.log(notification.type); }); }
Installing Laravel Echo Laravel Echo is a JavaScript library that makes it painless to subscribe to channels and listen for events broadcast by Laravel. You may install Echo via the NPM package manager. In this example, we will also install the pusher-js package since we will be using the Pusher Channels broadcaster: npm install --save laravel-echo pusher-js Once Echo is installed, you are ready to create a fresh Echo instance in your application's JavaScript. A great place to do this is at the bottom of the resources/js/bootstrap.js file that is included with the Laravel framework: import Echo from "laravel-echo" window.Echo = new Echo({ broadcaster: 'pusher', key: 'your-pusher-channels-key' }); When creating an Echo instance that uses the pusher connector, you may also specify a cluster as well as whether the connection must be made over TLS (by default, when forceTLS is false, a non-TLS connection will be made if the page was loaded over HTTP, or as a fallback if a TLS connection fails): window.Echo = new Echo({ broadcaster: 'pusher', key: 'your-pusher-channels-key', cluster: 'eu', forceTLS: true }); Using An Existing Client Instance If you already have a Pusher Channels or Socket.io client instance that you would like Echo to utilize, you may pass it to Echo via the client configuration option: const client = require('pusher-js'); window.Echo = new Echo({ broadcaster: 'pusher', key: 'your-pusher-channels-key', client: client }); Listening For Events Once you have installed and instantiated Echo, you are ready to start listening for event broadcasts. First, use the channel method to retrieve an instance of a channel, then call the listen method to listen for a specified event: 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(...); Leaving A Channel To leave a channel, you may call the leaveChannel method on your Echo instance: Echo.leaveChannel('orders'); If you would like to leave a channel and also its associated private and presence channels, you may call the leave method: Echo.leave('orders'); Namespaces You may have noticed in the examples above that we did not specify the full namespace for the event classes. This is because Echo will automatically assume the events are located in the App\Events namespace. However, you may configure the root namespace when you instantiate Echo by passing a namespace configuration option: window.Echo = new Echo({ broadcaster: 'pusher', key: 'your-pusher-channels-key', namespace: 'App.Other.Namespace' }); Alternatively, you may prefix event classes with a . when subscribing to them using Echo. This will allow you to always specify the fully-qualified class name: Echo.channel('orders') .listen('.Namespace\\Event\\Class', (e) => { // }); 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.
Artisan Console [ Generating Commands ] { php artisan list, php artisan help migrate, php artisan tinker, php artisan make:command SendEmails, signature and description properties, handle method, Within the commands method of your app/Console/Kernel.php file, Laravel loads the routes/console.php file, Artisan::command, Artisan::command('email:send {user}', function (DripEmailer $drip, $user) { $drip->send(User::find($user)); }); Artisan::command('build {project}', function ($project) { $this->info("Building {$project}!"); })->describe('Build the project');}
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 Tinker (REPL) All Laravel applications include Tinker, a REPL powered by the PsySH package. Tinker allows you to interact with your entire Laravel application on the command line, including the Eloquent ORM, jobs, events, and more. To enter the Tinker environment, run the tinker Artisan command: php artisan tinker You can publish Tinker's configuration file using the vendor:publish command: php artisan vendor:publish --provider="Laravel\Tinker\TinkerServiceProvider" Command Whitelist Tinker utilizes a white-list to determine which Artisan commands are allowed to be run within its shell. By default, you may run the clear-compiled, down, env, inspire, migrate, optimize, and up commands. If you would like to white-list more commands you may add them to the commands array in your tinker.php configuration file: 'commands' => [ // App\Console\Commands\ExampleCommand::class, ], Alias Blacklist Typically, Tinker automatically aliases classes as you require them in Tinker. However, you may wish to never alias some classes. You may accomplish this by listing the classes in the dont_alias array of your tinker.php configuration file: 'dont_alias' => [ App\User::class, ], Writing Commands In addition to the commands provided with Artisan, you may also build your own custom commands. Commands are typically stored in the app/Console/Commandsdirectory; however, you are free to choose your own storage location as long as your commands can be loaded by Composer. Generating Commands To create a new command, use the make:command Artisan command. This command will create a new command class in the app/Console/Commands directory. Don't worry if this directory does not exist in your application, since it will be created the first time you run the make:command Artisan command. The generated command will include the default set of properties and methods that are present on all commands: php artisan make:command SendEmails Command Structure After generating your command, you should fill in the signature and descriptionproperties of the class, which will be used when displaying your command on the listscreen. The handle method will be called when your command is executed. You may place your command logic in this method. For greater code reuse, it is good practice to keep your console commands light and let them defer to application services to accomplish their tasks. In the example below, note that we inject a service class to do the "heavy lifting" of sending the e-mails. Let's take a look at an example command. Note that we are able to inject any dependencies we need into the command's handle method. The Laravel service container will automatically inject all dependencies that are type-hinted in this method's signature: class SendEmails extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'email:send {user}'; /** * The console command description. * * @var string */ protected $description = 'Send drip e-mails to a user'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @param \App\DripEmailer $drip * @return mixed */ public function handle(DripEmailer $drip) { $drip->send(User::find($this->argument('user'))); } } Closure Commands Closure based commands provide an alternative to defining console commands as classes. In the same way that route Closures are an alternative to controllers, think of command Closures as an alternative to command classes. Within the commands method of your app/Console/Kernel.php file, Laravel loads the routes/console.php file: /** * 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. 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)); }); 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');
Database [ Query Builder ] { config/database.php; Read & Write Connections; DB::connection('foo'); DB::select('select * from users where active = ?', [1]); DB::select('select * from users where id = :id', ['id' => 1]); DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']); DB::update('update users set votes = 100 where name = ?', ['John']); DB::delete('delete from users'); DB::statement('drop table users'); DB::listen(function ($query) { // $query->sql // $query->bindings // $query->time }); DB::transaction(function () { DB::table('users')->update(['votes' => 1]); DB::table('posts')->delete(); }, 5); DB::beginTransaction(); DB::rollBack(); DB::commit(); DB::table('users')->get(); DB::table('users')->where('name', 'John')->first(); DB::table('users')->where('name', 'John')->value('email'); DB::table('roles')->pluck('title'); DB::table('roles')->pluck('title', 'name'); DB::table('users')->orderBy('id')->chunk(100, function ($users) { foreach ($users as $user) { // } }); DB::table('users')->orderBy('id')->chunk(100, function ($users) { // Process the records... return false; }); DB::table('users')->where('active', false) ->chunkById(100, function ($users) { foreach ($users as $user) { DB::table('users') ->where('id', $user->id) ->update(['active' => true]); } }); DB::table('users')->count(); DB::table('orders')->max('price'); DB::table('orders') ->where('finalized', 1) ->avg('price'); DB::table('orders')->where('finalized', 1)->exists(); DB::table('orders')->where('finalized', 1)->doesntExist(); DB::table('users')->select('name', 'email as user_email')->get(); DB::table('users')->distinct()->get(); $query = DB::table('users')->select('name'); $users = $query->addSelect('age')->get(); DB::table('users') ->select(DB::raw('count(*) as user_count, status')) ->where('status', '<>', 1) ->groupBy('status') ->get(); DB::table('orders') ->selectRaw('price * ? as price_with_tax', [1.0825]) ->get(); whereRaw and orWhereRaw: DB::table('orders') ->whereRaw('price > IF(state = "TX", ?, 100)', [200]) ->get(); havingRaw and orHavingRaw methods DB::table('orders') ->select('department', DB::raw('SUM(price) as total_sales')) ->groupBy('department') ->havingRaw('SUM(price) > ?', [2500]) ->get(); DB::table('orders') ->orderByRaw('updated_at - created_at DESC') ->get(); Inner Join Clause: DB::table('users') ->join('contacts', 'users.id', '=', 'contacts.user_id') ->join('orders', 'users.id', '=', 'orders.user_id') ->select('users.*', 'contacts.phone', 'orders.price') ->get(); Left Join / Right Join Clause: DB::table('users') ->leftJoin('posts', 'users.id', '=', 'posts.user_id') ->get(); DB::table('users') ->rightJoin('posts', 'users.id', '=', 'posts.user_id') ->get(); Cross Join Clause DB::table('sizes') ->crossJoin('colours') ->get(); Advanced Join Clauses: DB::table('users') ->join('contacts', function ($join) { $join->on('users.id', '=', 'contacts.user_id')->orOn(...); }) ->get(); DB::table('users') ->join('contacts', function ($join) { $join->on('users.id', '=', 'contacts.user_id') ->where('contacts.user_id', '>', 5); }) ->get(); Sub-Query Joins $latestPosts = DB::table('posts') ->select('user_id', DB::raw('MAX(created_at) as last_post_created_at')) ->where('is_published', true) ->groupBy('user_id'); $users = DB::table('users') ->joinSub($latestPosts, 'latest_posts', function ($join) { $join->on('users.id', '=', 'latest_posts.user_id'); })->get(); Unions $first = DB::table('users') ->whereNull('first_name'); $users = DB::table('users') ->whereNull('last_name') ->union($first) ->get(); DB::table('users')->where('votes', '=', 100)->get(); $users = DB::table('users')->where([ ['status', '=', '1'], ['subscribed', '<>', '1'], ])->get(); DB::table('users') ->where('votes', '>', 100) ->orWhere('name', 'John') ->get(); DB::table('users') ->whereBetween('votes', [1, 100])->get(); DB::table('users') ->whereNotBetween('votes', [1, 100]) ->get(); DB::table('users') ->whereIn('id', [1, 2, 3]) ->get(); DB::table('users') ->whereNotIn('id', [1, 2, 3]) ->get(); DB::table('users') ->whereNull('updated_at') ->get(); DB::table('users') ->whereNotNull('updated_at') ->get(); whereDate / whereMonth / whereDay / whereYear / whereTime; DB::table('users') ->whereColumn('first_name', 'last_name') ->get(); DB::table('users') ->whereColumn([ ['first_name', '=', 'last_name'], ['updated_at', '>', 'created_at'] ])->get(); DB::table('users') ->where('name', '=', 'John') ->where(function ($query) { $query->where('votes', '>', 100) ->orWhere('title', '=', 'Admin'); }) ->get(); DB::table('users') ->whereExists(function ($query) { $query->select(DB::raw(1)) ->from('orders') ->whereRaw('orders.user_id = users.id'); }) ->get(); DB::table('users') ->where('options->language', 'en') ->get(); DB::table('users') ->whereJsonContains('options->languages', ['en', 'de']) ->get(); DB::table('users') ->whereJsonLength('options->languages', '>', 1) ->get(); DB::table('users') ->orderBy('name', 'desc') ->get(); latest and oldest methods allow you to easily order results by date. By default, result will be ordered by the created_at column DB::table('users') ->latest() ->first(); DB::table('users') ->inRandomOrder() ->first(); DB::table('users') ->groupBy('account_id') ->having('account_id', '>', 100) ->get(); DB::table('users')->skip(10)->take(5)->get(); DB::table('users') ->offset(10) ->limit(5) ->get(); DB::table('users') ->when($sortBy, function ($query, $sortBy) { return $query->orderBy($sortBy); }, function ($query) { return $query->orderBy('name'); }) ->get(); DB::table('users')->insert([ ['email' => '[email protected]', 'votes' => 0], ['email' => '[email protected]', 'votes' => 0] ]); $id = DB::table('users')->insertGetId( ['email' => '[email protected]', 'votes' => 0] ); DB::table('users') ->where('id', 1) ->update(['votes' => 1]); DB::table('users') ->updateOrInsert( ['email' => '[email protected]', 'name' => 'John'], ['votes' => '2'] ); DB::table('users') ->where('id', 1) ->update(['options->enabled' => true]); DB::table('users')->increment('votes'); DB::table('users')->increment('votes', 5); DB::table('users')->decrement('votes'); DB::table('users')->decrement('votes', 5); DB::table('users')->increment('votes', 1, ['name' => 'John']); DB::table('users')->delete(); DB::table('users')->where('votes', '>', 100)->delete(); DB::table('users')->truncate(); DB::table('users')->where('votes', '>', 100)->sharedLock()->get(); DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get(); }
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: MySQL PostgreSQL SQLite SQL Server 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. You are free to modify this configuration as needed for your local database. 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 To enable foreign key constraints for SQLite connections, you should add the foreign_key_constraints option to your config/database.php configuration file: 'sqlite' => [ // ... 'foreign_key_constraints' => true, ], 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 mysqlarray will be shared across both connections. 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. Using Multiple Database Connections When using multiple connections, you may access each connection via the connectionmethod 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(); 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. Running A Select Query To run a basic query, you may use the select method on the DB facade: 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; } 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]); 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']); 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']); 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'); 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'); 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: 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() { // } } 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(); }); 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); 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(); The DB facade's transaction methods control the transactions for both the query builder and Eloquent ORM. Laravel's database query builder provides a convenient, fluent interface to creating and running database queries. It can be used to perform most database operations in your application and works on all supported database systems. The Laravel query builder uses PDO parameter binding to protect your application against SQL injection attacks. There is no need to clean strings being passed as bindings. Retrieving Results Retrieving All Rows From A Table You may use the table method on the DB facade to begin a query. The table method returns a fluent query builder instance for the given table, allowing you to chain more constraints onto the query and then finally get the results using the get method: 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::table('users')->get(); return view('user.index', ['users' => $users]); } } The get method returns an Illuminate\Support\Collection containing the results where each result is an instance of the PHP stdClass object. You may access each column's value by accessing the column as a property of the object: foreach ($users as $user) { echo $user->name; } Retrieving A Single Row / Column From A Table If you just need to retrieve a single row from the database table, you may use the firstmethod. This method will return a single stdClass object: $user = DB::table('users')->where('name', 'John')->first(); echo $user->name; If you don't even need an entire row, you may extract a single value from a record using the value method. This method will return the value of the column directly: $email = DB::table('users')->where('name', 'John')->value('email'); Retrieving A List Of Column Values If you would like to retrieve a Collection containing the values of a single column, you may use the pluck method. In this example, we'll retrieve a Collection of role titles: $titles = DB::table('roles')->pluck('title'); foreach ($titles as $title) { echo $title; } You may also specify a custom key column for the returned Collection: $roles = DB::table('roles')->pluck('title', 'name'); foreach ($roles as $name => $title) { echo $title; } Chunking Results If you need to work with thousands of database records, consider using the chunkmethod. This method retrieves a small chunk of the results at a time and feeds each chunk into a Closure for processing. This method is very useful for writing Artisan commands that process thousands of records. For example, let's work with the entire users table in chunks of 100 records at a time: DB::table('users')->orderBy('id')->chunk(100, function ($users) { foreach ($users as $user) { // } }); You may stop further chunks from being processed by returning false from the Closure: DB::table('users')->orderBy('id')->chunk(100, function ($users) { // Process the records... return false; }); If you are updating database records while chunking results, your chunk results could change in unexpected ways. So, when updating records while chunking, it is always best to use the chunkById method instead. This method will automatically paginate the results based on the record's primary key: DB::table('users')->where('active', false) ->chunkById(100, function ($users) { foreach ($users as $user) { DB::table('users') ->where('id', $user->id) ->update(['active' => true]); } }); When updating or deleting records inside the chunk callback, any changes to the primary key or foreign keys could affect the chunk query. This could potentially result in records not being included in the chunked results. Aggregates The query builder also provides a variety of aggregate methods such as count, max, min, avg, and sum. You may call any of these methods after constructing your query: $users = DB::table('users')->count(); $price = DB::table('orders')->max('price'); You may combine these methods with other clauses: $price = DB::table('orders') ->where('finalized', 1) ->avg('price'); Determining If Records Exist Instead of using the count method to determine if any records exist that match your query's constraints, you may use the exists and doesntExist methods: return DB::table('orders')->where('finalized', 1)->exists(); return DB::table('orders')->where('finalized', 1)->doesntExist(); Selects Specifying A Select Clause You may not always want to select all columns from a database table. Using the selectmethod, you can specify a custom select clause for the query: $users = DB::table('users')->select('name', 'email as user_email')->get(); The distinct method allows you to force the query to return distinct results: $users = DB::table('users')->distinct()->get(); If you already have a query builder instance and you wish to add a column to its existing select clause, you may use the addSelect method: $query = DB::table('users')->select('name'); $users = $query->addSelect('age')->get(); Raw Expressions Sometimes you may need to use a raw expression in a query. To create a raw expression, you may use the DB::raw method: $users = DB::table('users') ->select(DB::raw('count(*) as user_count, status')) ->where('status', '<>', 1) ->groupBy('status') ->get(); Raw statements will be injected into the query as strings, so you should be extremely careful to not create SQL injection vulnerabilities. Raw Methods Instead of using DB::raw, you may also use the following methods to insert a raw expression into various parts of your query. selectRaw The selectRaw method can be used in place of select(DB::raw(...)). This method accepts an optional array of bindings as its second argument: $orders = DB::table('orders') ->selectRaw('price * ? as price_with_tax', [1.0825]) ->get(); whereRaw / orWhereRaw The whereRaw and orWhereRaw methods can be used to inject a raw where clause into your query. These methods accept an optional array of bindings as their second argument: $orders = DB::table('orders') ->whereRaw('price > IF(state = "TX", ?, 100)', [200]) ->get(); havingRaw / orHavingRaw The havingRaw and orHavingRaw methods may be used to set a raw string as the value of the having clause. These methods accept an optional array of bindings as their second argument: $orders = DB::table('orders') ->select('department', DB::raw('SUM(price) as total_sales')) ->groupBy('department') ->havingRaw('SUM(price) > ?', [2500]) ->get(); orderByRaw The orderByRaw method may be used to set a raw string as the value of the order byclause: $orders = DB::table('orders') ->orderByRaw('updated_at - created_at DESC') ->get(); Joins Inner Join Clause The query builder may also be used to write join statements. To perform a basic "inner join", you may use the join method on a query builder instance. The first argument passed to the join method is the name of the table you need to join to, while the remaining arguments specify the column constraints for the join. You can even join to multiple tables in a single query: $users = DB::table('users') ->join('contacts', 'users.id', '=', 'contacts.user_id') ->join('orders', 'users.id', '=', 'orders.user_id') ->select('users.*', 'contacts.phone', 'orders.price') ->get(); Left Join / Right Join Clause If you would like to perform a "left join" or "right join" instead of an "inner join", use the leftJoin or rightJoin methods. These methods have the same signature as the joinmethod: $users = DB::table('users') ->leftJoin('posts', 'users.id', '=', 'posts.user_id') ->get(); $users = DB::table('users') ->rightJoin('posts', 'users.id', '=', 'posts.user_id') ->get(); Cross Join Clause To perform a "cross join" use the crossJoin method with the name of the table you wish to cross join to. Cross joins generate a cartesian product between the first table and the joined table: $users = DB::table('sizes') ->crossJoin('colours') ->get(); Advanced Join Clauses You may also specify more advanced join clauses. To get started, pass a Closure as the second argument into the join method. The Closure will receive a JoinClause object which allows you to specify constraints on the join clause: DB::table('users') ->join('contacts', function ($join) { $join->on('users.id', '=', 'contacts.user_id')->orOn(...); }) ->get(); If you would like to use a "where" style clause on your joins, you may use the where and orWhere methods on a join. Instead of comparing two columns, these methods will compare the column against a value: DB::table('users') ->join('contacts', function ($join) { $join->on('users.id', '=', 'contacts.user_id') ->where('contacts.user_id', '>', 5); }) ->get(); Sub-Query Joins You may use the joinSub, leftJoinSub, and rightJoinSub methods to join a query to a sub-query. Each of these methods receive three arguments: the sub-query, its table alias, and a Closure that defines the related columns: $latestPosts = DB::table('posts') ->select('user_id', DB::raw('MAX(created_at) as last_post_created_at')) ->where('is_published', true) ->groupBy('user_id'); $users = DB::table('users') ->joinSub($latestPosts, 'latest_posts', function ($join) { $join->on('users.id', '=', 'latest_posts.user_id'); })->get(); Unions The query builder also provides a quick way to "union" two queries together. For example, you may create an initial query and use the union method to union it with a second query: $first = DB::table('users') ->whereNull('first_name'); $users = DB::table('users') ->whereNull('last_name') ->union($first) ->get(); The unionAll method is also available and has the same method signature as union. Where Clauses Simple Where Clauses You may use the where method on a query builder instance to add where clauses to the query. The most basic call to where requires three arguments. The first argument is the name of the column. The second argument is an operator, which can be any of the database's supported operators. Finally, the third argument is the value to evaluate against the column. For example, here is a query that verifies the value of the "votes" column is equal to 100: $users = DB::table('users')->where('votes', '=', 100)->get(); For convenience, if you want to verify that a column is equal to a given value, you may pass the value directly as the second argument to the where method: $users = DB::table('users')->where('votes', 100)->get(); You may use a variety of other operators when writing a where clause: $users = DB::table('users') ->where('votes', '>=', 100) ->get(); $users = DB::table('users') ->where('votes', '<>', 100) ->get(); $users = DB::table('users') ->where('name', 'like', 'T%') ->get(); You may also pass an array of conditions to the where function: $users = DB::table('users')->where([ ['status', '=', '1'], ['subscribed', '<>', '1'], ])->get(); Or Statements You may chain where constraints together as well as add or clauses to the query. The orWhere method accepts the same arguments as the where method: $users = DB::table('users') ->where('votes', '>', 100) ->orWhere('name', 'John') ->get(); Additional Where Clauses whereBetween The whereBetween method verifies that a column's value is between two values: $users = DB::table('users') ->whereBetween('votes', [1, 100])->get(); whereNotBetween The whereNotBetween method verifies that a column's value lies outside of two values: $users = DB::table('users') ->whereNotBetween('votes', [1, 100]) ->get(); whereIn / whereNotIn The whereIn method verifies that a given column's value is contained within the given array: $users = DB::table('users') ->whereIn('id', [1, 2, 3]) ->get(); The whereNotIn method verifies that the given column's value is not contained in the given array: $users = DB::table('users') ->whereNotIn('id', [1, 2, 3]) ->get(); whereNull / whereNotNull The whereNull method verifies that the value of the given column is NULL: $users = DB::table('users') ->whereNull('updated_at') ->get(); The whereNotNull method verifies that the column's value is not NULL: $users = DB::table('users') ->whereNotNull('updated_at') ->get(); whereDate / whereMonth / whereDay / whereYear / whereTime The whereDate method may be used to compare a column's value against a date: $users = DB::table('users') ->whereDate('created_at', '2016-12-31') ->get(); The whereMonth method may be used to compare a column's value against a specific month of a year: $users = DB::table('users') ->whereMonth('created_at', '12') ->get(); The whereDay method may be used to compare a column's value against a specific day of a month: $users = DB::table('users') ->whereDay('created_at', '31') ->get(); The whereYear method may be used to compare a column's value against a specific year: $users = DB::table('users') ->whereYear('created_at', '2016') ->get(); The whereTime method may be used to compare a column's value against a specific time: $users = DB::table('users') ->whereTime('created_at', '=', '11:20:45') ->get(); whereColumn The whereColumn method may be used to verify that two columns are equal: $users = DB::table('users') ->whereColumn('first_name', 'last_name') ->get(); You may also pass a comparison operator to the method: $users = DB::table('users') ->whereColumn('updated_at', '>', 'created_at') ->get(); The whereColumn method can also be passed an array of multiple conditions. These conditions will be joined using the and operator: $users = DB::table('users') ->whereColumn([ ['first_name', '=', 'last_name'], ['updated_at', '>', 'created_at'] ])->get(); Parameter Grouping Sometimes you may need to create more advanced where clauses such as "where exists" clauses or nested parameter groupings. The Laravel query builder can handle these as well. To get started, let's look at an example of grouping constraints within parenthesis: DB::table('users') ->where('name', '=', 'John') ->where(function ($query) { $query->where('votes', '>', 100) ->orWhere('title', '=', 'Admin'); }) ->get(); As you can see, passing a Closure into the where method instructs the query builder to begin a constraint group. The Closure will receive a query builder instance which you can use to set the constraints that should be contained within the parenthesis group. The example above will produce the following SQL: select * from users where name = 'John' and (votes > 100 or title = 'Admin') You should always group orWhere calls in order to avoid unexpected behavior when global scopes are applied. Where Exists Clauses The whereExists method allows you to write where exists SQL clauses. The whereExistsmethod accepts a Closure argument, which will receive a query builder instance allowing you to define the query that should be placed inside of the "exists" clause: DB::table('users') ->whereExists(function ($query) { $query->select(DB::raw(1)) ->from('orders') ->whereRaw('orders.user_id = users.id'); }) ->get(); The query above will produce the following SQL: select * from users where exists ( select 1 from orders where orders.user_id = users.id ) JSON Where Clauses Laravel also supports querying JSON column types on databases that provide support for JSON column types. Currently, this includes MySQL 5.7, PostgreSQL, SQL Server 2016, and SQLite 3.9.0 (with the JSON1 extension). To query a JSON column, use the ->operator: $users = DB::table('users') ->where('options->language', 'en') ->get(); $users = DB::table('users') ->where('preferences->dining->meal', 'salad') ->get(); You may use whereJsonContains to query JSON arrays (not supported on SQLite): $users = DB::table('users') ->whereJsonContains('options->languages', 'en') ->get(); MySQL and PostgreSQL support whereJsonContains with multiple values: $users = DB::table('users') ->whereJsonContains('options->languages', ['en', 'de']) ->get(); You may use whereJsonLength to query JSON arrays by their length: $users = DB::table('users') ->whereJsonLength('options->languages', 0) ->get(); $users = DB::table('users') ->whereJsonLength('options->languages', '>', 1) ->get(); Ordering, Grouping, Limit, & Offset orderBy The orderBy method allows you to sort the result of the query by a given column. The first argument to the orderBy method should be the column you wish to sort by, while the second argument controls the direction of the sort and may be either asc or desc: $users = DB::table('users') ->orderBy('name', 'desc') ->get(); latest / oldest The latest and oldest methods allow you to easily order results by date. By default, result will be ordered by the created_at column. Or, you may pass the column name that you wish to sort by: $user = DB::table('users') ->latest() ->first(); inRandomOrder The inRandomOrder method may be used to sort the query results randomly. For example, you may use this method to fetch a random user: $randomUser = DB::table('users') ->inRandomOrder() ->first(); groupBy / having The groupBy and having methods may be used to group the query results. The havingmethod's signature is similar to that of the where method: $users = DB::table('users') ->groupBy('account_id') ->having('account_id', '>', 100) ->get(); You may pass multiple arguments to the groupBy method to group by multiple columns: $users = DB::table('users') ->groupBy('first_name', 'status') ->having('account_id', '>', 100) ->get(); For more advanced having statements, see the havingRaw method. skip / take To limit the number of results returned from the query, or to skip a given number of results in the query, you may use the skip and take methods: $users = DB::table('users')->skip(10)->take(5)->get(); Alternatively, you may use the limit and offset methods: $users = DB::table('users') ->offset(10) ->limit(5) ->get(); Conditional Clauses Sometimes you may want clauses to apply to a query only when something else is true. For instance you may only want to apply a where statement if a given input value is present on the incoming request. You may accomplish this using the when method: $role = $request->input('role'); $users = DB::table('users') ->when($role, function ($query, $role) { return $query->where('role_id', $role); }) ->get(); The when method only executes the given Closure when the first parameter is true. If the first parameter is false, the Closure will not be executed. You may pass another Closure as the third parameter to the when method. This Closure will execute if the first parameter evaluates as false. To illustrate how this feature may be used, we will use it to configure the default sorting of a query: $sortBy = null; $users = DB::table('users') ->when($sortBy, function ($query, $sortBy) { return $query->orderBy($sortBy); }, function ($query) { return $query->orderBy('name'); }) ->get(); Inserts The query builder also provides an insert method for inserting records into the database table. The insert method accepts an array of column names and values: DB::table('users')->insert( ['email' => '[email protected]', 'votes' => 0] ); You may even insert several records into the table with a single call to insert by passing an array of arrays. Each array represents a row to be inserted into the table: DB::table('users')->insert([ ['email' => '[email protected]', 'votes' => 0], ['email' => '[email protected]', 'votes' => 0] ]); Auto-Incrementing IDs If the table has an auto-incrementing id, use the insertGetId method to insert a record and then retrieve the ID: $id = DB::table('users')->insertGetId( ['email' => '[email protected]', 'votes' => 0] ); When using PostgreSQL the insertGetId method expects the auto-incrementing column to be named id. If you would like to retrieve the ID from a different "sequence", you may pass the column name as the second parameter to the insertGetId method. Updates In addition to inserting records into the database, the query builder can also update existing records using the update method. The update method, like the insert method, accepts an array of column and value pairs containing the columns to be updated. You may constrain the update query using where clauses: DB::table('users') ->where('id', 1) ->update(['votes' => 1]); Update Or Insert Sometimes you may want to update an existing record in the database or create it if no matching record exists. In this scenario, the updateOrInsert method may be used. The updateOrInsert method accepts two arguments: an array of conditions by which to find the record, and an array of column and value pairs containing the columns to be updated. The updateOrInsert method will first attempt to locate a matching database record using the first argument's column and value pairs. If the record exists, it will be updated with the values in the second argument. If the record can not be found, a new record will be inserted with the merged attributes of both arguments: DB::table('users') ->updateOrInsert( ['email' => '[email protected]', 'name' => 'John'], ['votes' => '2'] ); Updating JSON Columns When updating a JSON column, you should use -> syntax to access the appropriate key in the JSON object. This operation is only supported on MySQL 5.7+: DB::table('users') ->where('id', 1) ->update(['options->enabled' => true]); Increment & Decrement The query builder also provides convenient methods for incrementing or decrementing the value of a given column. This is a shortcut, providing a more expressive and terse interface compared to manually writing the update statement. Both of these methods accept at least one argument: the column to modify. A second argument may optionally be passed to control the amount by which the column should be incremented or decremented: DB::table('users')->increment('votes'); DB::table('users')->increment('votes', 5); DB::table('users')->decrement('votes'); DB::table('users')->decrement('votes', 5); You may also specify additional columns to update during the operation: DB::table('users')->increment('votes', 1, ['name' => 'John']); Deletes The query builder may also be used to delete records from the table via the deletemethod. You may constrain delete statements by adding where clauses before calling the delete method: DB::table('users')->delete(); DB::table('users')->where('votes', '>', 100)->delete(); If you wish to truncate the entire table, which will remove all rows and reset the auto-incrementing ID to zero, you may use the truncate method: DB::table('users')->truncate(); Pessimistic Locking The query builder also includes a few functions to help you do "pessimistic locking" on your select statements. To run the statement with a "shared lock", you may use the sharedLock method on a query. A shared lock prevents the selected rows from being modified until your transaction commits: DB::table('users')->where('votes', '>', 100)->sharedLock()->get(); Alternatively, you may use the lockForUpdate method. A "for update" lock prevents the rows from being modified or from being selected with another shared lock: DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get();
Queues [ Running Queue Workers ] { You may run the worker using the queue:work Artisan command; queue workers are long-lived processes and store the booted application state in memory. As a result, they will not notice changes in your code base after they have been started; Specifying The Connection & Queue:php artisan queue:work redis --queue=emails; Single Job php artisan queue:work --once; Processing Jobs & Exiting php artisan queue:work --stop-when-empty; php artisan queue:work --queue=high,low; php artisan queue:restart; retry_after option specifies how many seconds the queue connection should wait before retrying a job that is being processed; The --timeout option specifies how long the Laravel queue master process will wait before killing off a child queue worker that is processing a job; php artisan queue:work --sleep=3 }
Laravel includes a queue worker that will process new jobs as they are pushed onto the queue. You may run the worker using the queue:work Artisan command. Note that once the queue:work command has started, it will continue to run until it is manually stopped or you close your terminal: php artisan queue:work To keep the queue:work process running permanently in the background, you should use a process monitor such as Supervisor to ensure that the queue worker does not stop running. Remember, queue workers are long-lived processes and store the booted application state in memory. As a result, they will not notice changes in your code base after they have been started. So, during your deployment process, be sure to restart your queue workers. Specifying The Connection & Queue You may also specify which queue connection the worker should utilize. The connection name passed to the work command should correspond to one of the connections defined in your config/queue.php configuration file: php artisan queue:work redis You may customize your queue worker even further by only processing particular queues for a given connection. For example, if all of your emails are processed in an emails queue on your redis queue connection, you may issue the following command to start a worker that only processes only that queue: php artisan queue:work redis --queue=emails Processing A Single Job The --once option may be used to instruct the worker to only process a single job from the queue: php artisan queue:work --once Processing All Queued Jobs & Then Exiting The --stop-when-empty option may be used to instruct the worker to process all jobs and then exit gracefully. This option can be useful when working Laravel queues within a Docker container if you wish to shutdown the container after the queue is empty: php artisan queue:work --stop-when-empty Resource Considerations Daemon queue workers do not "reboot" the framework before processing each job. Therefore, you should free any heavy resources after each job completes. For example, if you are doing image manipulation with the GD library, you should free the memory with imagedestroy when you are done. Queue Priorities Sometimes you may wish to prioritize how your queues are processed. For example, in your config/queue.php you may set the default queue for your redis connection to low. However, occasionally you may wish to push a job to a high priority queue like so: dispatch((new Job)->onQueue('high')); To start a worker that verifies that all of the high queue jobs are processed before continuing to any jobs on the low queue, pass a comma-delimited list of queue names to the work command: php artisan queue:work --queue=high,low Queue Workers & Deployment Since queue workers are long-lived processes, they will not pick up changes to your code without being restarted. So, the simplest way to deploy an application using queue workers is to restart the workers during your deployment process. You may gracefully restart all of the workers by issuing the queue:restart command: php artisan queue:restart This command will instruct all queue workers to gracefully "die" after they finish processing their current job so that no existing jobs are lost. Since the queue workers will die when the queue:restart command is executed, you should be running a process manager such as Supervisor to automatically restart the queue workers. The queue uses the cache to store restart signals, so you should verify a cache driver is properly configured for your application before using this feature. Job Expirations & Timeouts Job Expiration In your config/queue.php configuration file, each queue connection defines a retry_after option. This option specifies how many seconds the queue connection should wait before retrying a job that is being processed. For example, if the value of retry_after is set to 90, the job will be released back onto the queue if it has been processing for 90 seconds without being deleted. Typically, you should set the retry_after value to the maximum number of seconds your jobs should reasonably take to complete processing. The only queue connection which does not contain a retry_after value is Amazon SQS. SQS will retry the job based on the Default Visibility Timeout which is managed within the AWS console. Worker Timeouts The queue:work Artisan command exposes a --timeout option. The --timeout option specifies how long the Laravel queue master process will wait before killing off a child queue worker that is processing a job. Sometimes a child queue process can become "frozen" for various reasons, such as an external HTTP call that is not responding. The --timeout option removes frozen processes that have exceeded that specified time limit: php artisan queue:work --timeout=60 The retry_after configuration option and the --timeout CLI option are different, but work together to ensure that jobs are not lost and that jobs are only successfully processed once. The --timeout value should always be at least several seconds shorter than your retry_after configuration value. This will ensure that a worker processing a given job is always killed before the job is retried. If your --timeoutoption is longer than your retry_after configuration value, your jobs may be processed twice. Worker Sleep Duration When jobs are available on the queue, the worker will keep processing jobs with no delay in between them. However, the sleep option determines how long (in seconds) the worker will "sleep" if there are no new jobs available. While sleeping, the worker will not process any new jobs - the jobs will be processed after the worker wakes up again. php artisan queue:work --sleep=3
Queues [ Drivers / Configurations ] { config/queue.php. a database, Beanstalkd, Amazon SQS, Redis, a synchronous driver that will execute jobs immediately (for local use) and null queue driver; there is a connections configuration option. This option defines a particular connection to a backend service however, any given queue connection may have multiple "queues"; each connection configuration example in the queue configuration file contains a queue attribute. This is the default queue that jobs will be dispatched; php artisan queue:work --queue=high,default; Database php artisan queue:table; Redis predis/predis ~1.0 or phpredis PHP extension; 'redis' => [ 'driver' => 'redis', 'connection' => 'default', 'queue' => 'default', 'retry_after' => 90, 'block_for' => 5, ]; Amazon SQS: aws/aws-sdk-php ~3.0; Beanstalkd: pda/pheanstalk ~4.0; }
Laravel now offers Horizon, a beautiful dashboard and configuration system for your Redis powered queues. Check out the full Horizon documentation for more information. Laravel queues provide a unified API across a variety of different queue backends, such as Beanstalk, Amazon SQS, Redis, or even a relational database. Queues allow you to defer the processing of a time consuming task, such as sending an email, until a later time. Deferring these time consuming tasks drastically speeds up web requests to your application. The queue configuration file is stored in config/queue.php. In this file you will find connection configurations for each of the queue drivers that are included with the framework, which includes a database, Beanstalkd, Amazon SQS, Redis, and a synchronous driver that will execute jobs immediately (for local use). A null queue driver is also included which discards queued jobs. Connections Vs. Queues Before getting started with Laravel queues, it is important to understand the distinction between "connections" and "queues". In your config/queue.php configuration file, there is a connections configuration option. This option defines a particular connection to a backend service such as Amazon SQS, Beanstalk, or Redis. However, any given queue connection may have multiple "queues" which may be thought of as different stacks or piles of queued jobs. Note that each connection configuration example in the queue configuration file contains a queue attribute. This is the default queue that jobs will be dispatched to when they are sent to a given connection. In other words, if you dispatch a job without explicitly defining which queue it should be dispatched to, the job will be placed on the queue that is defined in the queue attribute of the connection configuration: // This job is sent to the default queue... Job::dispatch(); // This job is sent to the "emails" queue... Job::dispatch()->onQueue('emails'); Some applications may not need to ever push jobs onto multiple queues, instead preferring to have one simple queue. However, pushing jobs to multiple queues can be especially useful for applications that wish to prioritize or segment how jobs are processed, since the Laravel queue worker allows you to specify which queues it should process by priority. For example, if you push jobs to a high queue, you may run a worker that gives them higher processing priority: php artisan queue:work --queue=high,default Driver Notes & Prerequisites Database In order to use the database queue driver, you will need a database table to hold the jobs. To generate a migration that creates this table, run the queue:table Artisan command. Once the migration has been created, you may migrate your database using the migrate command: php artisan queue:table php artisan migrate Redis In order to use the redis queue driver, you should configure a Redis database connection in your config/database.php configuration file. Redis Cluster If your Redis queue connection uses a Redis Cluster, your queue names must contain a key hash tag. This is required in order to ensure all of the Redis keys for a given queue are placed into the same hash slot: 'redis' => [ 'driver' => 'redis', 'connection' => 'default', 'queue' => '{default}', 'retry_after' => 90, ], Blocking When using the Redis queue, you may use the block_for configuration option to specify how long the driver should wait for a job to become available before iterating through the worker loop and re-polling the Redis database. Adjusting this value based on your queue load can be more efficient than continually polling the Redis database for new jobs. For instance, you may set the value to 5 to indicate that the driver should block for five seconds while waiting for a job to become available: 'redis' => [ 'driver' => 'redis', 'connection' => 'default', 'queue' => 'default', 'retry_after' => 90, 'block_for' => 5, ], Setting block_for to 0 will cause queue workers to block indefinitely until a job is available. This will also prevent signals such as SIGTERM from being handled until the next job has been processed. Other Driver Prerequisites The following dependencies are needed for the listed queue drivers: Amazon SQS: aws/aws-sdk-php ~3.0 Beanstalkd: pda/pheanstalk ~4.0 Redis: predis/predis ~1.0 or phpredis PHP extension
Notifications [ Custom Channels ] { define a class that contains a send method. The method should receive two arguments: a $notifiable and a $notification; Once your notification channel class has been defined, you may return the class name from the via method of any of your notifications public function via($notifiable) { return [VoiceChannel::class]; } public function toVoice($notifiable) { // ... } }
Laravel ships with a handful of notification channels, but you may want to write your own drivers to deliver notifications via other channels. Laravel makes it simple. To get started, define a class that contains a send method. The method should receive two arguments: a $notifiable and a $notification: namespace App\Channels; use Illuminate\Notifications\Notification; class VoiceChannel { /** * Send the given notification. * * @param mixed $notifiable * @param \Illuminate\Notifications\Notification $notification * @return void */ public function send($notifiable, Notification $notification) { $message = $notification->toVoice($notifiable); // Send notification to the $notifiable instance... } } Once your notification channel class has been defined, you may return the class name from the via method of any of your notifications: namespace App\Notifications; use Illuminate\Bus\Queueable; use App\Channels\VoiceChannel; use App\Channels\Messages\VoiceMessage; use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; class InvoicePaid extends Notification { use Queueable; /** * Get the notification channels. * * @param mixed $notifiable * @return array|string */ public function via($notifiable) { return [VoiceChannel::class]; } /** * Get the voice representation of the notification. * * @param mixed $notifiable * @return VoiceMessage */ public function toVoice($notifiable) { // ... } }
Task Scheduling [ Maintenance Mode ] { evenInMaintenanceMode() }
Maintenance Mode Laravel's scheduled tasks will not run when Laravel is in maintenance mode, since we don't want your tasks to interfere with any unfinished maintenance you may be performing on your server. However, if you would like to force a task to run even in maintenance mode, you may use the evenInMaintenanceMode method: $schedule->command('emails:send')->evenInMaintenanceMode();
Notifications [ Markdown ] { php artisan make:notification InvoicePaid --markdown=mail.invoice.paid ; hould define a toMail method on their notification class. However, instead of using the lineand action methods to construct the notification, use the markdown method to specify the name of the Markdown template that should be used; @component('mail::message'); @component('mail::button', ['url' => $url, 'color' => 'green']); @component('mail::panel'); @component('mail::table'); php artisan vendor:publish --tag=laravel-mail; resources/views/vendor/mail; resources/views/vendor/mail/html/themes directory will contain a default.css }
Markdown Mail Notifications Markdown mail notifications allow you to take advantage of the pre-built templates of mail notifications, while giving you more freedom to write longer, customized messages. 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. Generating The Message To generate a notification with a corresponding Markdown template, you may use the --markdown option of the make:notification Artisan command: php artisan make:notification InvoicePaid --markdown=mail.invoice.paid Like all other mail notifications, notifications that use Markdown templates should define a toMail method on their notification class. However, instead of using the lineand action methods to construct the notification, use the markdown method to specify the name of the Markdown template that should be used: /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $url = url('/invoice/'.$this->invoice->id); return (new MailMessage) ->subject('Invoice Paid') ->markdown('mail.invoice.paid', ['url' => $url]); } Writing The Message Markdown mail notifications use a combination of Blade components and Markdown syntax which allow you to easily construct notifications while leveraging Laravel's pre-crafted notification components: @component('mail::message') # Invoice Paid Your invoice has been paid! @component('mail::button', ['url' => $url]) View Invoice @endcomponent Thanks,<br> {{ config('app.name') }} @endcomponent 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 notification as you wish: @component('mail::button', ['url' => $url, 'color' => 'green']) View Invoice @endcomponent 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 notification. This allows you to draw attention to a given block of text: @component('mail::panel') This is the panel content. @endcomponent 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 Customizing The Components You may export all of the Markdown notification 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. 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 notifications. 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.
Events [ Registering Events / Listeners ] { app/Events, app/Listeners, EventServiceProvider listen property, php artisan event:generate, public function boot() { parent::boot(); Event::listen('event.name', function ($foo, $bar) { // }); }; Event::listen('event.*', function ($eventName, array $data) { // }); An event class is a data container which holds the information related to the 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; to stop the propagation of an event to other listeners.returning false from your listener's handle method }
Laravel's events provide 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. 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). 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', ], ]; 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. Events and listeners that already exist will be left untouched: php artisan event:generate 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) { // }); } 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) { // }); 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 ORMobject: namespace App\Events; use App\Order; use Illuminate\Queue\SerializesModels; class OrderShipped { use SerializesModels; public $order; /** * Create a new event instance. * * @param \App\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 Orderinstance 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. 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: namespace App\Listeners; use App\Events\OrderShipped; class SendShipmentNotification { /** * Create the event listener. * * @return void */ public function __construct() { // } /** * Handle the event. * * @param \App\Events\OrderShipped $event * @return void */ public function handle(OrderShipped $event) { // Access the order using $event->order... } } 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. 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.
Mail [ Markdown ] { php artisan make:mail OrderShipped --markdown=emails.orders.shipped; markdown('emails.orders.shipped'); Do not use excess indentation when writing Markdown emails. Markdown parsers will render indented content as code blocks; @component('mail::button', ['url' => $url, 'color' => 'success']); @component('mail::panel'); @component('mail::table'); php artisan vendor:publish --tag=laravel-mail; resources/views/vendor/mail; resources/views/vendor/mail/html/themes directory will contain a default.css; 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. }
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. 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('[email protected]') ->markdown('emails.orders.shipped'); } 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 Do not use excess indentation when writing Markdown emails. Markdown parsers will render indented content as code blocks. Button Component The button component renders a centered button link. The component accepts two arguments, a url and an optional color. Supported colors are primary, success, and error. You may add as many button components to a message as you wish: @component('mail::button', ['url' => $url, 'color' => 'success']) View Order @endcomponent 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 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 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. The components in the html directory are used to generate the HTML version of your email, and their counterparts in the markdown directory are used to generate the plain-text version. You are free to customize these components however you like. 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. 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.
Routing [ Named Routes ] { Generating URLs To Named Routes, Inspecting The Current Route }
Named routes allow the convenient generation of URLs or redirects for specific routes. You may specify a name for a route by chaining the name method onto the route definition: Route::get('user/profile', function () { // })->name('profile'); You may also specify route names for controller actions: Route::get('user/profile', 'UserProfileController@show')->name('profile'); Generating URLs To Named Routes Once you have assigned a name to a given route, you may use the route's name when generating URLs or redirects via the global route function: // Generating URLs... $url = route('profile'); // Generating Redirects... return redirect()->route('profile'); If the named route defines parameters, you may pass the parameters as the second argument to the route function. The given parameters will automatically be inserted into the URL in their correct positions: Route::get('user/{id}/profile', function ($id) { // })->name('profile'); $url = route('profile', ['id' => 1]); Inspecting The Current Route If you would like to determine if the current request was routed to a given named route, you may use the named method on a Route instance. For example, you may check the current route name from a route middleware: /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if ($request->route()->named('profile')) { // } return $next($request); }
Package Development [ Discovery ] { "extra": { "laravel": { "providers": [ "Barryvdh\\Debugbar\\ServiceProvider" ], "aliases": { "Debugbar": "Barryvdh\\Debugbar\\Facade" } } }; "extra": { "laravel": { "dont-discover": [ "barryvdh/laravel-debugbar" ] } }; "extra": { "laravel": { "dont-discover": [ "*" ] } }, }
Packages are the primary way of adding functionality to Laravel. Packages might be anything from a great way to work with dates like Carbon, or an entire BDD testing framework like Behat. There are different types of packages. Some packages are stand-alone, meaning they work with any PHP framework. Carbon and Behat are examples of stand-alone packages. Any of these packages may be used with Laravel by requesting them in your composer.json file. On the other hand, other packages are specifically intended for use with Laravel. These packages may have routes, controllers, views, and configuration specifically intended to enhance a Laravel application. This guide primarily covers the development of those packages that are Laravel specific. A Note On Facades When writing a Laravel application, it generally does not matter if you use contracts or facades since both provide essentially equal levels of testability. However, when writing packages, your package will not typically have access to all of Laravel's testing helpers. If you would like to be able to write your package tests as if they existed inside a typical Laravel application, you may use the Orchestral Testbench package. Package Discovery In a Laravel application's config/app.php configuration file, the providers option defines a list of service providers that should be loaded by Laravel. When someone installs your package, you will typically want your service provider to be included in this list. Instead of requiring users to manually add your service provider to the list, you may define the provider in the extra section of your package's composer.json file. In addition to service providers, you may also list any facades you would like to be registered: "extra": { "laravel": { "providers": [ "Barryvdh\\Debugbar\\ServiceProvider" ], "aliases": { "Debugbar": "Barryvdh\\Debugbar\\Facade" } } }, Once your package has been configured for discovery, Laravel will automatically register its service providers and facades when it is installed, creating a convenient installation experience for your package's users. Opting Out Of Package Discovery If you are the consumer of a package and would like to disable package discovery for a package, you may list the package name in the extra section of your application's composer.json file: "extra": { "laravel": { "dont-discover": [ "barryvdh/laravel-debugbar" ] } }, You may disable package discovery for all packages using the * character inside of your application's dont-discover directive: "extra": { "laravel": { "dont-discover": [ "*" ] } },
Notifications [ Broadcast Notifications ] { The broadcast channel broadcasts notifications using Laravel's event broadcasting services, allowing your JavaScript client to catch notifications in realtime. If a notification supports broadcasting, you should define a toBroadcast method on the notification class. This method will receive a $notifiable entity and should return a BroadcastMessage instance. The returned data will be encoded as JSON and broadcast to your JavaScript client. return (new BroadcastMessage($data)) ->onConnection('sqs') ->onQueue('broadcasts'); Notifications will broadcast on a private channel formatted using a {notifiable}.{id} convention. So, if you are sending a notification to a App\User instance with an ID of 1, the notification will be broadcast on the App.User.1; Echo.private('App.User.' + userId) .notification((notification) => { console.log(notification.type); }); receivesBroadcastNotificationsOn; }
Prerequisites Before broadcasting notifications, you should configure and be familiar with Laravel's event broadcasting services. Event broadcasting provides a way to react to server-side fired Laravel events from your JavaScript client. Formatting Broadcast Notifications The broadcast channel broadcasts notifications using Laravel's event broadcastingservices, allowing your JavaScript client to catch notifications in realtime. If a notification supports broadcasting, you should define a toBroadcast method on the notification class. This method will receive a $notifiable entity and should return a BroadcastMessage instance. The returned data will be encoded as JSON and broadcast to your JavaScript client. Let's take a look at an example toBroadcast method: use Illuminate\Notifications\Messages\BroadcastMessage; /** * Get the broadcastable representation of the notification. * * @param mixed $notifiable * @return BroadcastMessage */ public function toBroadcast($notifiable) { return new BroadcastMessage([ 'invoice_id' => $this->invoice->id, 'amount' => $this->invoice->amount, ]); } Broadcast Queue Configuration All broadcast notifications are queued for broadcasting. If you would like to configure the queue connection or queue name that is used to queue the broadcast operation, you may use the onConnection and onQueue methods of the BroadcastMessage: return (new BroadcastMessage($data)) ->onConnection('sqs') ->onQueue('broadcasts'); In addition to the data you specify, broadcast notifications will also contain a type field containing the class name of the notification. Listening For Notifications Notifications will broadcast on a private channel formatted using a {notifiable}.{id}convention. So, if you are sending a notification to a App\User instance with an ID of 1, the notification will be broadcast on the App.User.1 private channel. When using Laravel Echo, you may easily listen for notifications on a channel using the notificationhelper method: Echo.private('App.User.' + userId) .notification((notification) => { console.log(notification.type); }); Customizing The Notification Channel If you would like to customize which channels a notifiable entity receives its broadcast notifications on, you may define a receivesBroadcastNotificationsOn method on the notifiable entity: namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * The channels the user receives notification broadcasts on. * * @return string */ public function receivesBroadcastNotificationsOn() { return 'users.'.$this->id; } }
Notifications [ Slack Notifications ] { composer require guzzlehttp/guzzle; configure an "Incoming Webhook" integration for your Slack team. This integration will provide you with a URL you may use when routing Slack notifications.; define a toSlackmethod on the notification class. This method will receive a $notifiable entity and should return a Illuminate\Notifications\Messages\SlackMessage instance. Slack messages may contain text content as well as an "attachment" that formats additional text or an array of fields; You may use the from and to methods to customize the sender and recipient. The frommethod accepts a username and emoji identifier, while the to method accepts a channel or username; image('https://laravel.com/favicon.png'); attachment(function ($attachment) use ($url) { $attachment->title('Exception: File Not Found', $url) ->content('File [background.jpg] was not found.'); }); $attachment->title('Invoice 1322', $url) ->fields([ 'Title' => 'Server Expenses', 'Amount' => '$1,234', 'Via' => 'American Express', 'Was Overdue' => ':-1:', ]); $attachment->title('Exception: File Not Found', $url) ->content('File [background.jpg] was *not found*.') ->markdown(['text']); define a routeNotificationForSlackmethod on your notifiable entity; }
Prerequisites Before you can send notifications via Slack, you must install the Guzzle HTTP library via Composer: composer require guzzlehttp/guzzle You will also need to configure an "Incoming Webhook" integration for your Slack team. This integration will provide you with a URL you may use when routing Slack notifications. Formatting Slack Notifications If a notification supports being sent as a Slack message, you should define a toSlackmethod on the notification class. This method will receive a $notifiable entity and should return a Illuminate\Notifications\Messages\SlackMessage instance. Slack messages may contain text content as well as an "attachment" that formats additional text or an array of fields. Let's take a look at a basic toSlack example: /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { return (new SlackMessage) ->content('One of your invoices has been paid!'); } In this example we are just sending a single line of text to Slack, which will create a message that looks like the following: Customizing The Sender & Recipient You may use the from and to methods to customize the sender and recipient. The frommethod accepts a username and emoji identifier, while the to method accepts a channel or username: /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { return (new SlackMessage) ->from('Ghost', ':ghost:') ->to('#other') ->content('This will be sent to #other'); } You may also use an image as your logo instead of an emoji: /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { return (new SlackMessage) ->from('Laravel') ->image('https://laravel.com/favicon.png') ->content('This will display the Laravel logo next to the message'); } Slack Attachments You may also add "attachments" to Slack messages. Attachments provide richer formatting options than simple text messages. In this example, we will send an error notification about an exception that occurred in an application, including a link to view more details about the exception: /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { $url = url('/exceptions/'.$this->exception->id); return (new SlackMessage) ->error() ->content('Whoops! Something went wrong.') ->attachment(function ($attachment) use ($url) { $attachment->title('Exception: File Not Found', $url) ->content('File [background.jpg] was not found.'); }); } The example above will generate a Slack message that looks like the following: Attachments also allow you to specify an array of data that should be presented to the user. The given data will be presented in a table-style format for easy reading: /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { $url = url('/invoices/'.$this->invoice->id); return (new SlackMessage) ->success() ->content('One of your invoices has been paid!') ->attachment(function ($attachment) use ($url) { $attachment->title('Invoice 1322', $url) ->fields([ 'Title' => 'Server Expenses', 'Amount' => '$1,234', 'Via' => 'American Express', 'Was Overdue' => ':-1:', ]); }); } The example above will create a Slack message that looks like the following: Markdown Attachment Content If some of your attachment fields contain Markdown, you may use the markdown method to instruct Slack to parse and display the given attachment fields as Markdown formatted text. The values accepted by this method are: pretext, text, and / or fields. For more information about Slack attachment formatting, check out the Slack API documentation: /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { $url = url('/exceptions/'.$this->exception->id); return (new SlackMessage) ->error() ->content('Whoops! Something went wrong.') ->attachment(function ($attachment) use ($url) { $attachment->title('Exception: File Not Found', $url) ->content('File [background.jpg] was *not found*.') ->markdown(['text']); }); } Routing Slack Notifications To route Slack notifications to the proper location, define a routeNotificationForSlackmethod on your notifiable entity. This should return the webhook URL to which the notification should be delivered. Webhook URLs may be generated by adding an "Incoming Webhook" service to your Slack team: use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * Route notifications for the Slack channel. * * @param \Illuminate\Notifications\Notification $notification * @return string */ public function routeNotificationForSlack($notification) { return 'https://hooks.slack.com/services/...'; } }
Notifications [ SMS Notifications ] { powered by Nexmo., you need to install the nexmo/client, config/services.php: 'nexmo' => [ 'key' => env('NEXMO_KEY'), 'secret' => env('NEXMO_SECRET'), 'sms_from' => '15556666666', ], you should define a toNexmo method on the notification class. This method will receive a $notifiable entity and should return a Illuminate\Notifications\Messages\NexmoMessage instance; unicode(); from('15554443333'); public function routeNotificationForNexmo($notification) { return $this->phone; }}
Prerequisites Sending SMS notifications in Laravel is powered by Nexmo. Before you can send notifications via Nexmo, you need to install the nexmo/client Composer package and add a few configuration options to your config/services.php configuration file. You may copy the example configuration below to get started: 'nexmo' => [ 'key' => env('NEXMO_KEY'), 'secret' => env('NEXMO_SECRET'), 'sms_from' => '15556666666', ], The sms_from option is the phone number that your SMS messages will be sent from. You should generate a phone number for your application in the Nexmo control panel. Formatting SMS Notifications If a notification supports being sent as an SMS, you should define a toNexmo method on the notification class. This method will receive a $notifiable entity and should return a Illuminate\Notifications\Messages\NexmoMessage instance: /** * Get the Nexmo / SMS representation of the notification. * * @param mixed $notifiable * @return NexmoMessage */ public function toNexmo($notifiable) { return (new NexmoMessage) ->content('Your SMS message content'); } Unicode Content If your SMS message will contain unicode characters, you should call the unicodemethod when constructing the NexmoMessage instance: /** * Get the Nexmo / SMS representation of the notification. * * @param mixed $notifiable * @return NexmoMessage */ public function toNexmo($notifiable) { return (new NexmoMessage) ->content('Your unicode message') ->unicode(); } Customizing The "From" Number If you would like to send some notifications from a phone number that is different from the phone number specified in your config/services.php file, you may use the frommethod on a NexmoMessage instance: /** * Get the Nexmo / SMS representation of the notification. * * @param mixed $notifiable * @return NexmoMessage */ public function toNexmo($notifiable) { return (new NexmoMessage) ->content('Your SMS message content') ->from('15554443333'); } Routing SMS Notifications When sending notifications via the nexmo channel, the notification system will automatically look for a phone_number attribute on the notifiable entity. If you would like to customize the phone number the notification is delivered to, define a routeNotificationForNexmo method on the entity: namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * Route notifications for the Nexmo channel. * * @param \Illuminate\Notifications\Notification $notification * @return string */ public function routeNotificationForNexmo($notification) { return $this->phone; } }
Notifications [ Database Notifications ] { php artisan notifications:table && php artisan migrate; should define a toDatabase or toArray method on the notification class. This method will receive a $notifiable entity and should return a plain PHP array. The toArray method is also used by the broadcast channel to determine which data to broadcast to your JavaScript client. If you would like to have two different array representations for the database and broadcast channels, you should define a toDatabase method instead of a toArray method; The Illuminate\Notifications\Notifiable trait, which is included on Laravel's default App\User model, includes a notifications Eloquent relationship that returns the notifications for the entity; $user->notifications; $user->unreadNotifications; $notification->markAsRead(); $user->unreadNotifications->markAsRead(); $user->unreadNotifications()->update(['read_at' => now()]);}
Prerequisites The database notification channel stores the notification information in a database table. This table will contain information such as the notification type as well as custom JSON data that describes the notification. You can query the table to display the notifications in your application's user interface. But, before you can do that, you will need to create a database table to hold your notifications. You may use the notifications:table command to generate a migration with the proper table schema: php artisan notifications:table php artisan migrate Formatting Database Notifications If a notification supports being stored in a database table, you should define a toDatabase or toArray method on the notification class. This method will receive a $notifiable entity and should return a plain PHP array. The returned array will be encoded as JSON and stored in the data column of your notifications table. Let's take a look at an example toArray method: /** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toArray($notifiable) { return [ 'invoice_id' => $this->invoice->id, 'amount' => $this->invoice->amount, ]; } toDatabase Vs. toArray The toArray method is also used by the broadcast channel to determine which data to broadcast to your JavaScript client. If you would like to have two different array representations for the database and broadcast channels, you should define a toDatabase method instead of a toArray method. Accessing The Notifications Once notifications are stored in the database, you need a convenient way to access them from your notifiable entities. The Illuminate\Notifications\Notifiable trait, which is included on Laravel's default App\User model, includes a notifications Eloquent relationship that returns the notifications for the entity. To fetch notifications, you may access this method like any other Eloquent relationship. By default, notifications will be sorted by the created_at timestamp: $user = App\User::find(1); foreach ($user->notifications as $notification) { echo $notification->type; } If you want to retrieve only the "unread" notifications, you may use the unreadNotifications relationship. Again, these notifications will be sorted by the created_at timestamp: $user = App\User::find(1); foreach ($user->unreadNotifications as $notification) { echo $notification->type; } To access your notifications from your JavaScript client, you should define a notification controller for your application which returns the notifications for a notifiable entity, such as the current user. You may then make an HTTP request to that controller's URI from your JavaScript client. Marking Notifications As Read Typically, you will want to mark a notification as "read" when a user views it. The Illuminate\Notifications\Notifiable trait provides a markAsRead method, which updates the read_at column on the notification's database record: $user = App\User::find(1); foreach ($user->unreadNotifications as $notification) { $notification->markAsRead(); } However, instead of looping through each notification, you may use the markAsReadmethod directly on a collection of notifications: $user->unreadNotifications->markAsRead(); You may also use a mass-update query to mark all of the notifications as read without retrieving them from the database: $user = App\User::find(1); $user->unreadNotifications()->update(['read_at' => now()]); You may delete the notifications to remove them from the table entirely: $user->notifications()->delete();
Package Development [ Service Providers ] { Service providers are the connection points between your package and Laravel. A service provider is responsible for binding things into Laravel's service container and informing Laravel where to load package resources such as views, configuration, and localization files. A service provider extends the Illuminate\Support\ServiceProvider class and contains two methods: register and boot. The base ServiceProvider class is located in the illuminate/support Composer package, which you should add to your own package's dependencies. }
Service providers are the connection points between your package and Laravel. A service provider is responsible for binding things into Laravel's service container and informing Laravel where to load package resources such as views, configuration, and localization files. A service provider extends the Illuminate\Support\ServiceProvider class and contains two methods: register and boot. The base ServiceProvider class is located in the illuminate/support Composer package, which you should add to your own package's dependencies. To learn more about the structure and purpose of service providers, check out their documentation.
Queues [ Handling Failed Jobs ] { php artisan queue:failed-table; define a failed method directly on your job class, allowing you to perform job specific clean-up when a failure occurs; register an event that will be called when a job fails, you may use the Queue::failing method; To view all of your failed jobs that have been inserted into your failed_jobs database table, you may use the queue:failed Artisan command; The job ID may be used to retry the failed job php artisan queue:retry 5; php artisan queue:retry all; php artisan queue:forget 5; php artisan queue:flush; }
Sometimes your queued jobs will fail. Don't worry, things don't always go as planned! Laravel includes a convenient way to specify the maximum number of times a job should be attempted. After a job has exceeded this amount of attempts, it will be inserted into the failed_jobs database table. To create a migration for the failed_jobstable, you may use the queue:failed-table command: php artisan queue:failed-table php artisan migrate Then, when running your queue worker, you should specify the maximum number of times a job should be attempted using the --tries switch on the queue:work command. If you do not specify a value for the --tries option, jobs will be attempted indefinitely: php artisan queue:work redis --tries=3 Cleaning Up After Failed Jobs You may define a failed method directly on your job class, allowing you to perform job specific clean-up when a failure occurs. This is the perfect location to send an alert to your users or revert any actions performed by the job. The Exception that caused the job to fail will be passed to the failed method: use Exception; use App\Podcast; use App\AudioProcessor; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; class ProcessPodcast implements ShouldQueue { use InteractsWithQueue, Queueable, SerializesModels; protected $podcast; /** * Create a new job instance. * * @param Podcast $podcast * @return void */ public function __construct(Podcast $podcast) { $this->podcast = $podcast; } /** * Execute the job. * * @param AudioProcessor $processor * @return void */ public function handle(AudioProcessor $processor) { // Process uploaded podcast... } /** * The job failed to process. * * @param Exception $exception * @return void */ public function failed(Exception $exception) { // Send user notification of failure, etc... } } Failed Job Events If you would like to register an event that will be called when a job fails, you may use the Queue::failing method. This event is a great opportunity to notify your team via email or Slack. For example, we may attach a callback to this event from the AppServiceProvider that is included with Laravel: namespace App\Providers; use Illuminate\Support\Facades\Queue; use Illuminate\Queue\Events\JobFailed; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { Queue::failing(function (JobFailed $event) { // $event->connectionName // $event->job // $event->exception }); } /** * Register the service provider. * * @return void */ public function register() { // } } Retrying Failed Jobs To view all of your failed jobs that have been inserted into your failed_jobs database table, you may use the queue:failed Artisan command: php artisan queue:failed The queue:failed command will list the job ID, connection, queue, and failure time. The job ID may be used to retry the failed job. For instance, to retry a failed job that has an ID of 5, issue the following command: php artisan queue:retry 5 To retry all of your failed jobs, execute the queue:retry command and pass all as the ID: php artisan queue:retry all If you would like to delete a failed job, you may use the queue:forget command: php artisan queue:forget 5 To delete all of your failed jobs, you may use the queue:flush command: php artisan queue:flush Ignoring Missing Models When injecting an Eloquent model into a job, it is automatically serialized before being placed on the queue and restored when the job is processed. However, if the model has been deleted while the job was waiting to be processed by a worker, your job may fail with a ModelNotFoundException. For convenience, you may choose to automatically delete jobs with missing models by setting your job's deleteWhenMissingModels property to true: /** * Delete the job if its models no longer exist. * * @var bool */ public $deleteWhenMissingModels = true;
URL Generation [ Controller Actions ] { action('HomeController@index'); action([HomeController::class, 'index']); action('UserController@profile', ['id' => 1]);}
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'); You may also reference actions with a "callable" array syntax: use App\Http\Controllers\HomeController; $url = action([HomeController::class, 'index']); If the controller method accepts route parameters, you may pass them as the second argument to the function: $url = action('UserController@profile', ['id' => 1]);
Task Scheduling [ Scheduling Shell Commands ] { exec method }
The exec method may be used to issue a command to the operating system:
Task Scheduling [ Scheduling Queue Jobs ] { $schedule->job(new Heartbeat)->everyFiveMinutes(); // Dispatch the job to the "heartbeats" queue... $schedule->job(new Heartbeat, 'heartbeats')->everyFiveMinutes(); }
The job method may be used to schedule a queued job. This method provides a convenient way to schedule jobs without using the call method to manually create Closures to queue the job: $schedule->job(new Heartbeat)->everyFiveMinutes(); // Dispatch the job to the "heartbeats" queue... $schedule->job(new Heartbeat, 'heartbeats')->everyFiveMinutes();
Task Scheduling [ Time Zones ] { timezone('America/New_York'); }
Using the timezone method, you may specify that a scheduled task's time should be interpreted within a given timezone: $schedule->command('report:generate') ->timezone('America/New_York') ->at('02:00') Remember that some timezones utilize daylight savings time. When daylight saving time changes occur, your scheduled task may run twice or even not run at all. For this reason, we recommend avoiding timezone scheduling when possible.
URL Generation [ Named Routes ] { route('post.show', ['post' => 1]); URL::signedRoute('unsubscribe', ['user' => 1]); URL::temporarySignedRoute( 'unsubscribe', now()->addMinutes(30), ['user' => 1] ); $request->hasValidSignature(); Route::post('/unsubscribe/{user}', function (Request $request) { // ... })->name('unsubscribe')->middleware('signed'); }
The route helper may be used to generate URLs to named routes. Named routes allow you to generate URLs without being coupled to the actual URL defined on the route. Therefore, if the route's URL changes, no changes need to be made to your routefunction calls. For example, imagine your application contains a route defined like the following: Route::get('/post/{post}', function () { // })->name('post.show'); To generate a URL to this route, you may use the route helper like so: echo route('post.show', ['post' => 1]); // http://example.com/post/1 You will often be generating URLs using the primary key of Eloquent models. For this reason, you may pass Eloquent models as parameter values. The route helper will automatically extract the model's primary key: echo route('post.show', ['post' => $post]); The route helper may also be used to generate URLs for routes with multiple parameters: Route::get('/post/{post}/comment/{comment}', function () { // })->name('comment.show'); echo route('comment.show', ['post' => 1, 'comment' => 3]); // http://example.com/post/1/comment/3 Signed URLs Laravel allows you to easily create "signed" URLs to named routes. These URLs have a "signature" hash appended to the query string which allows Laravel to verify that the URL has not been modified since it was created. Signed URLs are especially useful for routes that are publicly accessible yet need a layer of protection against URL manipulation. For example, you might use signed URLs to implement a public "unsubscribe" link that is emailed to your customers. To create a signed URL to a named route, use the signedRoute method of the URL facade: use Illuminate\Support\Facades\URL; return URL::signedRoute('unsubscribe', ['user' => 1]); If you would like to generate a temporary signed route URL that expires, you may use the temporarySignedRoute method: use Illuminate\Support\Facades\URL; return URL::temporarySignedRoute( 'unsubscribe', now()->addMinutes(30), ['user' => 1] ); Validating Signed Route Requests To verify that an incoming request has a valid signature, you should call the hasValidSignature method on the incoming Request: use Illuminate\Http\Request; Route::get('/unsubscribe/{user}', function (Request $request) { if (! $request->hasValidSignature()) { abort(401); } // ... })->name('unsubscribe'); Alternatively, you may assign the Illuminate\Routing\Middleware\ValidateSignaturemiddleware to the route. If it is not already present, you should assign this middleware a key in your HTTP kernel's routeMiddleware array: /** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array */ protected $routeMiddleware = [ 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, ]; Once you have registered the middleware in your kernel, you may attach it to a route. If the incoming request does not have a valid signature, the middleware will automatically return a 403 error response: Route::post('/unsubscribe/{user}', function (Request $request) { // ... })->name('unsubscribe')->middleware('signed');
Package Development [ Publishing File Groups ] { public function boot() { $this->publishes([ __DIR__.'/../config/package.php' => config_path('package.php') ], 'config'); $this->publishes([ __DIR__.'/../database/migrations/' => database_path('migrations') ], 'migrations'); }; php artisan vendor:publish --tag=config }
You may want to publish groups of package assets and resources separately. For instance, you might want to allow your users to publish your package's configuration files without being forced to publish your package's assets. You may do this by "tagging" them when calling the publishes method from a package's service provider. For example, let's use tags to define two publish groups in the boot method of a package service provider: /** * Bootstrap any application services. * * @return void */ public function boot() { $this->publishes([ __DIR__.'/../config/package.php' => config_path('package.php') ], 'config'); $this->publishes([ __DIR__.'/../database/migrations/' => database_path('migrations') ], 'migrations'); } Now your users may publish these groups separately by referencing their tag when executing the vendor:publish command: php artisan vendor:publish --tag=config
Package Development [ Assets ] { Public Assets: public function boot() { $this->publishes([ __DIR__.'/path/to/assets' => public_path('vendor/courier'), ], 'public'); } php artisan vendor:publish --tag=public --force }
Your package may have assets such as JavaScript, CSS, and images. To publish these assets to the application's public directory, use the service provider's publishesmethod. In this example, we will also add a public asset group tag, which may be used to publish groups of related assets: /** * Bootstrap any application services. * * @return void */ public function boot() { $this->publishes([ __DIR__.'/path/to/assets' => public_path('vendor/courier'), ], 'public'); } Now, when your package's users execute the vendor:publish command, your assets will be copied to the specified publish location. Since you will typically need to overwrite the assets every time the package is updated, you may use the --force flag: php artisan vendor:publish --tag=public --force
Helper Methods [ Strings ] { __, Str::camel, class_basename, e, Str::endsWith, Str::kebab, preg_replace_array, Str::snake, Str::startsWith, Str::after, Str::before, Str::contains, Str::finish, Str::is, Str::limit, Str::orderedUuid, Str::plural, Str::random, Str::replaceArray, Str::replaceFirst, Str::replaceLast, Str::singular, Str::slug, Str::start, Str::studly, Str::title, trans, trans_choice, Str::uuid }
__() 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. Str::camel() The Str::camel method converts the given string to camelCase: use Illuminate\Support\Str; $converted = Str::camel('foo_bar'); // fooBar class_basename() The class_basename function returns the class name of the given class with the class' namespace removed: $class = class_basename('Foo\Bar\Baz'); // Baz e() The e function runs PHP's htmlspecialchars function with the double_encode option set to true by default: echo e('<html>foo</html>'); // <html>foo</html> Str::endsWith() The Str::endsWith method determines if the given string ends with the given value: use Illuminate\Support\Str; $result = Str::endsWith('This is my name', 'name'); // true Str::kebab() The Str::kebab method converts the given string to kebab-case: use Illuminate\Support\Str; $converted = Str::kebab('fooBar'); // foo-bar preg_replace_array() 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 Str::snake() The Str::snake method converts the given string to snake_case: use Illuminate\Support\Str; $converted = Str::snake('fooBar'); // foo_bar Str::startsWith() The Str::startsWith method determines if the given string begins with the given value: use Illuminate\Support\Str; $result = Str::startsWith('This is my name', 'This'); // true Str::after() The Str::after method returns everything after the given value in a string: use Illuminate\Support\Str; $slice = Str::after('This is my name', 'This is'); // ' my name' Str::before() The Str::before method returns everything before the given value in a string: use Illuminate\Support\Str; $slice = Str::before('This is my name', 'my name'); // 'This is ' Str::contains() The Str::contains method determines if the given string contains the given value (case sensitive): use Illuminate\Support\Str; $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: use Illuminate\Support\Str; $contains = Str::contains('This is my name', ['my', 'foo']); // true Str::finish() The Str::finish method adds a single instance of the given value to a string if it does not already end with the value: use Illuminate\Support\Str; $adjusted = Str::finish('this/string', '/'); // this/string/ $adjusted = Str::finish('this/string/', '/'); // this/string/ Str::is() The Str::is method determines if a given string matches a given pattern. Asterisks may be used to indicate wildcards: use Illuminate\Support\Str; $matches = Str::is('foo*', 'foobar'); // true $matches = Str::is('baz*', 'foobar'); // false Str::limit() The Str::limit method truncates the given string at the specified length: use Illuminate\Support\Str; $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: use Illuminate\Support\Str; $truncated = Str::limit('The quick brown fox jumps over the lazy dog', 20, ' (...)'); // The quick brown fox (...) Str::orderedUuid() The Str::orderedUuid method generates a "timestamp first" UUID that may be efficiently stored in an indexed database column: use Illuminate\Support\Str; return (string) Str::orderedUuid(); Str::plural() The Str::plural method converts a string to its plural form. This function currently only supports the English language: use Illuminate\Support\Str; $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: use Illuminate\Support\Str; $plural = Str::plural('child', 2); // children $plural = Str::plural('child', 1); // child Str::random() The Str::random method generates a random string of the specified length. This function uses PHP's random_bytes function: use Illuminate\Support\Str; $random = Str::random(40); Str::replaceArray() The Str::replaceArray method replaces a given value in the string sequentially using an array: use Illuminate\Support\Str; $string = 'The event will take place between ? and ?'; $replaced = Str::replaceArray('?', ['8:30', '9:00'], $string); // The event will take place between 8:30 and 9:00 Str::replaceFirst() The Str::replaceFirst method replaces the first occurrence of a given value in a string: use Illuminate\Support\Str; $replaced = Str::replaceFirst('the', 'a', 'the quick brown fox jumps over the lazy dog'); // a quick brown fox jumps over the lazy dog Str::replaceLast() The Str::replaceLast method replaces the last occurrence of a given value in a string: use Illuminate\Support\Str; $replaced = Str::replaceLast('the', 'a', 'the quick brown fox jumps over the lazy dog'); // the quick brown fox jumps over a lazy dog Str::singular() The Str::singular method converts a string to its singular form. This function currently only supports the English language: use Illuminate\Support\Str; $singular = Str::singular('cars'); // car $singular = Str::singular('children'); // child Str::slug() The Str::slug method generates a URL friendly "slug" from the given string: use Illuminate\Support\Str; $slug = Str::slug('Laravel 5 Framework', '-'); // laravel-5-framework Str::start() The Str::start method adds a single instance of the given value to a string if it does not already start with the value: use Illuminate\Support\Str; $adjusted = Str::start('this/string', '/'); // /this/string $adjusted = Str::start('/this/string', '/'); // /this/string Str::studly() The Str::studly method converts the given string to StudlyCase: use Illuminate\Support\Str; $converted = Str::studly('foo_bar'); // FooBar Str::title() The Str::title method converts the given string to Title Case: use Illuminate\Support\Str; $converted = Str::title('a nice title uses the correct case'); // A Nice Title Uses The Correct Case trans() 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. trans_choice() 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. Str::uuid() The Str::uuid method generates a UUID (version 4): use Illuminate\Support\Str; return (string) Str::uuid();
Views [ Passing Data to Views ] { view('greetings', ['name' => 'Victoria']); view('greeting')->with('name', 'Victoria'); View::share('key', 'value'); }
you may pass an array of data to views: return view('greetings', ['name' => 'Victoria']); When passing information in this manner, the data should be an array with key / value pairs. Inside your view, you can then access each value using its corresponding key. As an alternative to passing a complete array of data to the view helper function, you may use the with method to add individual pieces of data to the view: return view('greeting')->with('name', 'Victoria'); Sharing Data With All Views Occasionally, you may need to share a piece of data with all views that are rendered by your application. You may do so using the view facade's share method. Typically, you should place calls to share within a service provider's boot method. You are free to add them to the AppServiceProvider or generate a separate service provider to house them public function boot() { View::share('key', 'value'); }
Helper Methods [ Paths ] { app_path, base_path, config_path, database_path, mix, public_path, resource_path, storage_path }
app_path() 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'); base_path() 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'); config_path() 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'); database_path() 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'); mix() The mix function returns the path to a versioned Mix file: $path = mix('css/app.css'); public_path() 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'); resource_path() 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('sass/app.scss'); storage_path() 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');
Architecture [ Facades ] { Introduction, When To Use Facades, Facades Vs. Dependency Injection, Facades Vs. Helper Functions, How Facades Work, Real-Time Facades }
Introduction Facades provide a "static" interface to classes that are available in the application's service container. 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'); }); 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. 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. 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'); } 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. 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. 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 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 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:
Architecture [ Service Providers ] { config/app.php providers array, Writing Service Providers, The Register Method, The Boot Method, Registering Providers, Deferred Providers }
Introduction Service providers are the central place of all Laravel application bootstrapping. In general, we mean registering things, including registering service container bindings, event listeners, middleware, and even routes. Service providers are the central place to configure your application. If you open the config/app.php file included with Laravel, you will see a providers array. These are all of the service provider classes that will be loaded for your application. Note that many of these are "deferred" providers, meaning they will not be loaded on every request, but only when the services they provide are actually needed. Writing Service Providers All service providers extend the Illuminate\Support\ServiceProvider class. Most service providers contain a register and a boot method. Within the register method, you should only bind things into the service container. You should never attempt to register any event listeners, routes, or any other piece of functionality within the register method. The Artisan CLI can generate a new provider via the make:provider command: php artisan make:provider RiakServiceProvider The Register Method As mentioned previously, within the register method, you should only bind things into the service container. You should never attempt to register any event listeners, routes, or any other piece of functionality within the register method. Otherwise, you may accidentally use a service that is provided by a service provider which has not loaded yet. Let's take a look at a basic service provider. Within any of your service provider methods, you always have access to the $app property which provides access to the service container The bindings And singletons Properties If your service provider registers many simple bindings, you may wish to use the bindings and singletons properties instead of manually registering each container binding. When the service provider is loaded by the framework, it will automatically check for these properties and register their bindings The Boot Method So, what if we need to register a view composer within our service provider? This should be done within the boot method. This method is called after all other service providers have been registered, meaning you have access to all other services that have been registered by the framework Boot Method Dependency Injection You may type-hint dependencies for your service provider's boot method. The service container will automatically inject any dependencies you need: use Illuminate\Contracts\Routing\ResponseFactory; public function boot(ResponseFactory $response) { $response->macro('caps', function ($value) { // }); } Registering Providers All service providers are registered in the config/app.php configuration file. This file contains a providers array where you can list the class names of your service providers. By default, a set of Laravel core service providers are listed in this array. These providers bootstrap the core Laravel components, such as the mailer, queue, cache, and others. To register your provider, add it to the array: 'providers' => [ // Other Service Providers App\Providers\ComposerServiceProvider::class, ], Deferred Providers If your provider is only registering bindings in the service container, you may choose to defer its registration until one of the registered bindings is actually needed. Deferring the loading of such a provider will improve the performance of your application, since it is not loaded from the filesystem on every request. Laravel compiles and stores a list of all of the services supplied by deferred service providers, along with the name of its service provider class. Then, only when you attempt to resolve one of these services does Laravel load the service provider. To defer the loading of a provider, set the defer property to true and define a provides method. The provides method should return the service container bindings registered by the provider: namespace App\Providers; use Riak\Connection; use Illuminate\Support\ServiceProvider; class RiakServiceProvider extends ServiceProvider { /** * Indicates if loading of the provider is deferred. * * @var bool */ protected $defer = true; /** * Register the service provider. * * @return void */ public function register() { $this->app->singleton(Connection::class, function ($app) { return new Connection($app['config']['riak']); }); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return [Connection::class]; } }
Middleware [ 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: 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');
Routing [ Redirects ] { Route::redirect('/here', '/there', 302); Route::permanentRedirect('/here', '/there'); }
Redirect Routes If you are defining a route that redirects to another URI, you may use the Route::redirect method. This method provides a convenient shortcut so that you do not have to define a full route or controller for performing a simple redirect: Route::redirect('/here', '/there'); By default, Route::redirect returns a 302 status code. You may customize the status code using the optional third parameter: Route::redirect('/here', '/there', 301); You may use the Route::permanentRedirect method to return a 301 status code: Route::permanentRedirect('/here', '/there');
Mail [ Writing Mail ] { 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. $this->from('[email protected]'), you may specify a global "from" address in your config/mail.php; 'from' => ['address' => '[email protected]', 'name' => 'App Name']; In addition, you may define a global "reply_to" address within your config/mail.phpconfiguration file: 'reply_to' => ['address' => '[email protected]', 'name' => 'App Name'], $this->view('emails.orders.shipped'); ->text('emails.orders.shipped_plain')}; View Data Via Public Properties; Via The with Method; attach('/path/to/file', [ 'as' => 'name.pdf', 'mime' => 'application/pdf', ]); attachFromStorage('/path/to/file', 'name.pdf', [ 'mime' => 'application/pdf' ]); attachFromStorageDisk('s3', '/path/to/file'); attachData($this->pdf, 'name.pdf', [ 'mime' => 'application/pdf', ]); $message->embed($pathToImage); $message->embedData($data, $name); $this->withSwiftMessage(function ($message) { $message->getHeaders() ->addTextHeader('Custom-Header', 'HeaderValue'); }); }
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. Configuring The Sender 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('[email protected]') ->view('emails.orders.shipped'); } 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' => '[email protected]', 'name' => 'App Name'], In addition, you may define a global "reply_to" address within your config/mail.phpconfiguration file: 'reply_to' => ['address' => '[email protected]', 'name' => 'App Name'], 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'); } 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. Plain Text Emails If you would like to define a plain-text version of your email, you may use the textmethod. 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'); } View Data 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: 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> 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: 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> 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', ]); } Attaching Files from Disk If you have stored a file on one of your filesystem disks, you may attach it to the email using the attachFromStorage method: /** * Build the message. * * @return $this */ public function build() { return $this->view('email.orders.shipped') ->attachFromStorage('/path/to/file'); } If necessary, you may specify the file's attachment name and additional options using the second and third arguments to the attachFromStorage method: /** * Build the message. * * @return $this */ public function build() { return $this->view('email.orders.shipped') ->attachFromStorage('/path/to/file', 'name.pdf', [ 'mime' => 'application/pdf' ]); } The attachFromStorageDisk method may be used if you need to specify a storage disk other than your default disk: /** * Build the message. * * @return $this */ public function build() { return $this->view('email.orders.shipped') ->attachFromStorageDisk('s3', '/path/to/file'); } 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', ]); } 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 $messagevariable 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($pathToImage) }}"> </body> $message variable is not available in markdown messages. 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> 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'); }); }
Artisan Console [ Registering Commands ] { load method in console kernel's commands method, all commands registered within the app/Console/Commands, $commands property of your app/Console/Kernel.php }
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 $commandsproperty 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 ];
Logging [ Configuration ] { config/logging.php, stack, single, daily, slack, syslog, errorlog, monolog, custom, Log Levels }
All of the configuration for your application's logging system is housed in the config/logging.php configuration file. This file allows you to configure your application's log channels, so be sure to review each of the available channels and their options. We'll review a few common options below. By default, Laravel will use the stack channel when logging messages. The stack channel is used to aggregate multiple log channels into a single channel. Configuring The Channel Name By default, Monolog is instantiated with a "channel name" that matches the current environment, such as production or local. To change this value, add a name option to your channel's configuration: 'stack' => [ 'driver' => 'stack', 'name' => 'channel-name', 'channels' => ['single', 'slack'], ], Available Channel Drivers Name Description stack A wrapper to facilitate creating "multi-channel" channels single A single file or path based logger channel (StreamHandler) daily A RotatingFileHandler based Monolog driver which rotates daily slack A SlackWebhookHandler based Monolog driver syslog A SyslogHandler based Monolog driver errorlog A ErrorLogHandler based Monolog driver monolog A Monolog factory driver that may use any supported Monolog handler custom A driver that calls a specified factory to create a channel Configuring The Single and Daily Channels The single and daily channels have three optional configuration options: bubble, permission, and locking. bubble Indicates if messages should bubble up to other channels after being handled (default true), permission The log file's permissions (default 0644), locking Attempt to lock the log file before writing to it (default false) Configuring The Slack Channel The slack channel requires a url configuration option. This URL should match a URL for an incoming webhook that you have configured for your Slack team Building Log Stacks As previously mentioned, the stack driver allows you to combine multiple channels into a single log channel. To illustrate how to use log stacks, let's take a look at an example configuration that you might see in a production application 'stack' => [ 'driver' => 'stack', 'channels' => ['syslog', 'slack'], ], Let's dissect this configuration. First, notice our stack channel aggregates two other channels via its channels option: syslog and slack. So, when logging messages, both of these channels will have the opportunity to log the message. Log Levels Take note of the level configuration option present on the syslog and slack channel configurations in the example above. This option determines the minimum "level" a message must be in order to be logged by the channel. Monolog, which powers Laravel's logging services, offers all of the log levels defined in the RFC 5424 specification: emergency, alert, critical, error, warning, notice, info, and debug.
Helper Methods [ Arrays / Objects ] { Arr::add, Arr::collapse, Arr::divide, Arr::dot, Arr::except, Arr::first, Arr::flatten, Arr::forget, Arr::get, Arr::has, Arr::last, Arr::only, Arr::pluck, Arr::prepend, Arr::pull, Arr::random, Arr::set, Arr::sort, Arr::sortRecursive, Arr::where, Arr::wrap, data_fill, data_get, data_set, head, last }
Arr::add() The Arr::add method adds a given key / value pair to an array if the given key doesn't already exist in the array: use Illuminate\Support\Arr; $array = Arr::add(['name' => 'Desk'], 'price', 100); // ['name' => 'Desk', 'price' => 100] Arr::collapse() The Arr::collapse method collapses an array of arrays into a single array: use Illuminate\Support\Arr; $array = Arr::collapse([[1, 2, 3], [4, 5, 6], [7, 8, 9]]); // [1, 2, 3, 4, 5, 6, 7, 8, 9] Arr::divide() The Arr::divide method returns two arrays, one containing the keys, and the other containing the values of the given array: use Illuminate\Support\Arr; [$keys, $values] = Arr::divide(['name' => 'Desk']); // $keys: ['name'] // $values: ['Desk'] Arr::dot() The Arr::dot method flattens a multi-dimensional array into a single level array that uses "dot" notation to indicate depth: use Illuminate\Support\Arr; $array = ['products' => ['desk' => ['price' => 100]]]; $flattened = Arr::dot($array); // ['products.desk.price' => 100] Arr::except() The Arr::except method removes the given key / value pairs from an array: use Illuminate\Support\Arr; $array = ['name' => 'Desk', 'price' => 100]; $filtered = Arr::except($array, ['price']); // ['name' => 'Desk'] Arr::first() The Arr::first method returns the first element of an array passing a given truth test: use Illuminate\Support\Arr; $array = [100, 200, 300]; $first = Arr::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: use Illuminate\Support\Arr; $first = Arr::first($array, $callback, $default); Arr::flatten() The Arr::flatten method flattens a multi-dimensional array into a single level array: use Illuminate\Support\Arr; $array = ['name' => 'Joe', 'languages' => ['PHP', 'Ruby']]; $flattened = Arr::flatten($array); // ['Joe', 'PHP', 'Ruby'] Arr::forget() The Arr::forget method removes a given key / value pair from a deeply nested array using "dot" notation: use Illuminate\Support\Arr; $array = ['products' => ['desk' => ['price' => 100]]]; Arr::forget($array, 'products.desk'); // ['products' => []] Arr::get() The Arr::get method retrieves a value from a deeply nested array using "dot" notation: use Illuminate\Support\Arr; $array = ['products' => ['desk' => ['price' => 100]]]; $price = Arr::get($array, 'products.desk.price'); // 100 The Arr::get method also accepts a default value, which will be returned if the specific key is not found: use Illuminate\Support\Arr; $discount = Arr::get($array, 'products.desk.discount', 0); // 0 Arr::has() The Arr::has method checks whether a given item or items exists in an array using "dot" notation: use Illuminate\Support\Arr; $array = ['product' => ['name' => 'Desk', 'price' => 100]]; $contains = Arr::has($array, 'product.name'); // true $contains = Arr::has($array, ['product.price', 'product.discount']); // false Arr::last() The Arr::last method returns the last element of an array passing a given truth test: use Illuminate\Support\Arr; $array = [100, 200, 300, 110]; $last = Arr::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: use Illuminate\Support\Arr; $last = Arr::last($array, $callback, $default); Arr::only() The Arr::only method returns only the specified key / value pairs from the given array: use Illuminate\Support\Arr; $array = ['name' => 'Desk', 'price' => 100, 'orders' => 10]; $slice = Arr::only($array, ['name', 'price']); // ['name' => 'Desk', 'price' => 100] Arr::pluck() The Arr::pluck method retrieves all of the values for a given key from an array: use Illuminate\Support\Arr; $array = [ ['developer' => ['id' => 1, 'name' => 'Taylor']], ['developer' => ['id' => 2, 'name' => 'Abigail']], ]; $names = Arr::pluck($array, 'developer.name'); // ['Taylor', 'Abigail'] You may also specify how you wish the resulting list to be keyed: use Illuminate\Support\Arr; $names = Arr::pluck($array, 'developer.name', 'developer.id'); // [1 => 'Taylor', 2 => 'Abigail'] Arr::prepend() The Arr::prepend method will push an item onto the beginning of an array: use Illuminate\Support\Arr; $array = ['one', 'two', 'three', 'four']; $array = Arr::prepend($array, 'zero'); // ['zero', 'one', 'two', 'three', 'four'] If needed, you may specify the key that should be used for the value: use Illuminate\Support\Arr; $array = ['price' => 100]; $array = Arr::prepend($array, 'Desk', 'name'); // ['name' => 'Desk', 'price' => 100] Arr::pull() The Arr::pull method returns and removes a key / value pair from an array: use Illuminate\Support\Arr; $array = ['name' => 'Desk', 'price' => 100]; $name = Arr::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: use Illuminate\Support\Arr; $value = Arr::pull($array, $key, $default); Arr::random() The Arr::random method returns a random value from an array: use Illuminate\Support\Arr; $array = [1, 2, 3, 4, 5]; $random = Arr::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: use Illuminate\Support\Arr; $items = Arr::random($array, 2); // [2, 5] - (retrieved randomly) Arr::set() The Arr::set method sets a value within a deeply nested array using "dot" notation: use Illuminate\Support\Arr; $array = ['products' => ['desk' => ['price' => 100]]]; Arr::set($array, 'products.desk.price', 200); // ['products' => ['desk' => ['price' => 200]]] Arr::sort() The Arr::sort method sorts an array by its values: use Illuminate\Support\Arr; $array = ['Desk', 'Table', 'Chair']; $sorted = Arr::sort($array); // ['Chair', 'Desk', 'Table'] You may also sort the array by the results of the given Closure: use Illuminate\Support\Arr; $array = [ ['name' => 'Desk'], ['name' => 'Table'], ['name' => 'Chair'], ]; $sorted = array_values(Arr::sort($array, function ($value) { return $value['name']; })); /* [ ['name' => 'Chair'], ['name' => 'Desk'], ['name' => 'Table'], ] */ Arr::sortRecursive() The Arr::sortRecursive method recursively sorts an array using the sort function for numeric sub=arrays and ksort for associative sub-arrays: use Illuminate\Support\Arr; $array = [ ['Roman', 'Taylor', 'Li'], ['PHP', 'Ruby', 'JavaScript'], ['one' => 1, 'two' => 2, 'three' => 3], ]; $sorted = Arr::sortRecursive($array); /* [ ['JavaScript', 'PHP', 'Ruby'], ['one' => 1, 'three' => 3, 'two' => 2], ['Li', 'Roman', 'Taylor'], ] */ Arr::where() The Arr::where method filters an array using the given Closure: use Illuminate\Support\Arr; $array = [100, '200', 300, '400', 500]; $filtered = Arr::where($array, function ($value, $key) { return is_string($value); }); // [1 => '200', 3 => '400'] Arr::wrap() The Arr::wrap method wraps the given value in an array. If the given value is already an array it will not be changed: use Illuminate\Support\Arr; $string = 'Laravel'; $array = Arr::wrap($string); // ['Laravel'] If the given value is null, an empty array will be returned: use Illuminate\Support\Arr; $nothing = null; $array = Arr::wrap($nothing); // [] data_fill() 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], ], ] */ data_get() 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 The function also accepts wildcards using asterisks, which may target any key of the array or object: $data = [ 'product-one' => ['name' => 'Desk 1', 'price' => 100], 'product-two' => ['name' => 'Desk 2', 'price' => 150], ]; data_get($data, '*.name'); // ['Desk 1', 'Desk 2']; data_set() 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 fourth argument: $data = ['products' => ['desk' => ['price' => 100]]]; data_set($data, 'products.desk.price', 200, false); // ['products' => ['desk' => ['price' => 100]]] head() The head function returns the first element in the given array: $array = [100, 200, 300]; $first = head($array); // 100 last() The last function returns the last element in the given array: $array = [100, 200, 300]; $last = last($array); // 300
Frontend [ Blade Templating ] { resources/views, @yield('title'), @section('sidebar'), @extends('layouts.app'), @component('alert') , slot('title'), {{ $name }} htmlspecialchars, {{ time() }}, {!! $name !!}, @json($array); Blade::withoutDoubleEncoding, @{{ name }}, @verbatim, @if, @elseif, @else, @endif, @unless, @isset, @empty, @auth, @guest, @hasSection, @switch, @case, @break, @default and @endswitch, @for, @foreach, @forelse, @while, @continue, @break, $loop variable, {{-- --}}, @php, @csrf, @method('PUT'), @include, @includeIf, @includeWhen, @includeFirst, Blade::include, @each, @stack, @push, @prepend, @inject, Blade::directive, Blade::if }
Blade is the simple, yet powerful templating engine provided with Laravel. Unlike other popular PHP templating engines, Blade does not restrict you from using plain PHP code in your views. In fact, all Blade views are compiled into plain PHP code and cached until they are modified, meaning Blade adds essentially zero overhead to your application. Blade view files use the .blade.php file extension and are typically stored in the resources/views directory. Template Inheritance Defining A Layout Two of the primary benefits of using Blade are template inheritance and sections. To get started, let's take a look at a simple example. First, we will examine a "master" page layout. Since most web applications maintain the same general layout across various pages, it's convenient to define this layout as a single Blade view <!-- 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. 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. 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 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 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 Aliasing Components If your Blade components are stored in a sub-directory, you may wish to alias them for easier access. For example, imagine a Blade component that is stored at resources/views/components/alert.blade.php. You may use the component method to alias the component from components.alert to alert. Typically, this should be done in the boot method of your AppServiceProvider: use Illuminate\Support\Facades\Blade; Blade::component('components.alert', 'alert'); Once the component has been aliased, you may render it using a directive: @alert(['type' => 'danger']) You are not allowed to access this resource! @endalert You may omit the component parameters if it has no additional slots: @alert You are not allowed to access this resource! @endalert Displaying Data You may display data passed to your Blade views by wrapping the variable in curly braces. For example, given the following route: Route::get('greeting', function () { return view('welcome', ['name' => 'Samantha']); }); You may display the contents of the name variable like so: Hello, {{ $name }}. Blade {{ }} statements are automatically sent through PHP's htmlspecialchars function to prevent XSS attacks. You are not limited to displaying the contents of the variables passed to the view. You may also echo the results of any PHP function. In fact, you can put any PHP code you wish inside of a Blade echo statement: The current UNIX timestamp is {{ time() }}. Displaying Unescaped Data By default, Blade {{ }} statements are automatically sent through PHP's htmlspecialchars function to prevent XSS attacks. If you do not want your data to be escaped, you may use the following syntax: Hello, {!! $name !!}. Be very careful when echoing content that is supplied by users of your application. Always use the escaped, double curly brace syntax to prevent XSS attacks when displaying user supplied data. Rendering JSON Sometimes you may pass an array to your view with the intention of rendering it as JSON in order to initialize a JavaScript variable. However, instead of manually calling json_encode, you may use the @json Blade directive: var app = @json($array); HTML Entity Encoding By default, Blade (and the Laravel e helper) will double encode HTML entities. If you would like to disable double encoding, call the Blade::withoutDoubleEncoding method from the boot method of your AppServiceProvider 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. 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 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 @emptydirectives 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 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 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 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 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 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 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: $loop->index The index of the current loop iteration (starts at 0). $loop->iteration The current loop iteration (starts at 1). $loop->remaining The iterations remaining in the loop. $loop->count The total number of items in the array being iterated. $loop->first Whether this is the first iteration through the loop. $loop->last Whether this is the last iteration through the loop. $loop->depth The nesting level of the current loop. $loop->parent When in a nested loop, the parent's loop variable. Comments Blade also allows you to define comments in your views. However, unlike HTML comments, Blade comments are not included in the HTML returned by your application: {{-- This comment will not be present in the rendered HTML --}} PHP In some situations, it's useful to embed PHP code into your views. You can use the Blade @php directive to execute a block of plain PHP within your template: @php // @endphp Forms CSRF Field 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 Blade directive to generate the token field: <form method="POST" action="/profile"> @csrf ... </form> Method Field Since HTML forms can't make PUT, PATCH, or DELETE requests, you will need to add a hidden _method field to spoof these HTTP verbs. The @method Blade directive can create this field for you: <form action="/foo/bar" method="POST"> @method('PUT') ... </form> 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']) 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']) Aliasing Includes If your Blade includes are stored in a sub-directory, you may wish to alias them for easier access. For example, imagine a Blade include that is stored at resources/views/includes/input.blade.php with the following content: <input type="{{ $type ?? 'text' }}"> You may use the include method to alias the include from includes.input to input. Typically, this should be done in the boot method of your AppServiceProvider: use Illuminate\Support\Facades\Blade; Blade::include('includes.input', 'input'); Once the include has been aliased, you may render it using the alias name as the Blade directive: @input(['type' => 'email']) 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') Views rendered via @each do not inherit the variables from the parent view. If the child view requires these variables, you should use @foreach and @include instead Stacks Blade allows you to push to named stacks which can be rendered somewhere else in another view or layout. This can be particularly useful for specifying any JavaScript libraries required by your child views: 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> If you would like to prepend content onto the beginning of a stack, you should use the @prepend directive: @push('scripts') This will be second... @endpush // Later... @prepend('scripts') This will be first... @endprepend Service Injection The @inject directive may be used to retrieve a service from the Laravel service container. The first argument passed to @inject is the name of the variable the service will be placed into, while the second argument is the class or interface name of the service you wish to resolve: @inject('metrics', 'App\Services\MetricsService') <div> Monthly Revenue: {{ $metrics->monthlyRevenue() }}. </div> 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: 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: 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
Collections [ Higher-order Messages ] { "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, groupBy, keyBy, map, max, min, partition, reject, some, sortBy, sortByDesc, sum, and unique. $users->each->markAsVip(); $users->sum->votes;}
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, groupBy, keyBy, map, max, min, partition, reject, some, 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;
Controllers [ Dependency Injection ] { Constructor Injection , Method Injection }
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. 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. 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. 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 public function update(Request $request, $id) { // }
Controllers [ Defining Controllers ]
Controllers can group related request handling logic into a single class. Controllers are stored in the app/Http/Controllers directory. 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: 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. The route parameters will also be passed to the method. 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.
File Storage [ Custom Filesystems ] { Flysystem adapters, public function boot() { Storage::extend('dropbox', function ($app, $config) { $client = new DropboxClient( $config['authorization_token'] ); return new Filesystem(new DropboxAdapter($client)); }); } }
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: 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['authorization_token'] ); 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. Next, register the service provider in your config/app.php configuration file: 'providers' => [ // ... App\Providers\DropboxServiceProvider::class, ]; Once you have created and registered the extension's service provider, you may use the dropbox driver in your config/filesystems.php configuration file.
Logging [ Creating Custom Channels ] { Customizing Monolog For Channels, Creating Monolog Handler Channels, Monolog Formatters }
Customizing Monolog For Channels Sometimes you may need complete control over how Monolog is configured for an existing channel. For example, you may want to configure a custom Monolog FormatterInterface implementation for a given channel's handlers. To get started, define a tap array on the channel's configuration. The tap array should contain a list of classes that should have an opportunity to customize (or "tap" into) the Monolog instance after it is created: 'single' => [ 'driver' => 'single', 'tap' => [App\Logging\CustomizeFormatter::class], 'path' => storage_path('logs/laravel.log'), 'level' => 'debug', ], Once you have configured the tap option on your channel, you're ready to define the class that will customize your Monolog instance. This class only needs a single method: __invoke, which receives an Illuminate\Log\Logger instance. The Illuminate\Log\Loggerinstance proxies all method calls to the underlying Monolog instance public function __invoke($logger) { foreach ($logger->getHandlers() as $handler) { $handler->setFormatter(...); } } Creating Monolog Handler Channels Monolog has a variety of available handlers. In some cases, the type of logger you wish to create is merely a Monolog driver with an instance of a specific handler. These channels can be created using the monolog driver. When using the monolog driver, the handler configuration option is used to specify which handler will be instantiated. Optionally, any constructor parameters the handler needs may be specified using the handler_with configuration option: 'logentries' => [ 'driver' => 'monolog', 'handler' => Monolog\Handler\SyslogUdpHandler::class, 'handler_with' => [ 'host' => 'my.logentries.internal.datahubhost.company.com', 'port' => '10000', ], ], Monolog Formatters When using the monolog driver, the Monolog LineFormatter will be used as the default formatter. However, you may customize the type of formatter passed to the handler using the formatter and formatter_with configuration options: 'browser' => [ 'driver' => 'monolog', 'handler' => Monolog\Handler\BrowserConsoleHandler::class, 'formatter' => Monolog\Formatter\HtmlFormatter::class, 'formatter_with' => [ 'dateFormat' => 'Y-m-d', ], ], If you are using a Monolog handler that is capable of providing its own formatter, you may set the value of the formatter configuration option to default: 'newrelic' => [ 'driver' => 'monolog', 'handler' => Monolog\Handler\NewRelicHandler::class, 'formatter' => 'default', ], Creating Channels Via Factories If you would like to define an entirely custom channel in which you have full control over Monolog's instantiation and configuration, you may specify a custom driver type in your config/logging.php configuration file. Your configuration should include a via option to point to the factory class which will be invoked to create the Monolog instance: 'channels' => [ 'custom' => [ 'driver' => 'custom', 'via' => App\Logging\CreateCustomLogger::class, ], ], Once you have configured the custom channel, you're ready to define the class that will create your Monolog instance. This class only needs a single method: __invoke, which should return the Monolog instance: public function __invoke(array $config) { return new Logger(...); }
Validation [ Manually Creating Validators ] { Validator::make, $validator->fails(), validate(), redirect('register') ->withErrors($validator, 'login'); validator->after(function ($validator){//}}
If you do not want to use the validate method on the request, you may create a validator instance manually using the Validator facade. The make method on the facade generates a new validator instance: public function store(Request $request) { $validator = Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]); if ($validator->fails()) { return redirect('post/create') ->withErrors($validator) ->withInput(); } // Store the blog post... } The first argument passed to the make method is the data under validation. The second argument is the validation rules that should be applied to the data. After checking if the request validation failed, you may use the withErrors method to flash the error messages to the session. When using this method, the $errors variable will automatically be shared with your views after redirection, allowing you to easily display them back to the user. The withErrors method accepts a validator, a MessageBag, or a PHP array. If you would like to create a validator instance manually but still take advantage of the automatic redirection offered by the requests's validate method, you may call the validate method on an existing validator instance. If validation fails, the user will automatically be redirected or, in the case of an AJAX request, a JSON response will be returned: Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ])->validate(); Named Error Bags If you have multiple forms on a single page, you may wish to name the MessageBag of errors, allowing you to retrieve the error messages for a specific form. Pass a name as the second argument to withErrors: return redirect('register') ->withErrors($validator, 'login'); You may then access the named MessageBag instance from the $errors variable: {{ $errors->login->first('email') }} After Validation Hook The validator also allows you to attach callbacks to be run after validation is completed. This allows you to easily perform further validation and even add more error messages to the message collection. To get started, use the after method on a validator instance: $validator = Validator::make(...); $validator->after(function ($validator) { if ($this->somethingElseIsInvalid()) { $validator->errors()->add('field', 'Something is wrong with this field!'); } }); if ($validator->fails()) { // }
Responses [ Response Macros ]
If you would like to define a custom response that you can re-use in a variety of your routes and controllers, you may use the macro method on the Response facade. For example, from a service provider's boot method: Response::macro('caps', function ($value) { return Response::make(strtoupper($value)); }); The macro function accepts a name as its first argument, and a Closure as its second. The macro's Closure will be executed when calling the macro name from a ResponseFactory implementation or the response helper: return response()->caps('foo');
Security [ Authorization ] { gates and policies, Gate::define, Gate::resource, Gate::allows, Gate::denies, Gate::forUser, Gate::before, Gate::after, make:policy, protected $policies = [ Post::class => PostPolicy::class, ] Policy Methods, Methods Without Models, ?User $user, before method on the policy, $user->can('update', $post), $user->can('create', Post::class), middleware('can:update,post'), middleware('can:create,App\Post'), $this->authorize('update', $post); $this->authorize('create', Post::class), $this->authorizeResource(Post::class, 'post'); @can('update', $post); @cannot('update', $post) @can('create', App\Post::class)}
In addition to providing authentication services out of the box, Laravel also provides a simple way to authorize user actions against a given resource. Like authentication, Laravel's approach to authorization is simple, and there are two primary ways of authorizing actions: gates and policies. Think of gates and policies like routes and controllers. Gates provide a simple, Closure based approach to authorization while policies, like controllers, group their logic around a particular model or resource. We'll explore gates first and then examine policies. You do not need to choose between exclusively using gates or exclusively using policies when building an application. Most applications will most likely contain a mixture of gates and policies, and that is perfectly fine! Gates are most applicable to actions which are not related to any model or resource, such as viewing an administrator dashboard. In contrast, policies should be used when you wish to authorize an action for a particular model or resource. Gates Writing Gates Gates are Closures that determine if a user is authorized to perform a given action and are typically defined in the App\Providers\AuthServiceProvider class using the Gatefacade. 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', 'App\Policies\PostPolicy@update'); } Resource Gates You may also define multiple Gate abilities at once using the resource method: Gate::resource('posts', 'App\Policies\PostPolicy'); This is identical to manually defining the following Gate definitions: Gate::define('posts.view', 'App\Policies\PostPolicy@view'); Gate::define('posts.create', 'App\Policies\PostPolicy@create'); Gate::define('posts.update', 'App\Policies\PostPolicy@update'); Gate::define('posts.delete', 'App\Policies\PostPolicy@delete'); By default, the view, create, update, and delete abilities will be defined. You may override the default abilities by passing an array as a third argument to the resourcemethod. The keys of the array define the names of the abilities while the values define the method names. For example, the following code will only create two new Gate definitions - posts.image and posts.photo: Gate::resource('posts', 'PostPolicy', [ 'image' => 'updateImage', 'photo' => 'updatePhoto', ]); 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... } Intercepting Gate Checks Sometimes, you may wish to grant all abilities to a specific user. You may use the before method to define a callback that is run before all other authorization checks: Gate::before(function ($user, $ability) { if ($user->isSuperAdmin()) { return true; } }); If the before callback returns a non-null result that result will be considered the result of the check. You may use the after method to define a callback to be executed after all other authorization checks: Gate::after(function ($user, $ability, $result, $arguments) { if ($user->isSuperAdmin()) { return true; } }); Similar to the before check, if the after callback returns a non-null result that result will be considered the result of the check. Creating Policies Generating Policies Policies are classes that organize authorization logic around a particular model or resource. For example, if your application is a blog, you may have a Post model and a corresponding PostPolicy to authorize user actions such as creating or updating posts. You may generate a policy using the make:policy artisan command. The generated policy will be placed in the app/Policies directory. If this directory does not exist in your application, Laravel will create it for you: 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 All policies are resolved via the Laravel service container, allowing you to type-hint any needed dependencies in the policy's constructor to have them automatically injected. Registering Policies Once the policy exists, it needs to be registered. The AuthServiceProvider included with fresh Laravel applications contains a policies property which maps your Eloquent models to their corresponding policies. Registering a policy will instruct Laravel which policy to utilize when authorizing actions against a given model: protected $policies = [ Post::class => PostPolicy::class, ]; Writing Policies Policy Methods Once the policy has been registered, you may add methods for each action it authorizes. For example, let's define an update method on our PostPolicy which determines if a given User can update a given Post instance. The update method will receive a User and a Post instance as its arguments, and should return true or false indicating whether the user is authorized to update the given Post. So, for this example, let's verify that the user's id matches the user_id on the post 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. If you used the --model option when generating your policy via the Artisan console, it will already contain methods for the view, create, update, delete, restore, and forceDeleteactions. 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 createmethod, 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) { // } Guest Users By default, all gates and policies automatically return false if the incoming HTTP request was not initiated by an authenticated user. However, you may allow these authorization checks to pass through to your gates and policies by declaring an "optional" type-hint or supplying a null default value for the user argument definition: public function update(?User $user, Post $post) { return $user->id === $post->user_id; } Policy Filters For certain users, you may wish to authorize all actions within a given policy. To accomplish this, define a before method on the policy. The before method will be executed before any other methods on the policy, giving you an opportunity to authorize the action before the intended policy method is actually called. This feature is most commonly used for authorizing application administrators to perform any action: 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. The before method of a policy class will not be called if the class doesn't contain a method with a name matching the name of the ability being checked. Authorizing Actions Using Policies Via The User Model The User model that is included with your Laravel application includes two helpful methods for authorizing actions: can and cant. The can method receives the action you wish to authorize and the relevant model. For example, let's determine if a user is authorized to update a given Post model: if ($user->can('update', $post)) { // } If a policy is registered for the given model, the can method will automatically call the appropriate policy and return the boolean result. If no policy is registered for the model, the can method will attempt to call the Closure based Gate matching the given action name. Actions That Don't Require Models Remember, some actions like create may not require a model instance. In these situations, you may pass a class name to the can method. The class name will be used to determine which policy to use when authorizing the action: use App\Post; if ($user->can('create', Post::class)) { // Executes the "create" method on the relevant policy... } Via Middleware Laravel includes a middleware that can authorize actions before the incoming request even reaches your routes or controllers. By default, the Illuminate\Auth\Middleware\Authorize middleware is assigned the can key in your App\Http\Kernel class. Let's explore an example of using the can middleware to authorize that a user can update a blog post: use App\Post; Route::put('/post/{post}', function (Post $post) { // The current user may update the post... })->middleware('can:update,post'); In this example, we're passing the can middleware two arguments. The first is the name of the action we wish to authorize and the second is the route parameter we wish to pass to the policy method. In this case, since we are using implicit model binding, a Post model will be passed to the policy method. If the user is not authorized to perform the given action, a HTTP response with a 403 status code will be generated by the middleware. Actions That Don't Require Models Again, some actions like create may not require a model instance. In these situations, you may pass a class name to the middleware. The class name will be used to determine which policy to use when authorizing the action: Route::post('/post', function () { // The current user may create posts... })->middleware('can:create,App\Post'); Via Controller Helpers In addition to helpful methods provided to the User model, Laravel provides a helpful authorize method to any of your controllers which extend the App\Http\Controllers\Controller base class. Like the can method, this method accepts the name of the action you wish to authorize and the relevant model. If the action is not authorized, the authorize method will throw an Illuminate\Auth\Access\AuthorizationException, which the default Laravel exception handler will convert to an HTTP response with a 403 status code: public function update(Request $request, Post $post) { $this->authorize('update', $post); // The current user can update the blog post... } Actions That Don't Require Models As previously discussed, some actions like create may not require a model instance. In these situations, you 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 * @throws \Illuminate\Auth\Access\AuthorizationException */ public function create(Request $request) { $this->authorize('create', Post::class); // The current user can create blog posts... } Authorizing Resource Controllers If you are utilizing resource controllers, you may make use of the authorizeResourcemethod in the controller's constructor. This method will attach the appropriate canmiddleware definition to the resource controller's methods. The authorizeResource method accepts the model's class name as its first argument, and the name of the route / request parameter that will contain the model's ID as its second argument: public function __construct() { $this->authorizeResource(Post::class, 'post'); } You may use the make:policy command with the --modeloption to quickly generate a policy class for a given model: php artisan make:policy PostPolicy --model=Post. Via Blade Templates When writing Blade templates, you may wish to display a portion of the page only if the user is authorized to perform a given action. For example, you may wish to show an update form for a blog post only if the user can actually update the post. In this situation, you may use the @can and @cannot family of directives: @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 Actions That Don't Require Models Like most of the other authorization methods, you may pass a class name to the @canand @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
Sessions [ Deleting Data ] { $request->session()->pull('key', 'default'); $request->session()->forget('key'); $request->session()->forget(['key1', 'key2']); $request->session()->flush(); }
Retrieving & Deleting An Item The pull method will retrieve and delete an item from the session in a single statement: $value = $request->session()->pull('key', 'default'); The forget method will remove a piece of data from the session. If you would like to remove all data from the session, you may use the flush method: // Forget a single key... $request->session()->forget('key'); // Forget multiple keys... $request->session()->forget(['key1', 'key2']); $request->session()->flush();
Websockets [ Broadcasting Events ] { config/broadcasting.php; Pusher Channels, Redis, log and null drivers; App\Providers\BroadcastServiceProvider; <meta name="csrf-token" content="{{ csrf_token() }}">; composer require pusher/pusher-php-server "~3.0"; composer require predis/predis; npm install --save socket.io-client; configure and run a queue listener; allows broadcast server-side Laravel events to client-side JavaScript application using WebSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; public function broadcastOn(); channel authorization rules in the routes/channels.php file; Echo.private(`order.${orderId}`) .listen('ShippingStatusUpdated', (e) => { console.log(e.update); }); 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, customize the broadcast name by defining a broadcastAs method, If you customize the broadcast name using the broadcastAs method, you should make sure to register your listener with a leading . character; All of its public properties are automatically serialized and broadcast as the event's payload or add a broadcastWith method; broadcastQueue property; use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow; broadcastWhen method; BroadcastServiceProvider a call to the Broadcast::routes method. This method will register the /broadcasting/auth route to handle authorization requests; window.Echo = new Echo({ broadcaster: 'pusher', key: 'your-pusher-channels-key', authEndpoint: '/custom/endpoint/auth' }); Broadcast::channel('order.{orderId}', function ($user, $orderId) { return $user->id === Order::findOrNew($orderId)->user_id; }); Broadcast::channel('order.{order}', function ($user, Order $order) { return $user->id === $order->user_id; }); php artisan make:channel OrderChannel; Broadcast::channel('order.{order}', OrderChannel::class); event(new ShippingStatusUpdated($update)); broadcast(new ShippingStatusUpdated($update)); broadcast(new ShippingStatusUpdated($update))->toOthers() (Your event must use the Illuminate\Broadcasting\InteractsWithSockets); X-Socket-ID header using the Echo.socketId method }
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. Driver Prerequisites Pusher Channels If you are broadcasting your events over Pusher Channels, you should install the Pusher Channels PHP SDK using the Composer package manager: composer require pusher/pusher-php-server "~3.0" Next, you should configure your Channels credentials in the config/broadcasting.phpconfiguration file. An example Channels configuration is already included in this file, allowing you to quickly specify your Channels key, secret, and application ID. The config/broadcasting.php file's pusher configuration also allows you to specify additional options that are supported by Channels, such as the cluster: 'options' => [ 'cluster' => 'eu', 'useTLS' => true ], When using Channels and Laravel Echo, you should specify pusher as your desired broadcaster when instantiating the Echo instance in your resources/js/bootstrap.jsfile: import Echo from "laravel-echo"; window.Pusher = require('pusher-js'); window.Echo = new Echo({ broadcaster: 'pusher', key: 'your-pusher-channels-key' }); Redis If you are using the Redis broadcaster, you should install the Predis library: composer require predis/predis The Redis broadcaster will broadcast messages using Redis' pub / sub feature; however, you will need to pair this with a WebSocket server that can receive the messages from Redis and broadcast them to your WebSocket channels. When the Redis broadcaster publishes an event, it will be published on the event's specified channel names and the payload will be a JSON encoded string containing the event name, a data payload, and the user that generated the event's socket ID (if applicable). Socket.IO If you are going to pair the Redis broadcaster with a Socket.IO server, you will need to include the Socket.IO JavaScript client library in your application. You may install it via the NPM package manager: npm install --save socket.io-client Next, you will need to instantiate Echo with the socket.io connector and a host. import Echo from "laravel-echo" window.io = require('socket.io-client'); window.Echo = new Echo({ broadcaster: 'socket.io', host: window.location.hostname + ':6001' }); Finally, you will need to run a compatible Socket.IO server. Laravel does not include a Socket.IO server implementation; however, a community driven Socket.IO server is currently maintained at the tlaverdure/laravel-echo-server GitHub repository. Queue Prerequisites Before broadcasting events, you will also need to configure and run a queue listener. All event broadcasting is done via queued jobs so that the response time of your application is not seriously affected. Concept Overview Laravel's event broadcasting allows you to broadcast your server-side Laravel events to your client-side JavaScript application using a driver-based approach to WebSockets. Currently, Laravel ships with Pusher Channels and Redis drivers. The events may be easily consumed on the client-side using the Laravel Echo Javascript package. Events are broadcast over "channels", which may be specified as public or private. Any visitor to your application may subscribe to a public channel without any authentication or authorization; however, in order to subscribe to a private channel, a user must be authenticated and authorized to listen on that channel. Using An Example Application Before diving into each component of event broadcasting, let's take a high level overview using an e-commerce store as an example. We won't discuss the details of configuring Pusher Channels or Laravel Echo since that will be discussed in detail in other sections of this documentation. In our application, let's assume we have a page that allows users to view the shipping status for their orders. Let's also assume that a ShippingStatusUpdated event is fired when a shipping status update is processed by the application: event(new ShippingStatusUpdated($update)); The ShouldBroadcast Interface When a user is viewing one of their orders, we don't want them to have to refresh the page to view status updates. Instead, we want to broadcast the updates to the application as they are created. So, we need to mark the ShippingStatusUpdated event with the ShouldBroadcast interface. This will instruct Laravel to broadcast the event when it is fired 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); } 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. 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; }); Defining Channel Classes If your application is consuming many different channels, your routes/channels.php file could become bulky. So, instead of using Closures to authorize channels, you may use channel classes. To generate a channel class, use the make:channel Artisan command. This command will place a new channel class in the App/Broadcasting directory. php artisan make:channel OrderChannel Next, register your channel in your routes/channels.php file: use App\Broadcasting\OrderChannel; Broadcast::channel('order.{order}', OrderChannel::class); Finally, you may place the authorization logic for your channel in the channel class' join method. This join method will house the same logic you would have typically placed in your channel authorization Closure. You may also take advantage of channel model binding: namespace App\Broadcasting; use App\User; use App\Order; class OrderChannel { /** * Create a new channel instance. * * @return void */ public function __construct() { // } /** * Authenticate the user's access to the channel. * * @param \App\User $user * @param \App\Order $order * @return array|bool */ public function join(User $user, Order $order) { return $user->id === $order->user_id; } } 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)); 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 broadcastfunction 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. Your event must use the Illuminate\Broadcasting\InteractsWithSockets trait in order to call the toOthers method. Configuration When you initialize a Laravel Echo instance, a socket ID is assigned to the connection. If you are using Vue and Axios, the socket ID will automatically be attached to every outgoing request as a X-Socket-ID header. Then, when you call the toOthers method, Laravel will extract the socket ID from the header and instruct the broadcaster to not broadcast to any connections with that socket ID. If you are not using Vue and Axios, you will need to manually configure your JavaScript application to send the X-Socket-ID header. You may retrieve the socket ID using the Echo.socketId method: var socketId = Echo.socketId();
Controllers [ Controller Namespacing ]
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');
Mail [ Drivers / Configuration ] { SwiftMailer library with drivers for SMTP, Mailgun, SparkPost, Amazon SES, and sendmail, API based drivers such as Mailgun and SparkPost are often simpler and faster than SMTP servers, but requires the Guzzle HTTP library; 'mailgun' => [ 'domain' => 'your-mailgun-domain', 'secret' => 'your-mailgun-key', 'endpoint' => 'api.eu.mailgun.net', ], 'sparkpost' => [ 'secret' => 'your-sparkpost-key', 'options' => [ 'endpoint' => 'https://api.eu.sparkpost.com/api/v1/transmissions', ], ], "aws/aws-sdk-php": "~3.0"; 'ses' => [ 'key' => 'your-ses-key', 'secret' => 'your-ses-secret', 'region' => 'ses-region', // e.g. us-east-1 'options' => [ 'ConfigurationSetName' => 'MyConfigurationSet', 'Tags' => [ [ 'Name' => 'foo', 'Value' => 'bar', ], ], ], ], }
Laravel provides a clean, simple API over the popular SwiftMailer library with drivers for SMTP, Mailgun, SparkPost, Amazon SES, and sendmail, allowing you to quickly get started sending mail through a local or cloud based service of your choice. 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 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.phpconfiguration file contains the following options: 'mailgun' => [ 'domain' => 'your-mailgun-domain', 'secret' => 'your-mailgun-key', ], If you are not using the "US" Mailgun region, you may define your region's endpoint in the services configuration file: 'mailgun' => [ 'domain' => 'your-mailgun-domain', 'secret' => 'your-mailgun-key', 'endpoint' => 'api.eu.mailgun.net', ], 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', ], If necessary, you may also configure which API endpoint should be used: 'sparkpost' => [ 'secret' => 'your-sparkpost-key', 'options' => [ 'endpoint' => 'https://api.eu.sparkpost.com/api/v1/transmissions', ], ], 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 requiresection 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 ], If you need to include additional options when executing the SES SendRawEmail request, you may define an options array within your ses configuration: 'ses' => [ 'key' => 'your-ses-key', 'secret' => 'your-ses-secret', 'region' => 'ses-region', // e.g. us-east-1 'options' => [ 'ConfigurationSetName' => 'MyConfigurationSet', 'Tags' => [ [ 'Name' => 'foo', 'Value' => 'bar', ], ], ], ],
Caching [ Drivers / Configuration ] { config/cache.php; "apc", "array", "database", "file", "memcached", "redis", "dynamodb"; Schema::create('cache', function ($table) { $table->string('key')->unique(); $table->text('value'); $table->integer('expiration'); }); Memcached driver requires the Memcached PECL package; Redis cache need to either install the predis/predispackage (~1.0) via Composer or install the PhpRedis PHP extension via PECL; The Illuminate\Contracts\Cache\Factory and Illuminate\Contracts\Cache\Repository, Illuminate\Support\Facades\Cache; Cache::store('file')->get('foo'); Cache::forget('key'); Cache::flush(); Cache::lock('foo')->release(); cache(['key' => 'value'], now()->addSeconds(10)); cache()->remember('users', $minutes, function () { return DB::table('users')->get(); }); Cache::shouldReceive, Illuminate\Cache\Events\CacheHit; Illuminate\Cache\Events\CacheMissed; Illuminate\Cache\Events\KeyForgotten; Illuminate\Cache\Events\KeyWritten}
Laravel provides an expressive, unified API for various caching backends. The cache configuration is located at config/cache.php. In this file you may specify which cache driver you would like to be used by default throughout your application. Laravel supports popular caching backends like Memcached and Redis out of the box. The cache configuration file also contains various other options, which are documented within the file, so make sure to read over these options. By default, Laravel is configured to use the file cache driver, which stores the serialized, cached objects in the filesystem. For larger applications, it is recommended that you use a more robust driver such as Memcached or Redis. You may even configure multiple cache configurations for the same driver. Driver Prerequisites Database When using the database cache driver, you will need to setup a table to contain the cache items. You'll find an example Schema declaration for the table below: Schema::create('cache', function ($table) { $table->string('key')->unique(); $table->text('value'); $table->integer('expiration'); }); You may also use the php artisan cache:table Artisan command to generate a migration with the proper schema. Memcached Using the Memcached driver requires the Memcached PECL package to be installed. You may list all of your Memcached servers in the config/cache.php configuration file: '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 ], ], Redis Before using a Redis cache with Laravel, you will need to either install the predis/predispackage (~1.0) via Composer or install the PhpRedis PHP extension via PECL. Obtaining A Cache Instance The Illuminate\Contracts\Cache\Factory and Illuminate\Contracts\Cache\Repositorycontracts 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: namespace App\Http\Controllers; use Illuminate\Support\Facades\Cache; class UserController extends Controller { /** * Show a list of all users of the application. * * @return Response */ public function index() { $value = Cache::get('key'); // } } Accessing Multiple Cache Stores Using the Cache facade, you may access various cache stores via the store method. The key passed to the store method should correspond to one of the stores listed in the stores configuration array in your cache configuration file: $value = Cache::store('file')->get('foo'); Cache::store('redis')->put('bar', 'baz', 10); 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(); Flushing the cache does not respect the cache prefix and will remove all entries from the cache. Consider this carefully when clearing a cache which is shared by other applications. Atomic Locks To utilize this feature, your application must be using the memcached or redis cache driver as your application's default cache driver. In addition, all servers must be communicating with the same central cache server. Atomic locks allow for the manipulation of distributed locks without worrying about race conditions. For example, Laravel Forge uses atomic locks to ensure that only one remote task is being executed on a server at a time. You may create and manage locks using the Cache::lock method: if (Cache::lock('foo', 10)->get()) { // Lock acquired for 10 seconds... Cache::lock('foo')->release(); } The get method also accepts a Closure. After the Closure is executed, Laravel will automatically release the lock: Cache::lock('foo')->get(function () { // Lock acquired indefinitely and automatically released... }); If the lock is not available at the moment you request it, you may instruct Laravel to wait for a specified number of seconds. If the lock can not be acquired within the specified time limit, an Illuminate\Contracts\Cache\LockTimeoutException will be thrown: use Illuminate\Contracts\Cache\LockTimeoutException; try { Cache::lock('foo', 10)->block(5); // Lock acquired after waiting maximum of 5 seconds... } catch (LockTimeoutException $e) { // Unable to acquire lock... } Cache::lock('foo', 10)->block(5, function () { // Lock acquired after waiting maximum of 5 seconds... }); 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)); When the cache function is called without any arguments, it returns an instance of the Illuminate\Contracts\Cache\Factory implementation, allowing you to call other caching methods: cache()->remember('users', $minutes, function () { return DB::table('users')->get(); }); When testing call to the global cache function, you may use the Cache::shouldReceive method just as if you were testing a facade. 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', ], ];
Controllers [ 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); }); 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.
File Storage [ Storing / Retrieving Files ] { Storage::disk('s3')->put('avatars/1', $fileContents); Storage::get('file.jpg'); Storage::disk('s3')->exists('file.jpg'); Storage::download('file.jpg', $name, $headers); Storage::url('file.jpg'); Storage::temporaryUrl( 'file.jpg', now()->addMinutes(5) ); 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), 'url' => env('APP_URL').'/storage', 'visibility' => 'public', ], Storage::size('file.jpg'); Storage::lastModified('file.jpg'); Storage::put('file.jpg', $contents); Storage::put('file.jpg', $resource); // 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'); Storage::prepend('file.log', 'Prepended Text'); Storage::append('file.log', 'Appended Text'); Storage::copy('old/file.jpg', 'new/file.jpg'); Storage::move('old/file.jpg', 'new/file.jpg'); $request->file('avatar')->store('avatars'); Storage::putFile('avatars', $request->file('avatar')); $path = $request->file('avatar')->storeAs( 'avatars', $request->user()->id ); $path = Storage::putFileAs( 'avatars', $request->file('avatar'), $request->user()->id ); $path = $request->file('avatar')->store( 'avatars/'.$request->user()->id, 's3' ); Storage::put('file.jpg', $contents, 'public'); $visibility = Storage::getVisibility('file.jpg'); Storage::setVisibility('file.jpg', 'public'); Storage::delete('file.jpg'); Storage::delete(['file.jpg', 'file2.jpg']); Storage::disk('s3')->delete('folder_path/file_name.jpg'); $files = Storage::files($directory); $files = Storage::allFiles($directory); $directories = Storage::directories($directory); // Recursive... $directories = Storage::allDirectories($directory); Storage::makeDirectory($directory); Storage::deleteDirectory($directory); }
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); 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'); Downloading Files The download method may be used to generate a response that forces the user's browser to download the file at the given path. The download method accepts a file name as the second argument to the method, which will determine the file name that is seen by the user downloading the file. Finally, you may pass an array of HTTP headers as the third argument to the method: return Storage::download('file.jpg'); return Storage::download('file.jpg', $name, $headers); File URLs You may use the url method to get the URL for the given file. If you are using the localdriver, 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('file.jpg'); 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. 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 DateTimeinstance specifying when the URL should expire: $url = Storage::temporaryUrl( 'file.jpg', now()->addMinutes(5) ); 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', ], 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('file.jpg'); The lastModified method returns the UNIX timestamp of the last time the file was modified: $time = Storage::lastModified('file.jpg'); 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); 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 file's extension will be determined by examining the file's MIME type. The path to the file will be returned by the putFilemethod 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'); 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'); 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/file.jpg', 'new/file.jpg'); Storage::move('old/file.jpg', 'new/file.jpg'); 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: 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 file's extension will be determined by examining the file's MIME type. 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')); 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 ); 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 ); 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' ); 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') 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(['file.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'); Directories 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); 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); Create A Directory The makeDirectory method will create the given directory, including any needed sub-directories: Storage::makeDirectory($directory); Delete A Directory Finally, the deleteDirectory may be used to remove a directory and all of its files: Storage::deleteDirectory($directory);
Websockets [ 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; 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; Echo.join(`chat.${roomId}`) .here((users) => { // }) .joining((user) => { console.log(user.name); }) .leaving((user) => { console.log(user.name); }); public function broadcastOn() { return new PresenceChannel('room.'.$this->message->room_id); }; broadcast(new NewMessage($message)); broadcast(new NewMessage($message))->toOthers(); Echo.join(`chat.${roomId}`) .here(...) .joining(...) .leaving(...) .listen('NewMessage', (e) => { // }); }
Presence Channels Presence channels build on the security of private channels while exposing the additional feature of awareness of who is subscribed to the channel. This makes it easy to build powerful, collaborative application features such as notifying users when another user is viewing the same page. Authorizing Presence Channels All presence channels are also private channels; therefore, users must be authorized to access them. However, when defining authorization callbacks for presence channels, you will not return true if the user is authorized to join the channel. Instead, you should return an array of data about the user. The data returned by the authorization callback will be made available to the presence channel event listeners in your JavaScript application. If the user is not authorized to join the presence channel, you should return false or null: Broadcast::channel('chat.{roomId}', function ($user, $roomId) { if ($user->canJoinRoom($roomId)) { return ['id' => $user->id, 'name' => $user->name]; } }); Joining Presence Channels To join a presence channel, you may use Echo's join method. The join method will return a PresenceChannel implementation which, along with exposing the listenmethod, 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. 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) => { // });
Artisan Console [ Executing Commands ] { Artisan::call('email:send', [ 'user' => 1, '--queue' => 'default' ]); Artisan::queue('email:send', [ 'user' => 1, '--queue' => 'default' ])->onConnection('redis')->onQueue('commands'); Artisan::call('email:send', [ 'user' => 1, '--id' => [5, 13] ]); Artisan::call('migrate:refresh', [ '--force' => true, ]); $this->call('email:send', [ 'user' => 1, '--queue' => 'default' ]); $this->callSilent('email:send', [ 'user' => 1, '--queue' => 'default' ]);}
Programmatically Executing Commands Sometimes you may wish to execute an Artisan command outside of the CLI. For example, you may wish to fire an Artisan command from a route or controller. You may use the call method on the Artisan facade to accomplish this. The call method accepts either the command's name or class as the first argument, and an array of command parameters as the second argument. The exit code will be returned: 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'); 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] ]); }); 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, ]); 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' ]);
Events [ Queued Listeners ] { use Illuminate\Contracts\Queue\ShouldQueue; $connection, $queue, or $delay properties on your listener class; Illuminate\Queue\InteractsWithQueue trait; failed method}
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: 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. Customizing The Queue Connection & Queue Name If you would like to customize the queue connection, queue name, or queue delay time of an event listener, you may define the $connection, $queue, or $delay properties on your listener class: 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'; /** * The time (seconds) before the job should be processed. * * @var int */ public $delay = 60; } Manually Accessing The Queue If you need to manually access the listener's underlying queue job's delete and releasemethods, 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: 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); } } } 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: 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) { // } }
Responses [ Flash Data ] { redirect('dashboard')->with('status', 'Profile updated!'); $request->session()->flash('status', 'Task was successful!') }
Redirecting to a new URL and flashing data to the session are usually done at the same time. Typically, this is done after successfully performing an action when you flash a success message to the session. For convenience, you may create a RedirectResponseinstance and flash data to the session in a single, fluent method chain: Route::post('user/profile', function () { // Update the user's profile... return redirect('dashboard')->with('status', 'Profile updated!'); }); After the user is redirected, you may display the flashed message from the session. For example, using Blade syntax: @if (session('status')) <div class="alert alert-success"> {{ session('status') }} </div> @endif Sometimes you may wish to store items in the session only for the next request. You may do so using the flash method. Data stored in the session using this method will only be available during the subsequent HTTP request, and then will be deleted. Flash data is primarily useful for short-lived status messages: $request->session()->flash('status', 'Task was successful!'); If you need to keep your flash data around for several requests, you may use the reflash method, which will keep all of the flash data for an additional request. If you only need to keep specific flash data, you may use the keep method: $request->session()->reflash(); $request->session()->keep(['username', 'email']);
Routing [ Route Parameters ] { Required Parameters, Optional Parameters , Regular Expression Constraints, Global Constraints, Encoded Forward Slashes }
Required Parameters Sometimes you will need to capture segments of the URI within your route. For example, you may need to capture a user's ID from the URL. You may do so by defining route parameters: Route::get('user/{id}', function ($id) { return 'User '.$id; }); You may define as many route parameters as required by your route: Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) { // }); Route parameters are always encased within {} braces and should consist of alphabetic characters, and may not contain a - character. Instead of using the -character, use an underscore (_). Route parameters are injected into route callbacks / controllers based on their order - the names of the callback / controller arguments do not matter. Optional Parameters Occasionally you may need to specify a route parameter, but make the presence of that route parameter optional. You may do so by placing a ? mark after the parameter name. Make sure to give the route's corresponding variable a default value: Route::get('user/{name?}', function ($name = null) { return $name; }); Route::get('user/{name?}', function ($name = 'John') { return $name; }); Regular Expression Constraints You may constrain the format of your route parameters using the where method on a route instance. The where method accepts the name of the parameter and a regular expression defining how the parameter should be constrained: Route::get('user/{name}', function ($name) { // })->where('name', '[A-Za-z]+'); Route::get('user/{id}', function ($id) { // })->where('id', '[0-9]+'); Route::get('user/{id}/{name}', function ($id, $name) { // })->where(['id' => '[0-9]+', 'name' => '[a-z]+']); Global Constraints If you would like a route parameter to always be constrained by a given regular expression, you may use the pattern method. You should define these patterns in the boot method of your RouteServiceProvider: /** * Define your route model bindings, pattern filters, etc. * * @return void */ public function boot() { Route::pattern('id', '[0-9]+'); parent::boot(); } Once the pattern has been defined, it is automatically applied to all routes using that parameter name: Route::get('user/{id}', function ($id) { // Only executed if {id} is numeric... }); Encoded Forward Slashes The Laravel routing component allows all characters except /. You must explicitly allow / to be part of your placeholder using a where condition regular expression: Route::get('search/{search}', function ($search) { return $search; })->where('search', '.*'); Encoded forward slashes are only supported within the last route segment.
Caching [ Storing Items ] { Cache::remember('users', $minutes, function () { return DB::table('users')->get(); }); $value = Cache::rememberForever('users', function () { return DB::table('users')->get(); }); Cache::put('key', 'value', $minutes); $expiresAt = now()->addMinutes(10); Cache::put('key', 'value', $expiresAt); Cache::add('key', 'value', $minutes); Cache::forever('key', 'value');}
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(); }); 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 DateTimeinstance representing the expiration time of the cached item: $expiresAt = now()->addMinutes(10); Cache::put('key', 'value', $expiresAt); 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); 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'); If you are using the Memcached driver, items that are stored "forever" may be removed when the cache reaches its size limit.
Requests [ Uploaded Files ] { Retrieving Uploaded Files, Validating Successful Uploads, File Paths & Extensions, Storing Uploaded Files, }
Retrieving Uploaded Files You may access uploaded files from a Illuminate\Http\Request instance using the filemethod or using dynamic properties. The file method returns an instance of the Illuminate\Http\UploadedFile class, which extends the PHP SplFileInfo class and provides a variety of methods for interacting with the file: $file = $request->file('photo'); $file = $request->photo; You may determine if a file is present on the request using the hasFile method: if ($request->hasFile('photo')) { // } Validating Successful Uploads In addition to checking if the file is present, you may verify that there were no problems uploading the file via the isValid method: if ($request->file('photo')->isValid()) { // } File Paths & Extensions The UploadedFile class also contains methods for accessing the file's fully-qualified path and its extension. The extension method will attempt to guess the file's extension based on its contents. This extension may be different from the extension that was supplied by the client: $path = $request->photo->path(); $extension = $request->photo->extension(); Other File Methods There are a variety of other methods available on UploadedFile instances. Check out the API documentation for the class for more information regarding these methods. Storing Uploaded Files To store an uploaded file, you will typically use one of your configured filesystems. The UploadedFile class has a store method which will move an uploaded file to one of your disks, which may be a location on your local filesystem or even a cloud storage location like Amazon S3. The store method accepts the path where the file should be stored relative to the filesystem's configured root directory. This path should not contain a file name, since a unique ID will automatically be generated to serve as the file name. The store method also accepts an optional second argument for the name of the disk that should be used to store the file. The method will return the path of the file relative to the disk's root: $path = $request->photo->store('images'); $path = $request->photo->store('images', 's3'); If you do not want a file name to be automatically generated, you may use the storeAs method, which accepts the path, file name, and disk name as its arguments: $path = $request->photo->storeAs('images', 'filename.jpg'); $path = $request->photo->storeAs('images', 'filename.jpg', 's3');
Routing [ Route Groups ] { Middleware, Namespaces , Sub-Domain, Routing, Route Prefixes, Route Name Prefixes }
Route groups allow you to share route attributes, such as middleware or namespaces, across a large number of routes without needing to define those attributes on each individual route. Shared attributes are specified in an array format as the first parameter to the Route::group method. Nested groups attempt to intelligently "merge" attributes with their parent group. Middleware and where conditions are merged while names, namespaces, and prefixes are appended. Namespace delimiters and slashes in URI prefixes are automatically added where appropriate. Middleware To assign middleware to all routes within a group, you may use the middleware method before defining the group. Middleware are executed in the order they are listed in the array: Route::middleware(['first', 'second'])->group(function () { Route::get('/', function () { // Uses first & second Middleware }); Route::get('user/profile', function () { // Uses first & second Middleware }); }); Namespaces Another common use-case for route groups is assigning the same PHP namespace to a group of controllers using the namespace method: Route::namespace('Admin')->group(function () { // Controllers Within The "App\Http\Controllers\Admin" Namespace }); Remember, by default, the RouteServiceProvider includes your route files within a namespace group, allowing you to register controller routes without specifying the full App\Http\Controllers namespace prefix. So, you only need to specify the portion of the namespace that comes after the base App\Http\Controllers namespace. Sub-Domain Routing Route groups may also be used to handle sub-domain routing. Sub-domains may be assigned route parameters just like route URIs, allowing you to capture a portion of the sub-domain for usage in your route or controller. The sub-domain may be specified by calling the domain method before defining the group: Route::domain('{account}.myapp.com')->group(function () { Route::get('user/{id}', function ($account, $id) { // }); }); Route Prefixes The prefix method may be used to prefix each route in the group with a given URI. For example, you may want to prefix all route URIs within the group with admin: Route::prefix('admin')->group(function () { Route::get('users', function () { // Matches The "/admin/users" URL }); }); Route Name Prefixes The name method may be used to prefix each route name in the group with a given string. For example, you may want to prefix all of the grouped route's names with admin. The given string is prefixed to the route name exactly as it is specified, so we will be sure to provide the trailing . character in the prefix: Route::name('admin.')->group(function () { Route::get('users', function () { // Route assigned name "admin.users"... })->name('users'); });
Requests [ Request Path and Method ] { $request->path(), $request->is('admin/*'), $request->url(), $request->fullUrl(), $request->method(), $request->isMethod('post') }
The Illuminate\Http\Request instance provides a variety of methods for examining the HTTP request for your application and extends the Symfony\Component\HttpFoundation\Request class. Retrieving The Request Path The path method returns the request's path information. So, if the incoming request is targeted at http://domain.com/foo/bar, the path method will return foo/bar: $uri = $request->path(); The is method allows you to verify that the incoming request path matches a given pattern. You may use the * character as a wildcard when utilizing this method: if ($request->is('admin/*')) { // } Retrieving The Request URL To retrieve the full URL for the incoming request you may use the url or fullUrlmethods. The url method will return the URL without the query string, while the fullUrl method includes the query string: // Without Query String... $url = $request->url(); // With Query String... $url = $request->fullUrl(); Retrieving The Request Method The method method will return the HTTP verb for the request. You may use the isMethodmethod to verify that the HTTP verb matches a given string: $method = $request->method(); if ($request->isMethod('post')) { // }
Sessions [ Configuration ] { config/session.php, file, cookie, database, memcached / redis, array, $request->session()->regenerate();}
Since HTTP driven applications are stateless, sessions provide a way to store information about the user across multiple requests. Laravel ships with a variety of session backends that are accessed through an expressive, unified API. Support for popular backends such as Memcached, Redis, and databases is included out of the box. he session configuration file is stored at config/session.php. Be sure to review the options available to you in this file. By default, Laravel is configured to use the filesession driver, which will work well for many applications. In production applications, you may consider using the memcached or redis drivers for even faster session performance. The session driver configuration option defines where session data will be stored for each request. Laravel ships with several great drivers out of the box: file - sessions are stored in storage/framework/sessions. cookie - sessions are stored in secure, encrypted cookies. database - sessions are stored in a relational database. memcached / redis - sessions are stored in one of these fast, cache based stores. array - sessions are stored in a PHP array and will not be persisted. The array driver is used during testing and prevents the data stored in the session from being persisted. Driver Prerequisites Database When using the database session driver, you will need to create a table to contain the session items. Below is an example Schema declaration for the table: Schema::create('sessions', function ($table) { $table->string('id')->unique(); $table->unsignedInteger('user_id')->nullable(); $table->string('ip_address', 45)->nullable(); $table->text('user_agent')->nullable(); $table->text('payload'); $table->integer('last_activity'); }); You may use the session:table Artisan command to generate this migration: php artisan session:table php artisan migrate Redis Before using Redis sessions with Laravel, you will need to install the predis/predispackage (~1.0) via Composer. You may configure your Redis connections in the database configuration file. In the session configuration file, the connection option may be used to specify which Redis connection is used by the session. Regenerating The Session ID Regenerating the session ID is often done in order to prevent malicious users from exploiting a session fixation attack on your application. Laravel automatically regenerates the session ID during authentication if you are using the built-in LoginController; however, if you need to manually regenerate the session ID, you may use the regenerate method. $request->session()->regenerate();
Sessions [ Flash Data ] { $request->session()->flash('status', 'Task was successful!'); $request->session()->reflash(); $request->session()->keep(['username', 'email']); }
Sometimes you may wish to store items in the session only for the next request. You may do so using the flash method. Data stored in the session using this method will only be available during the subsequent HTTP request, and then will be deleted. Flash data is primarily useful for short-lived status messages: $request->session()->flash('status', 'Task was successful!'); If you need to keep your flash data around for several requests, you may use the reflash method, which will keep all of the flash data for an additional request. If you only need to keep specific flash data, you may use the keep method: $request->session()->reflash(); $request->session()->keep(['username', 'email']);
Responses [ Attaching Headers / Cookies ] { Strings & Arrays & Eloquent collections, Response Objects, Attaching Headers To Responses }
Strings & Arrays All routes and controllers should return a response to be sent back to the user's browser. Laravel provides several different ways to return responses. The most basic response is returning a string from a route or controller. The framework will automatically convert the string into a full HTTP response. In addition to returning strings from your routes and controllers, you may also return arrays. The framework will automatically convert the array into a JSON response. You can also return Eloquent collections from your routes or controllers? They will automatically be converted to JSON. Response Objects Typically, you won't just be returning simple strings or arrays from your route actions. Instead, you will be returning full Illuminate\Http\Response instances or views. Returning a full Response instance allows you to customize the response's HTTP status code and headers. A Response instance inherits from the Symfony\Component\HttpFoundation\Response class, which provides a variety of methods for building HTTP responses: Route::get('home', function () { return response('Hello World', 200) ->header('Content-Type', 'text/plain'); }); Attaching Headers To Responses Keep in mind that most response methods are chainable, allowing for the fluent construction of response instances. For example, you may use the header method to add a series of headers to the response before sending it back to the user: return response($content) ->header('Content-Type', $type) ->header('X-Header-One', 'Header Value') ->header('X-Header-Two', 'Header Value'); Or, you may use the withHeaders method to specify an array of headers to be added to the response: return response($content) ->withHeaders([ 'Content-Type' => $type, 'X-Header-One' => 'Header Value', 'X-Header-Two' => 'Header Value', ]); Attaching Cookies To Responses You may attach a cookie to an outgoing Illuminate\Http\Response instance using the cookie method. You should pass the name, value, and number of minutes the cookie should be considered valid to this method: return response('Hello World')->cookie( 'name', 'value', $minutes ); The cookie method also accepts a few more arguments which are used less frequently. Generally, these arguments have the same purpose and meaning as the arguments that would be given to PHP's native setcookie method: return response('Hello World')->cookie( 'name', 'value', $minutes, $path, $domain, $secure, $httpOnly ); Alternatively, you can use the Cookie facade to "queue" cookies for attachment to the outgoing response from your application. The queue method accepts a Cookieinstance or the arguments needed to create a Cookie instance. These cookies will be attached to the outgoing response before it is sent to the browser: Cookie::queue(Cookie::make('name', 'value', $minutes)); Cookie::queue('name', 'value', $minutes); Generating Cookie Instances If you would like to generate a Symfony\Component\HttpFoundation\Cookie instance that can be given to a response instance at a later time, you may use the global cookiehelper. This cookie will not be sent back to the client unless it is attached to a response instance: $cookie = cookie('name', 'value', $minutes); return response('Hello World')->cookie($cookie);
Collections [ Creating / Extending Collections ] { Illuminate\Support\Collection; collect(['taylor', 'abigail', null]); The results of Eloquent queries are always returned as Collection instances; Collection::macro('toUpper', function () { return $this->map(function ($value) { return Str::upper($value); }); }); }
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 strtoupperfunction 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. Creating Collections As mentioned above, the collect helper returns a new Illuminate\Support\Collectioninstance for the given array. So, creating a collection is as simple as: $collection = collect([1, 2, 3]); The results of Eloquent queries are always returned as Collection instances. 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.
Architecture [ Request Lifecycle ] { public/index.php, bootstrap/app.php, application/service container, app/Http/Kernel.php, HTTP middlewares, Service Providers, router }
The entry point for all requests is the public/index.php file. It 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. 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. 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 middlewares 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. 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. 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. 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! 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. For large applications, you may wish to create several service providers, each with a more granular type of bootstrapping.
Caching [ Retrieving Items ] { Cache::get('key', 'default'); Cache::get('key', function () { return DB::table(...)->get(); }); Cache::has('key'); Cache::increment('key'); Cache::increment('key', $amount); Cache::decrement('key'); Cache::decrement('key', $amount); Cache::remember('users', $minutes, function () { return DB::table('users')->get(); }); $value = Cache::rememberForever('users', function () { return DB::table('users')->get(); }); Cache::pull('key');}
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(); }); 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: if (Cache::has('key')) { // } Incrementing / Decrementing Values The increment and decrement methods may be used to adjust the value of integer items in the cache. Both of these methods accept an optional second argument indicating the amount by which to increment or decrement the item's value: Cache::increment('key'); Cache::increment('key', $amount); Cache::decrement('key'); Cache::decrement('key', $amount); Retrieve & Store Sometimes you may wish to retrieve an item from the cache, but also store a default value if the requested item doesn't exist. For example, you may wish to retrieve all users from the cache or, if they don't exist, retrieve them from the database and add them to the cache. You may do this using the Cache::remember method: $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(); }); 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');
Responses [ Response Types ] { View Responses, JSON Responses, File Downloads, Streamed Downloads, File Responses }
The response helper may be used to generate other types of response instances. When the response helper is called without arguments, an implementation of the Illuminate\Contracts\Routing\ResponseFactory contract is returned. This contract provides several helpful methods for generating responses. View Responses If you need control over the response's status and headers but also need to return a view as the response's content, you should use the view method: return response() ->view('hello', $data, 200) ->header('Content-Type', $type); Of course, if you do not need to pass a custom HTTP status code or custom headers, you should use the global view helper function JSON Responses The json method will automatically set the Content-Type header to application/json, as well as convert the given array to JSON using the json_encode PHP function: return response()->json([ 'name' => 'Abigail', 'state' => 'CA' ]); If you would like to create a JSONP response, you may use the json method in combination with the withCallback method: return response() ->json(['name' => 'Abigail', 'state' => 'CA']) ->withCallback($request->input('callback')); File Downloads The download method may be used to generate a response that forces the user's browser to download the file at the given path. The download method accepts a file name as the second argument to the method, which will determine the file name that is seen by the user downloading the file. Finally, you may pass an array of HTTP headers as the third argument to the method: return response()->download($pathToFile); return response()->download($pathToFile, $name, $headers); return response()->download($pathToFile)->deleteFileAfterSend(); Symfony HttpFoundation, which manages file downloads, requires the file being downloaded to have an ASCII file name. Streamed Downloads Sometimes you may wish to turn the string response of a given operation into a downloadable response without having to write the contents of the operation to disk. You may use the streamDownload method in this scenario. This method accepts a callback, file name, and an optional array of headers as its arguments: return response()->streamDownload(function () { echo GitHub::api('repo') ->contents() ->readme('laravel', 'laravel')['contents']; }, 'laravel-readme.md'); File Responses The file method may be used to display a file, such as an image or PDF, directly in the user's browser instead of initiating a download. This method accepts the path to the file as its first argument and an array of headers as its second argument: return response()->file($pathToFile); return response()->file($pathToFile, $headers);
Sessions [ Retrieving Data ] { $request->session()->get('key'); session('key', 'default'); $request->session()->all(); $request->session()->has('users'); $request->session()->exists('users'); $request->session()->pull('key', 'default');}
There are two primary ways of working with session data in Laravel: the global sessionhelper and via a Request instance. $value = $request->session()->get('key'); When you retrieve an item from the session, you may also pass a default value as the second argument to the get method. This default value will be returned if the specified key does not exist in the session. If you pass a Closure as the default value to the getmethod and the requested key does not exist, the Closure will be executed and its result returned: $value = $request->session()->get('key', 'default'); $value = $request->session()->get('key', function () { return 'default'; }); The Global Session Helper You may also use the global session PHP function to retrieve and store data in the session. When the session helper is called with a single, string argument, it will return the value of that session key. When the helper is called with an array of key / value pairs, those values will be stored in the session: $value = session('key'); // Specifying a default value... $value = session('key', 'default'); Retrieving All Session Data If you would like to retrieve all the data in the session, you may use the all method: $data = $request->session()->all(); Determining If An Item Exists In The Session To determine if an item is present in the session, you may use the has method. The hasmethod returns true if the item is present and is not null: if ($request->session()->has('users')) { // } To determine if an item is present in the session, even if its value is null, you may use the exists method. The exists method returns true if the item is present: if ($request->session()->exists('users')) { // } Retrieving & Deleting An Item The pull method will retrieve and delete an item from the session in a single statement: $value = $request->session()->pull('key', 'default');
Events [ Dispatching Events ] { event(new OrderShipped($order)); }
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: 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)); } } 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.
Mail [ Sending Mail ] { Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->send(new OrderShipped($order)); 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; (new App\Mail\InvoicePaid($invoice))->render(); Route::get('mailable', function () { $invoice = App\Invoice::find(1); return new App\Mail\InvoicePaid($invoice); }); Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->queue(new OrderShipped($order)); Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->later($when, new OrderShipped($order)); $message = (new OrderShipped($order)) ->onConnection('sqs') ->onQueue('emails'); Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->queue($message); use Illuminate\Contracts\Queue\ShouldQueue; Mail::to($request->user())->locale('es')->send( new OrderShipped($order) ); use Illuminate\Contracts\Translation\HasLocalePreference; MessageSending, MessageSent }
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: 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)); } } 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)); Rendering Mailables Sometimes you may wish to capture the HTML content of a mailable without sending it. To accomplish this, you may call the render method of the mailable. This method will return the evaluated contents of the mailable as a string: $invoice = App\Invoice::find(1); return (new App\Mail\InvoicePaid($invoice))->render(); 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); }); Queueing Mail 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. You will need to configure your queues before using this feature. Delayed Message Queueing If you wish to delay the delivery of a queued email message, you may use the latermethod. 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)); 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); 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 { // } Localizing Mailables Laravel allows you to send mailables in a locale other than the current language, and will even remember this locale if the mail is queued. To accomplish this, the Mail facade offers a locale method to set the desired language. The application will change into this locale when the mailable is being formatted and then revert back to the previous locale when formatting is complete: Mail::to($request->user())->locale('es')->send( new OrderShipped($order) ); User Preferred Locales Sometimes, applications store each user's preferred locale. By implementing the HasLocalePreference contract on one or more of your models, you may instruct Laravel to use this stored locale when sending mail: use Illuminate\Contracts\Translation\HasLocalePreference; class User extends Model implements HasLocalePreference { /** * Get the user's preferred locale. * * @return string */ public function preferredLocale() { return $this->locale; } } Once you have implemented the interface, Laravel will automatically use the preferred locale when sending mailables and notifications to the model. Therefore, there is no need to call the locale method when using this interface: Mail::to($request->user())->send(new OrderShipped($order)); 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', ], ];
Notifications [ Sending Notifications ] { use Illuminate\Notifications\Notifiable; $user->notify(new InvoicePaid($invoice)); Notification::send($users, new InvoicePaid($invoice)); Every notification class has a via method that determines on which channels the notification will be delivered. Out of the box, notifications may be sent on the mail, database, broadcast, nexmo, and slack channels. use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Bus\Queueable; $user->notify((new InvoicePaid($invoice))->delay($when)); Notification::route('mail', '[email protected]') ->route('nexmo', '5555555555') ->notify(new InvoicePaid($invoice)); $user->notify((new InvoicePaid($invoice))->locale('es')); Notification::locale('es')->send($users, new InvoicePaid($invoice)); use Illuminate\Contracts\Translation\HasLocalePreference; class User extends Model implements HasLocalePreference; Illuminate\Notifications\Events\NotificationSent }
Using The Notifiable Trait Notifications may be sent in two ways: using the notify method of the Notifiable trait or using the Notification facade. First, let's explore using the trait: amespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; } This trait is utilized by the default App\User model and contains one method that may be used to send notifications: notify. The notify method expects to receive a notification instance: use App\Notifications\InvoicePaid; $user->notify(new InvoicePaid($invoice)); Remember, you may use the Illuminate\Notifications\Notifiable trait on any of your models. You are not limited to only including it on your Usermodel. Using The Notification Facade Alternatively, you may send notifications via the Notification facade. This is useful primarily when you need to send a notification to multiple notifiable entities such as a collection of users. To send notifications using the facade, pass all of the notifiable entities and the notification instance to the send method: Notification::send($users, new InvoicePaid($invoice)); Specifying Delivery Channels Every notification class has a via method that determines on which channels the notification will be delivered. Out of the box, notifications may be sent on the mail, database, broadcast, nexmo, and slack channels. If you would like to use other delivery channels such as Telegram or Pusher, check out the community driven Laravel Notification Channels website. The via method receives a $notifiable instance, which will be an instance of the class to which the notification is being sent. You may use $notifiable to determine which channels the notification should be delivered on: /** * Get the notification's delivery channels. * * @param mixed $notifiable * @return array */ public function via($notifiable) { return $notifiable->prefers_sms ? ['nexmo'] : ['mail', 'database']; } Queueing Notifications Before queueing notifications you should configure your queue and start a worker. Sending notifications can take time, especially if the channel needs an external API call to deliver the notification. To speed up your application's response time, let your notification be queued by adding the ShouldQueue interface and Queueable trait to your class. The interface and trait are already imported for all notifications generated using make:notification, so you may immediately add them to your notification class: namespace App\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; class InvoicePaid extends Notification implements ShouldQueue { use Queueable; // ... } Once the ShouldQueue interface has been added to your notification, you may send the notification like normal. Laravel will detect the ShouldQueue interface on the class and automatically queue the delivery of the notification: $user->notify(new InvoicePaid($invoice)); If you would like to delay the delivery of the notification, you may chain the delaymethod onto your notification instantiation: $when = now()->addMinutes(10); $user->notify((new InvoicePaid($invoice))->delay($when)); On-Demand Notifications Sometimes you may need to send a notification to someone who is not stored as a "user" of your application. Using the Notification::route method, you may specify ad-hoc notification routing information before sending the notification: Notification::route('mail', '[email protected]') ->route('nexmo', '5555555555') ->notify(new InvoicePaid($invoice)); Localizing Notifications Laravel allows you to send notifications in a locale other than the current language, and will even remember this locale if the notification is queued. To accomplish this, the Illuminate\Notifications\Notification class offers a localemethod to set the desired language. The application will change into this locale when the notification is being formatted and then revert back to the previous locale when formatting is complete: $user->notify((new InvoicePaid($invoice))->locale('es')); Localization of multiple notifiable entries may also be achieved via the Notificationfacade: Notification::locale('es')->send($users, new InvoicePaid($invoice)); User Preferred Locales Sometimes, applications store each user's preferred locale. By implementing the HasLocalePreference contract on your notifiable model, you may instruct Laravel to use this stored locale when sending a notification: use Illuminate\Contracts\Translation\HasLocalePreference; class User extends Model implements HasLocalePreference { /** * Get the user's preferred locale. * * @return string */ public function preferredLocale() { return $this->locale; } } Once you have implemented the interface, Laravel will automatically use the preferred locale when sending notifications and mailables to the model. Therefore, there is no need to call the locale method when using this interface: $user->notify(new InvoicePaid($invoice)); Notification Events When a notification is sent, the Illuminate\Notifications\Events\NotificationSent event is fired by the notification system. This contains the "notifiable" entity and the notification instance itself. You may register listeners for this event in your EventServiceProvider: /** * The event listener mappings for the application. * * @var array */ protected $listen = [ 'Illuminate\Notifications\Events\NotificationSent' => [ 'App\Listeners\LogNotification', ], ]; After registering listeners in your EventServiceProvider, use the event:generate Artisan command to quickly generate listener classes. Within an event listener, you may access the notifiable, notification, and channelproperties on the event to learn more about the notification recipient or the notification itself: /** * Handle the event. * * @param NotificationSent $event * @return void */ public function handle(NotificationSent $event) { // $event->channel // $event->notifiable // $event->notification // $event->response }
Views [ View Composer ] { callbacks or class methods, Attaching A Composer To Multiple Views, View Creators }
View composers are callbacks or class methods that are called when a view is rendered. If you have data that you want to be bound to a view each time that view is rendered, a view composer can help you organize that logic into a single location. For this example, let's register the view composers within a service provider. We'll use the View facade to access the underlying Illuminate\Contracts\View\Factory contract implementation. Remember, Laravel does not include a default directory for view composers. You are free to organize them however you wish. For example, you could create an app/Http/View/Composers directory View::composer( 'profile', 'App\Http\View\Composers\ProfileComposer' ); // Using Closure based composers... View::composer('dashboard', function ($view) { // }); Now that we have registered the composer, the ProfileComposer@compose method will be executed each time the profile view is being rendered. So, let's define the composer class public function compose(View $view) { $view->with('count', $this->users->count()); } Just before the view is rendered, the composer's compose method is called with the Illuminate\View\View instance. You may use the with method to bind data to the view. All view composers are resolved via the service container, so you may type-hint any dependencies you need within a composer's constructor Attaching A Composer To Multiple Views You may attach a view composer to multiple views at once by passing an array of views as the first argument to the composer method: View::composer( ['profile', 'dashboard'], 'App\Http\View\Composers\MyViewComposer' ); The composer method also accepts the * character as a wildcard, allowing you to attach a composer to all views: View::composer('*', function ($view) { // }); View Creators View creators are very similar to view composers; however, they are executed immediately after the view is instantiated instead of waiting until the view is about to render. To register a view creator, use the creator method: View::creator('profile', 'App\Http\View\Creators\ProfileCreator');
Views [ Creating Views ] { resources/views, return view('greeting', ['name' => 'James']); return view('admin.profile', $data); View::exists('emails.customer'), View::first(['custom.admin', 'admin'], $data); }
Views contain the HTML served by your application and separate your controller / application logic from your presentation logic. Views are stored in the resources/views directory. A simple view might look something like this: <!-- View stored in resources/views/greeting.blade.php --> <html> <body> <h1>Hello, {{ $name }}</h1> </body> </html> Since this view is stored at resources/views/greeting.blade.php, we may return it using the global view helper like so: Route::get('/', function () { return view('greeting', ['name' => 'James']); }); As you can see, the first argument passed to the view helper corresponds to the name of the view file in the resources/views directory. The second argument is an array of data that should be made available to the view. In this case, we are passing the namevariable, which is displayed in the view using Blade syntax. Views may also be nested within sub-directories of the resources/views directory. "Dot" notation may be used to reference nested views. For example, if your view is stored at resources/views/admin/profile.blade.php, you may reference it like so: return view('admin.profile', $data); Determining If A View Exists If you need to determine if a view exists, you may use the View facade. The existsmethod will return true if the view exists: use Illuminate\Support\Facades\View; if (View::exists('emails.customer')) { // } Creating The First Available View Using the first method, you may create the first view that exists in a given array of views. This is useful if your application or package allows views to be customized or overwritten: return view()->first(['custom.admin', 'admin'], $data); You may also call this method via the View facade: use Illuminate\Support\Facades\View; return View::first(['custom.admin', 'admin'], $data);
Security [ Authentication ] { php artisan make:auth, config/auth.php, "guards" and "providers", password column is at least 60 characters, a nullable, string remember_token column of 100 characters - remember me, RegisterController, LoginController, ForgotPasswordController, ResetPasswordController, Auth::routes(['register' => false]); $redirectTo = '/'; redirectTo() username(), guard(), validator method of the RegisterController, Auth::user(), Auth::id(), $request->user(), Auth::check(), middleware('auth'), middleware('auth:api'), ThrottlesLogins trait, Auth::attempt($credentials), redirect()->intended('dashboard'), Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1]), Auth::guard('admin')->attempt($credentials), Auth::logout(); Auth::attempt(['email' => $email, 'password' => $password], $remember), Auth::viaRemember(), Auth::login($user, true); Auth::guard('admin')->login($user); Auth::loginUsingId(1, true); Auth::once($credentials), middleware('auth.basic'), Auth::onceBasic(), Auth::logout(), AuthenticateSession, Auth::logoutOtherDevices($password), Auth::extend, 'guards' => [ 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ], Auth::viaRequest, Auth::provider, UserProvider contract, Authenticatable Contract, Events: Registered, Attempting, Authenticated, Login, Failed, Logout, Lockout, PasswordReset}
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.test/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. Database Considerations By default, Laravel includes an App\User Eloquent model in your app directory. This model may be used with the default Eloquent authentication driver. If your application is not using Eloquent, you may use the database authentication driver which uses the Laravel query builder. When building the database schema for the App\User model, make sure the password column is at least 60 characters in length. Maintaining the default string column length of 255 characters would be a good choice. Also, you should verify that your users (or equivalent) table contains a nullable, string remember_token column of 100 characters. This column will be used to store a token for users that select the "remember me" option when logging into your application Authentication Quickstart Laravel ships with several pre-built authentication controllers, which are located in the App\Http\Controllers\Auth namespace. The RegisterController handles new user registration, the LoginController handles authentication, the ForgotPasswordControllerhandles e-mailing links for resetting passwords, and the ResetPasswordControllercontains the logic to reset passwords. Each of these controllers uses a trait to include their necessary methods. For many applications, you will not need to modify these controllers at all. Routing Laravel 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. If your application doesn't need registration, you may disable it by removing the newly created RegisterControllerand modifying your route declaration: Auth::routes(['register' => false]);. 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/authdirectory. 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. Authenticating Now that you have routes and views setup for the included authentication controllers, you are ready to register and authenticate new users for your application! You may access your application in a browser since the authentication controllers already contain the logic (via their traits) to authenticate existing users and store new users in the database. Path Customization When a user is successfully authenticated, they will be redirected to the /home URI. You can customize the post-authentication redirect location by defining a redirectToproperty on the LoginController, RegisterController, ResetPasswordController, and VerificationController: protected $redirectTo = '/'; Next, you should modify the RedirectIfAuthenticated middleware's handle method to use your new URI when redirecting the user. If the redirect path needs custom generation logic you may define a redirectTomethod instead of a redirectTo property: protected function redirectTo() { return '/path'; } The redirectTo method will take precedence over the redirectTo attribute. 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'; } 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'); } 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\Userrecords in your database using the Eloquent ORM. You are free to modify this method according to the needs of your database. Retrieving The Authenticated User You may access the authenticated user via the Auth facade: 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: $request->user() Determining If The Current User Is Authenticated To determine if the user is already logged into your application, you may use the checkmethod on the Auth facade, which will return true if the user is authenticated Even though it is possible to determine if a user is authenticated using the check method, you will typically use a middleware to verify that the user is authenticated before allowing the user access to certain routes / controllers. To learn more about this, check out the documentation on protecting routes. Protecting Routes Route middleware can be used to only allow authenticated users to access a given route. Laravel ships with an auth middleware, which is defined at Illuminate\Auth\Middleware\Authenticate. Since this middleware is already registered in your HTTP kernel, all you need to do is attach the middleware to a route definition: Route::get('profile', function () { // Only authenticated users may enter... })->middleware('auth'); If you are using controllers, you may call the middleware method from the controller's constructor instead of attaching it in the route definition directly: public function __construct() { $this->middleware('auth'); } Redirecting Unauthenticated Users When the auth middleware detects an unauthorized user, it will redirect the user to the login named route. You may modify this behavior by updating the redirectTo function in your app/Http/Middleware/Authenticate.php file protected function redirectTo($request) { return route('login'); } Specifying A Guard When attaching the auth middleware to a route, you may also specify which guard should be used to authenticate the user. The guard specified should correspond to one of the keys in the guards array of your auth.php configuration file: public function __construct() { $this->middleware('auth:api'); } Login Throttling If you are using Laravel's built-in LoginController class, the Illuminate\Foundation\Auth\ThrottlesLogins trait will already be included in your controller. By default, the user will not be able to login for one minute if they fail to provide the correct credentials after several attempts. The throttling is unique to the user's username / e-mail address and their IP address. Manually Authenticating Users Note that you are not required to use the authentication controllers included with Laravel. If you choose to remove these controllers, you will need to manage user authentication using the Laravel authentication classes directly. Don't worry, it's a cinch! We will access Laravel's authentication services via the Auth facade, so we'll need to make sure to import the Auth facade at the top of the class. Next, let's check out the attempt method: Auth::attempt($credentials) 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 passwordvalue 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, falsewill be returned. The intended method on the redirector will redirect the user to the URL they were attempting to access before being intercepted by the authentication middleware. A fallback URI may be given to this method in case the intended destination is not available. Specifying Additional Conditions If you wish, you may also add extra conditions to the authentication query in addition to the user's e-mail and password. For example, we may verify that user is marked as "active": if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) { // The user is active, not suspended, and exists. } 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)) { // } Logging Out To log users out of your application, you may use the logout method on the Authfacade. This will clear the authentication information in the user's session: Auth::logout(); Remembering Users If you would like to provide "remember me" functionality in your application, you may pass a boolean value as the second argument to the attempt method, which will keep the user authenticated indefinitely, or until they manually logout. Your users table must include the string remember_token column, which will be used to store the "remember me" token. if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) { // The user is being remembered... } 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()) { // } Other Authentication Methods Authenticate A User Instance If you need to log an existing user instance into your application, you may call the login method with the user instance. The given object must be an implementation of the Illuminate\Contracts\Auth\Authenticatable contract. The App\User model included with Laravel already implements this interface: Auth::login($user); // Login and "remember" the given user... Auth::login($user, true); You may specify the guard instance you would like to use: Auth::guard('admin')->login($user); Authenticate A User By ID To log a user into the application by their ID, you may use the loginUsingId method. This method accepts the primary key of the user you wish to authenticate: Auth::loginUsingId(1); // Login and "remember" the given user... Auth::loginUsingId(1, true); Authenticate A User Once You may use the once method to log a user into the application for a single request. No sessions or cookies will be utilized, which means this method may be helpful when building a stateless API: if (Auth::once($credentials)) { // } HTTP Basic Authentication HTTP Basic Authentication provides a quick way to authenticate users of your application without setting up a dedicated "login" page. To get started, attach the auth.basic middleware to your route. The auth.basic middleware is included with the Laravel framework, so you do not need to define it: Route::get('profile', function () { // Only authenticated users may enter... })->middleware('auth.basic'); Once the middleware has been attached to the route, you will automatically be prompted for credentials when accessing the route in your browser. By default, the auth.basic middleware will use the email column on the user record as the "username". A Note On FastCGI If you are using PHP FastCGI, HTTP Basic authentication may not work correctly out of the box. The following lines should be added to your .htaccess file: RewriteCond %{HTTP:Authorization} ^(.+)$ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] Stateless HTTP Basic Authentication You may also use HTTP Basic Authentication without setting a user identifier cookie in the session, which is particularly useful for API authentication. To do so, define a middleware that calls the onceBasic method. If no exception is thrown by the onceBasicmethod, the request may be passed further into the application: public function handle($request, $next) { return Auth::onceBasic() ?: $next($request); } Logging Out To manually log users out of your application, you may use the logout method on the Auth facade. This will clear the authentication information in the user's session: use Illuminate\Support\Facades\Auth; Auth::logout(); Invalidating Sessions On Other Devices Laravel also provides a mechanism for invalidating and "logging out" a user's sessions that are active on other devices without invalidating the session on their current device. Before getting started, you should make sure that the Illuminate\Session\Middleware\AuthenticateSession middleware is present and un-commented in your app/Http/Kernel.php class' web middleware group: 'web' => [ // ... \Illuminate\Session\Middleware\AuthenticateSession::class, // ... ], Then, you may use the logoutOtherDevices method on the Auth facade. This method requires the user to provide their current password, which your application should accept through an input form: use Illuminate\Support\Facades\Auth; Auth::logoutOtherDevices($password); When the logoutOtherDevices method is invoked, the user's other sessions will be invalidated entirely, meaning they will be "logged out" of all guards they were previously authenticated by Adding Custom Guards You may define your own authentication guards using the extend method on the Authfacade. 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: 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 guardsconfiguration of your auth.php configuration file: 'guards' => [ 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ], Closure Request Guards The simplest way to implement a custom, HTTP request based authentication system is by using the Auth::viaRequest method. This method allows you to quickly define your authentication process using a single Closure. To get started, call the Auth::viaRequest method within the boot method of your AuthServiceProvider. The viaRequest method accepts a guard name as its first argument. This name can be any string that describes your custom guard. The second argument passed to the method should be a Closure that receives the incoming HTTP request and returns a user instance or, if authentication fails, null: Auth::viaRequest('custom-token', function ($request) { return User::where('token', $request->token)->first(); }); Once your custom guard has been defined, you may use this guard in the guardsconfiguration of your auth.php configuration file: 'guards' => [ 'api' => [ 'driver' => 'custom-token', ], ], Adding Custom User Providers If you are not using a traditional relational database to store your users, you will need to extend Laravel with your own authentication user provider. We will use the providermethod on the Auth facade to define a custom user provider: 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', ], ], The Authenticatable Contract Now that we have explored each of the methods on the UserProvider, let's take a look at the Authenticatable contract. Remember, the provider should return implementations of this interface from the retrieveById, retrieveByToken, and retrieveByCredentials methods: namespace Illuminate\Contracts\Auth; interface Authenticatable { public function getAuthIdentifierName(); public function getAuthIdentifier(); public function getAuthPassword(); public function getRememberToken(); public function setRememberToken($value); public function getRememberTokenName(); } This interface is simple. The getAuthIdentifierName method should return the name of the "primary key" field of the user and the getAuthIdentifier method should return the "primary key" of the user. In a MySQL back-end, again, this would be the auto-incrementing primary key. The getAuthPassword should return the user's hashed password. This interface allows the authentication system to work with any User class, regardless of what ORM or storage abstraction layer you are using. By default, Laravel includes a User class in the app directory which implements this interface, so you may consult this class for an implementation example. Events Laravel raises a variety of events during the authentication process. You may attach listeners to these events in your EventServiceProvider: /** * 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', ], ];
Mail [ Local Development ] { Log Driver, Universal To in config/mail.php 'to' => [ 'address' => '[email protected]', 'name' => 'Example' ], Mailtrap }
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. 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. 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' => '[email protected]', 'name' => 'Example' ], 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.
Routing [ Route Model Binding ] { Implicit Binding, Customizing The Key Name, Explicit Binding, Customizing The Resolution Logic }
When injecting a model ID to a route or controller action, you will often query to retrieve the model that corresponds to that ID. Laravel route model binding provides a convenient way to automatically inject the model instances directly into your routes. For example, instead of injecting a user's ID, you can inject the entire User model instance that matches the given ID. Implicit Binding Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name. For example: Route::get('api/users/{user}', function (App\User $user) { return $user->email; }); Since the $user variable is type-hinted as the App\User Eloquent model and the variable name matches the {user} URI segment, Laravel will automatically inject the model instance that has an ID matching the corresponding value from the request URI. If a matching model instance is not found in the database, a 404 HTTP response will automatically be generated. Customizing The Key Name If you would like model binding to use a database column other than id when retrieving a given model class, you may override the getRouteKeyName method on the Eloquent model: /** * Get the route key for the model. * * @return string */ public function getRouteKeyName() { return 'slug'; } Explicit Binding To register an explicit binding, use the router's model method to specify the class for a given parameter. You should define your explicit model bindings in the boot method of the RouteServiceProvider class: public function boot() { parent::boot(); Route::model('user', App\User::class); } Next, define a route that contains a {user} parameter: Route::get('profile/{user}', function (App\User $user) { // }); Since we have bound all {user} parameters to the App\User model, a User instance will be injected into the route. So, for example, a request to profile/1 will inject the Userinstance from the database which has an ID of 1. If a matching model instance is not found in the database, a 404 HTTP response will be automatically generated. Customizing The Resolution Logic If you wish to use your own resolution logic, you may use the Route::bind method. The Closure you pass to the bind method will receive the value of the URI segment and should return the instance of the class that should be injected into the route: /** * Bootstrap any application services. * * @return void */ public function boot() { parent::boot(); Route::bind('user', function ($value) { return App\User::where('name', $value)->first() ?? abort(404); }); } Alternatively, you may override the resolveRouteBinding method on your Eloquent model. This method will receive the value of the URI segment and should return the instance of the class that should be injected into the route: /** * Retrieve the model for a bound value. * * @param mixed $value * @return \Illuminate\Database\Eloquent\Model|null */ public function resolveRouteBinding($value) { return $this->where('name', $value)->first() ?? abort(404); }
Requests [ Proxy Configuration ] { }
When running your applications behind a load balancer that terminates TLS / SSL certificates, you may notice your application sometimes does not generate HTTPS links. Typically this is because your application is being forwarded traffic from your load balancer on port 80 and does not know it should generate secure links. To solve this, you may use the App\Http\Middleware\TrustProxies middleware that is included in your Laravel application, which allows you to quickly customize the load balancers or proxies that should be trusted by your application. Your trusted proxies should be listed as an array on the $proxies property of this middleware. In addition to configuring the trusted proxies, you may configure the proxy $headers that should be trusted: If you are using AWS Elastic Load Balancing, your $headersvalue should be Request::HEADER_X_FORWARDED_AWS_ELB. For more information on the constants that may be used in the $headers property, check out Symfony's documentation on trusting proxies. Trusting All Proxies If you are using Amazon AWS or another "cloud" load balancer provider, you may not know the IP addresses of your actual balancers. In this case, you may use * to trust all proxies: protected $proxies = '*';
Caching [ Creating Custom Drivers ] { use Illuminate\Contracts\Cache\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() {}; Cache::extend('mongo', function ($app) { return Cache::repository(new MongoStore); }); }
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: 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); }); 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 preference 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: 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: 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.
Logging [ Writing to Specific Channels ] { Log::channel('slack'), Log::stack(['single', 'slack']) }
You may write information to the logs using the Log facade. As previously mentioned, the logger provides the eight logging levels defined in the RFC 5424 specification: 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); By default, the message will be written to the default log channel as configured by your config/logging.php configuration file. 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]); Writing To Specific Channels Sometimes you may wish to log a message to a channel other than your application's default channel. You may use the channel method on the Log facade to retrieve and log to any channel defined in your configuration file: Log::channel('slack')->info('Something happened!'); If you would like to create an on-demand logging stack consisting of multiple channels, you may use the stack method: Log::stack(['single', 'slack'])->info('Something happened!');
Sessions [ Custom Drivers ] { SessionHandlerInterface, open, close, read, write, destroy, gc, Session::extend}
Your custom session driver should implement the SessionHandlerInterface. This interface contains just a few simple methods we need to implement. public function open($savePath, $sessionName) {} public function close() {} public function read($sessionId) {} public function write($sessionId, $data) {} public function destroy($sessionId) {} public function gc($lifetime) {} The open method would typically be used in file based session store systems. Since Laravel ships with a file session driver, you will almost never need to put anything in this method. You can leave it as an empty stub. It is a fact of poor interface design (which we'll discuss later) that PHP requires us to implement this method The close method, like the open method, can also usually be disregarded. For most drivers, it is not needed. The read method should return the string version of the session data associated with the given $sessionId. There is no need to do any serialization or other encoding when retrieving or storing session data in your driver, as Laravel will perform the serialization for you. The write method should write the given $data string associated with the $sessionId to some persistent storage system, such as MongoDB, Dynamo, etc. Again, you should not perform any serialization - Laravel will have already handled that for you. The destroy method should remove the data associated with the $sessionId from persistent storage. The gc method should destroy all session data that is older than the given $lifetime, which is a UNIX timestamp. For self-expiring systems like Memcached and Redis, this method may be left empty. Registering The Driver Once your driver has been implemented, you are ready to register it with the framework. To add additional drivers to Laravel's session backend, you may use the extend method on the Session facade. You should call the extend method from the boot method of a service provider. You may do this from the existing AppServiceProvideror create an entirely new provider: Session::extend('mongo', function ($app) { // Return implementation of SessionHandlerInterface... return new MongoSessionHandler; }); Once the session driver has been registered, you may use the mongo driver in your config/session.php configuration file.
Helper Methods [ Misc ] { 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 }
abort() 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); abort_if() 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. abort_unless() 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. app() 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'); auth() The auth function returns an authenticator instance. You may use it instead of the Authfacade for convenience: $user = auth()->user(); If needed, you may specify which guard instance you would like to access: $user = auth('admin')->user(); back() The back function generates a redirect HTTP response to the user's previous location: return back($status = 302, $headers = [], $fallback = false); return back(); bcrypt() 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'); broadcast() The broadcast function broadcasts the given event to its listeners: broadcast(new UserRegistered($user)); blank() 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. cache() 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)); class_uses_recursive() The class_uses_recursive function returns all traits used by a class, including traits used by all of its parent classes: $traits = class_uses_recursive(App\User::class); collect() The collect function creates a collection instance from the given value: $collection = collect(['taylor', 'abigail']); config() 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]); cookie() The cookie function creates a new cookie instance: $cookie = cookie('name', 'value', $minutes); csrf_field() The csrf_field function generates an HTML hidden input field containing the value of the CSRF token. For example, using Blade syntax: {{ csrf_field() }} csrf_token() The csrf_token function retrieves the value of the current CSRF token: $token = csrf_token(); dd() 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. decrypt() The decrypt function decrypts the given value using Laravel's encrypter: $decrypted = decrypt($encrypted_value); dispatch() The dispatch function pushes the given job onto the Laravel job queue: dispatch(new App\Jobs\SendEmails); dispatch_now() The dispatch_now function runs the given job immediately and returns the value from its handle method: $result = dispatch_now(new App\Jobs\SendEmails); dump() 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 ddfunction instead. You may use Artisan's dump-server command to intercept all dump calls and display them in your console window instead of your browser. encrypt() The encrypt function encrypts the given value using Laravel's encrypter: $encrypted = encrypt($unencrypted_value); env() 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'); 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. event() The event function dispatches the given event to its listeners: event(new UserRegistered($user)); factory() 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(); filled() 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. info() 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]); logger() 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.'); method_field() 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> now() The now function creates a new Illuminate\Support\Carbon instance for the current time: $now = now(); old() The old function retrieves an old input value flashed into the session: $value = old('value'); $value = old('value', 'default'); optional() 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) !!} The optional function also accepts a Closure as its second argument. The Closure will be invoked if the value provided as the first argument is not null: return optional(User::find($id), function ($user) { return new DummyUser; }); policy() The policy method retrieves a policy instance for a given class: $policy = policy(App\User::class); redirect() 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'); report() The report function will report an exception using your exception handler's reportmethod: report($e); request() The request function returns the current request instance or obtains an input item: $request = request(); $value = request('key', $default); rescue() 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(); }); resolve() The resolve function resolves a given class or interface name to its instance using the service container: $api = resolve('HelpSpot\API'); response() 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); retry() 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); session() 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); tap() 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 what the method actually returns in its definition. For example, the Eloquent updatemethod 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, ]); today() The today function creates a new Illuminate\Support\Carbon instance for the current date: $today = today(); throw_if() 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' ); throw_unless() 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' ); trait_uses_recursive() The trait_uses_recursive function returns all traits used by a trait: $traits = trait_uses_recursive(\Illuminate\Notifications\Notifiable::class); transform() 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 validator() 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); value() 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 view() The view function retrieves a view instance: return view('auth.login'); with() 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
Validation [ Validation Rules ] { Accepted, Active, URL, After (Date), After Or Equal (Date), Alpha, Alpha Dash, Alpha Numeric, Array, Bail, Before (Date), Before Or Equal (Date), Between, Boolean, Confirmed, Date, Date Equals, Date Format, Different, Digits, Digits Between, Dimensions (Image Files), Distinct, E-Mail, Exists (Database), File, Filled, Greater Than, Greater Than Or Equal, Image (File), In, In Array, Integer, IP Address, JSON, Less Than, Less Than Or Equal, Max, MIME Types, MIME Type By File, Extension, Min, Not In, Not Regex, Nullable, Numeric, Present, Regular Expression, Required, Required If, Required Unless, Required With, Required With All, Required Without, Required Without All, Same, Size, Starts With, String, Timezone, Unique (Database), URL, UUID }
accepted The field under validation must be yes, on, 1, or true. This is useful for validating "Terms of Service" acceptance. active_url The field under validation must have a valid A or AAAA record according to the dns_get_record PHP function. after:date The field under validation must be a value after a given date. The dates will be passed into the strtotime PHP function: 'start_date' => 'required|date|after:tomorrow' Instead of passing a date string to be evaluated by strtotime, you may specify another field to compare against the date: 'finish_date' => 'required|date|after:start_date' after_or_equal:date The field under validation must be a value after or equal to the given date. For more information, see the after rule. alpha The field under validation must be entirely alphabetic characters. alpha_dash The field under validation may have alpha-numeric characters, as well as dashes and underscores. alpha_num The field under validation must be entirely alpha-numeric characters. array The field under validation must be a PHP array. bail Stop running validation rules after the first validation failure. before:date The field under validation must be a value preceding the given date. The dates will be passed into the PHP strtotime function. In addition, like the after rule, the name of another field under validation may be supplied as the value of date. before_or_equal:date The field under validation must be a value preceding or equal to the given date. The dates will be passed into the PHP strtotime function. In addition, like the after rule, the name of another field under validation may be supplied as the value of date. between:min,max The field under validation must have a size between the given min and max. Strings, numerics, arrays, and files are evaluated in the same fashion as the size rule. boolean The field under validation must be able to be cast as a boolean. Accepted input are true, false, 1, 0, "1", and "0". confirmed The field under validation must have a matching field of foo_confirmation. For example, if the field under validation is password, a matching password_confirmation field must be present in the input. date The field under validation must be a valid, non-relative date according to the strtotimePHP function. date_equals:date The field under validation must be equal to the given date. The dates will be passed into the PHP strtotime function. date_format:format The field under validation must match the given format. You should use either date or date_format when validating a field, not both. different:field The field under validation must have a different value than field. digits:value The field under validation must be numeric and must have an exact length of value. digits_between:min,max The field under validation must have a length between the given min and max. dimensions The file under validation must be an image meeting the dimension constraints as specified by the rule's parameters: 'avatar' => 'dimensions:min_width=100,min_height=200' Available constraints are: min_width, max_width, min_height, max_height, width, height, ratio. A ratio constraint should be represented as width divided by height. This can be specified either by a statement like 3/2 or a float like 1.5: 'avatar' => 'dimensions:ratio=3/2' Since this rule requires several arguments, you may use the Rule::dimensions method to fluently construct the rule: use Illuminate\Validation\Rule; Validator::make($data, [ 'avatar' => [ 'required', Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2), ], ]); distinct When working with arrays, the field under validation must not have any duplicate values. 'foo.*.id' => 'distinct' email The field under validation must be formatted as an e-mail address. exists:table,column The field under validation must exist on a given database table. Basic Usage Of Exists Rule 'state' => 'exists:states' If the column option is not specified, the field name will be used. Specifying A Custom Column Name 'state' => 'exists:states,abbreviation' Occasionally, you may need to specify a specific database connection to be used for the exists query. You can accomplish this by prepending the connection name to the table name using "dot" syntax: 'email' => 'exists:connection.staff,email' If you would like to customize the query executed by the validation rule, you may use the Rule class to fluently define the rule. In this example, we'll also specify the validation rules as an array instead of using the | character to delimit them: use Illuminate\Validation\Rule; Validator::make($data, [ 'email' => [ 'required', Rule::exists('staff')->where(function ($query) { $query->where('account_id', 1); }), ], ]); file The field under validation must be a successfully uploaded file. filled The field under validation must not be empty when it is present. gt:field The field under validation must be greater than the given field. The two fields must be of the same type. Strings, numerics, arrays, and files are evaluated using the same conventions as the size rule. gte:field The field under validation must be greater than or equal to the given field. The two fields must be of the same type. Strings, numerics, arrays, and files are evaluated using the same conventions as the size rule. image The file under validation must be an image (jpeg, png, bmp, gif, or svg) in:foo,bar,... The field under validation must be included in the given list of values. Since this rule often requires you to implode an array, the Rule::in method may be used to fluently construct the rule: use Illuminate\Validation\Rule; Validator::make($data, [ 'zones' => [ 'required', Rule::in(['first-zone', 'second-zone']), ], ]); in_array:anotherfield.* The field under validation must exist in anotherfield's values. integer The field under validation must be an integer. ip The field under validation must be an IP address. ipv4 The field under validation must be an IPv4 address. ipv6 The field under validation must be an IPv6 address. json The field under validation must be a valid JSON string. lt:field The field under validation must be less than the given field. The two fields must be of the same type. Strings, numerics, arrays, and files are evaluated using the same conventions as the size rule. lte:field The field under validation must be less than or equal to the given field. The two fields must be of the same type. Strings, numerics, arrays, and files are evaluated using the same conventions as the size rule. max:value The field under validation must be less than or equal to a maximum value. Strings, numerics, arrays, and files are evaluated in the same fashion as the size rule. mimetypes:text/plain,... The file under validation must match one of the given MIME types: 'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime' To determine the MIME type of the uploaded file, the file's contents will be read and the framework will attempt to guess the MIME type, which may be different from the client provided MIME type. mimes:foo,bar,... The file under validation must have a MIME type corresponding to one of the listed extensions. Basic Usage Of MIME Rule 'photo' => 'mimes:jpeg,bmp,png' Even though you only need to specify the extensions, this rule actually validates against the MIME type of the file by reading the file's contents and guessing its MIME type. A full listing of MIME types and their corresponding extensions may be found at the following location: https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types min:value The field under validation must have a minimum value. Strings, numerics, arrays, and files are evaluated in the same fashion as the size rule. not_in:foo,bar,... The field under validation must not be included in the given list of values. The Rule::notIn method may be used to fluently construct the rule: use Illuminate\Validation\Rule; Validator::make($data, [ 'toppings' => [ 'required', Rule::notIn(['sprinkles', 'cherries']), ], ]); not_regex:pattern The field under validation must not match the given regular expression. Internally, this rule uses the PHP preg_match function. The pattern specified should obey the same formatting required by preg_match and thus also include valid delimiters. For example: 'email' => 'not_regex:/^.+$/i'. Note: When using the regex / not_regex patterns, it may be necessary to specify rules in an array instead of using pipe delimiters, especially if the regular expression contains a pipe character. nullable The field under validation may be null. This is particularly useful when validating primitive such as strings and integers that can contain null values. numeric The field under validation must be numeric. present The field under validation must be present in the input data but can be empty. regex:pattern The field under validation must match the given regular expression. Internally, this rule uses the PHP preg_match function. The pattern specified should obey the same formatting required by preg_match and thus also include valid delimiters. For example: 'email' => 'regex:/^.+@.+$/i'. Note: When using the regex / not_regex patterns, it may be necessary to specify rules in an array instead of using pipe delimiters, especially if the regular expression contains a pipe character. required The field under validation must be present in the input data and not empty. A field is considered "empty" if one of the following conditions are true: The value is null. The value is an empty string. The value is an empty array or empty Countable object. The value is an uploaded file with no path. required_if:anotherfield,value,... The field under validation must be present and not empty if the anotherfield field is equal to any value. If you would like to construct a more complex condition for the required_if rule, you may use the Rule::requiredIf method. This methods accepts a boolean or a Closure. When passed a Closure, the Closure should return true or false to indicate if the field under validation is required: use Illuminate\Validation\Rule; Validator::make($request->all(), [ 'role_id' => Rule::requiredIf($request->user()->is_admin), ]); Validator::make($request->all(), [ 'role_id' => Rule::requiredIf(function () use ($request) { return $request->user()->is_admin; }), ]); required_unless:anotherfield,value,... The field under validation must be present and not empty unless the anotherfield field is equal to any value. required_with:foo,bar,... The field under validation must be present and not empty only if any of the other specified fields are present. required_with_all:foo,bar,... The field under validation must be present and not empty only if all of the other specified fields are present. required_without:foo,bar,... The field under validation must be present and not empty only when any of the other specified fields are not present. required_without_all:foo,bar,... The field under validation must be present and not empty only when all of the other specified fields are not present. same:field The given field must match the field under validation. size:value The field under validation must have a size matching the given value. For string data, value corresponds to the number of characters. For numeric data, value corresponds to a given integer value. For an array, size corresponds to the count of the array. For files, size corresponds to the file size in kilobytes. starts_with:foo,bar,... The field under validation must start with one of the given values. string The field under validation must be a string. If you would like to allow the field to also be null, you should assign the nullable rule to the field. timezone The field under validation must be a valid timezone identifier according to the timezone_identifiers_list PHP function. unique:table,column,except,idColumn The field under validation must be unique in a given database table. If the columnoption is not specified, the field name will be used. Specifying A Custom Column Name: 'email' => 'unique:users,email_address' Custom Database Connection Occasionally, you may need to set a custom connection for database queries made by the Validator. As seen above, setting unique:users as a validation rule will use the default database connection to query the database. To override this, specify the connection and the table name using "dot" syntax: 'email' => 'unique:connection.users,email_address' Forcing A Unique Rule To Ignore A Given ID: Sometimes, you may wish to ignore a given ID during the unique check. For example, consider an "update profile" screen that includes the user's name, e-mail address, and location. You will probably want to verify that the e-mail address is unique. However, if the user only changes the name field and not the e-mail field, you do not want a validation error to be thrown because the user is already the owner of the e-mail address. To instruct the validator to ignore the user's ID, we'll use the Rule class to fluently define the rule. In this example, we'll also specify the validation rules as an array instead of using the | character to delimit the rules: use Illuminate\Validation\Rule; Validator::make($data, [ 'email' => [ 'required', Rule::unique('users')->ignore($user->id), ], ]); If your table uses a primary key column name other than id, you may specify the name of the column when calling the ignore method: Rule::unique('users')->ignore($user->id, 'user_id') By default, the unique rule will check the uniqueness of the column matching the name of the attribute being validated. However, you may pass a different column name as the second argument to the unique method: Rule::unique('users', 'email_address')->ignore($user->id), Adding Additional Where Clauses: You may also specify additional query constraints by customizing the query using the where method. For example, let's add a constraint that verifies the account_id is 1: 'email' => Rule::unique('users')->where(function ($query) { return $query->where('account_id', 1); }) url The field under validation must be a valid URL. uuid The field under validation must be a valid RFC 4122 (version 1, 3, 4, or 5) universally unique identifier (UUID).
Helper Methods [ URLs ] { action, asset, secure_asset, route, secure_url, url }
action() 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'); $url = action([HomeController::class, 'index']); If the method accepts route parameters, you may pass them as the second argument to the method: $url = action('UserController@profile', ['id' => 1]); asset() The asset function generates a URL for an asset using the current scheme of the request (HTTP or HTTPS): $url = asset('img/photo.jpg'); You can configure the asset URL host by setting the ASSET_URL variable in your .env file. This can be useful if you host your assets on an external service like Amazon S3: // ASSET_URL=http://example.com/assets $url = asset('img/photo.jpg'); // http://example.com/assets/img/photo.jpg secure_asset() The secure_asset function generates a URL for an asset using HTTPS: $url = secure_asset('img/photo.jpg'); route() 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); secure_url() 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]); url() 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();
Collections [ Collection Methods ] { 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, some, sort, sortBy, sortByDesc, sortKeys, sortKeysDesc, splice, split, sum, take, tap, times, toArray, toJson, transform, union, unique, uniqueStrict, unless, unlessEmpty, unlessNotEmpty, unwrap, values, when, whenEmpty, whenNotEmpty, where, whereStrict, whereBetween, whereIn, whereInStrict, whereInstanceOf, whereNotBetween, whereNotIn, whereNotInStrict, wrap, zip }
all() The all method returns the underlying array represented by the collection: collect([1, 2, 3])->all(); // [1, 2, 3] average() Alias for the avg method. avg() 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 chunk() 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 collapse() 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] combine() The combine method combines the values of the collection, as keys, with the values of another array or collection: $collection = collect(['name', 'age']); $combined = $collection->combine(['George', 29]); $combined->all(); // ['name' => 'George', 'age' => 29] concat() 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'] contains() 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. containsStrict() This method has the same signature as the contains method; however, all values are compared using "strict" comparisons. count() The count method returns the total number of items in the collection: $collection = collect([1, 2, 3, 4]); $collection->count(); // 4 crossJoin() 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'], ] */ dd() 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" ] } */ diff() 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] diffAssoc() 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] diffKeys() 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] dump() 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 ddmethod instead. each() The each method iterates over the items in the collection and passes each item to a callback: $collection->each(function ($item, $key) { // }); If you would like to stop iterating through the items, you may return false from your callback: $collection->each(function ($item, $key) { if (/* some condition */) { return false; } }); eachSpread() 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; }); every() 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 If the collection is empty, every will return true: $collection = collect([]); $collection->every(function($value, $key) { return $value > 2; }); // true except() 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. filter() 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. first() 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 firstWhere() 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] flatMap() 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']; flatten() 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. flip() 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'] forget() 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'] Unlike most other collection methods, forget does not return a new modified collection; it modifies the collection it is called on. forPage() 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] get() 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 groupBy() 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'], ], ] */ Instead of passing a string key, you may 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 be applied to 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']], ], ], ]; */ has() The has method determines if a given key exists in the collection: $collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]); $collection->has('product'); // true $collection->has(['product', 'amount']); // true $collection->has(['amount', 'price']); // false implode() 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' intersect() 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'] intersectByKeys() 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] isEmpty() The isEmpty method returns true if the collection is empty; otherwise, false is returned: collect([])->isEmpty(); // true isNotEmpty() The isNotEmpty method returns true if the collection is not empty; otherwise, false is returned: collect([])->isNotEmpty(); // false keyBy() 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'], ] */ keys() 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'] last() 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 macro() 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. make() The static make method creates a new collection instance. See the Creating Collections section. map() 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] 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. mapInto() 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')] mapSpread() 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 ($even, $odd) { return $even + $odd; }); $sequence->all(); // [1, 5, 9, 13, 17] mapToGroups() 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' => ['Johnny Doe'], ] */ $grouped->get('Sales')->all(); // ['John Doe', 'Jane Doe'] mapWithKeys() 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' => '[email protected]' ], [ 'name' => 'Jane', 'department' => 'Marketing', 'email' => '[email protected]' ] ]); $keyed = $collection->mapWithKeys(function ($item) { return [$item['email'] => $item['name']]; }); $keyed->all(); /* [ '[email protected]' => 'John', '[email protected]' => 'Jane', ] */ max() 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 median() 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 merge() 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'] min() 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 mode() 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] nth() 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'] only() 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. pad() 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'] partition() 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, $equalOrAboveThree) = $collection->partition(function ($i) { return $i < 3; }); $underThree->all(); // [1, 2] $equalOrAboveThree->all(); // [3, 4, 5, 6] pipe() 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 pluck() 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'] If duplicate keys exist, the last matching element will be inserted into the plucked collection: $collection = collect([ ['brand' => 'Tesla', 'color' => 'red'], ['brand' => 'Pagani', 'color' => 'white'], ['brand' => 'Tesla', 'color' => 'black'], ['brand' => 'Pagani', 'color' => 'orange'], ]); $plucked = $collection->pluck('color', 'brand'); $plucked->all(); // ['Tesla' => 'black', 'Pagani' => 'orange'] pop() 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] prepend() 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] pull() 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'] push() 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] put() 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] random() 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) If the Collection has fewer items than requested, the method will throw an InvalidArgumentException. reduce() 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 reject() 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. reverse() 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', ] */ search() 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 shift() 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] shuffle() 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) slice() 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. some() Alias for the contains method. sort() 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. If you need to sort a collection of nested arrays or objects, see the sortBy and sortByDesc methods. sortBy() 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']], ] */ sortByDesc() This method has the same signature as the sortBy method, but will sort the collection in the opposite order. sortKeys() The sortKeys method sorts the collection by the keys of the underlying associative array: $collection = collect([ 'id' => 22345, 'first' => 'John', 'last' => 'Doe', ]); $sorted = $collection->sortKeys(); $sorted->all(); /* [ 'first' => 'John', 'id' => 22345, 'last' => 'Doe', ] */ sortKeysDesc() This method has the same signature as the sortKeys method, but will sort the collection in the opposite order. splice() 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] split() 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]] sum() 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 take() 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] tap() 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 times() 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] toArray() 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], ] */ 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. toJson() The toJson method converts the collection into a JSON serialized string: $collection = collect(['name' => 'Desk', 'price' => 200]); $collection->toJson(); // '{"name":"Desk", "price":200}' transform() 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] Unlike most other collection methods, transform modifies the collection itself. If you wish to create a new collection instead, use the map method. union() 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']] unique() 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. uniqueStrict() This method has the same signature as the unique method; however, all values are compared using "strict" comparisons. unless() The unless method will execute the given callback unless the first argument given to the method evaluates to true For the inverse of unless, see the when method. unlessEmpty() Alias for the whenNotEmpty method. unlessNotEmpty() Alias for the whenEmpty method. unwrap() 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' values() The values method returns a new collection with the keys reset to consecutive integers: when() The when method will execute the given callback when the first argument given to the method evaluates to true: For the inverse of when, see the unless method. whenEmpty() The whenEmpty method will execute the given callback when the collection is empty: For the inverse of whenEmpty, see the whenNotEmpty method. whenNotEmpty() The whenNotEmpty method will execute the given callback when the collection is not empty: For the inverse of whenNotEmpty, see the whenEmpty method. where() The where method filters the collection by a given key / value pair: 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. whereStrict() This method has the same signature as the where method; however, all values are compared using "strict" comparisons. whereBetween() The whereBetween method filters the collection within a given range: whereIn() The whereIn method filters the collection by a given key / value contained within the given array: 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. whereInStrict() This method has the same signature as the whereIn method; however, all values are compared using "strict" comparisons. whereInstanceOf() The whereInstanceOf method filters the collection by a given class type whereNotBetween() The whereNotBetween method filters the collection within a given range: whereNotIn() The whereNotIn method filters the collection by a given key / value not contained within the given array: 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. whereNotInStrict() This method has the same signature as the whereNotIn method; however, all values are compared using "strict" comparisons. wrap() The static wrap method wraps the given value in a collection when applicable: zip() The zip method merges together the values of the given array with the values of the original collection at the corresponding index: