From 6823f659ab97ee3144a632d440569cb0ccd85a45 Mon Sep 17 00:00:00 2001 From: Jess Archer Date: Tue, 20 Oct 2020 22:24:20 +1000 Subject: [PATCH] [8.x] Improve linkability of docs by adding named anchors to h4 tags (#6506) * Add anchors to h4 tags A selection of h4 tags already had anchor tags so this is really just filling in the gaps (of which there is many!) This makes it much easier to share a specific subsection of the docs in blog posts, PRs, chat, etc. * Fix existing duplicate anchor * Add missing anchors for h3 tags --- artisan.md | 13 +++++++++++++ authentication.md | 18 ++++++++++++++++++ authorization.md | 8 ++++++++ billing.md | 20 ++++++++++++++++++++ blade.md | 19 +++++++++++++++++++ broadcasting.md | 15 +++++++++++++++ cache.md | 11 +++++++++++ cashier-paddle.md | 13 +++++++++++++ configuration.md | 6 ++++++ container.md | 4 ++++ controllers.md | 7 +++++++ csrf.md | 1 + database-testing.md | 8 ++++++++ database.md | 11 +++++++++++ deployment.md | 1 + dusk.md | 26 ++++++++++++++++++++++++++ eloquent-mutators.md | 6 ++++++ eloquent-relationships.md | 30 ++++++++++++++++++++++++++++++ eloquent-resources.md | 11 +++++++++++ eloquent-serialization.md | 5 +++++ eloquent.md | 30 ++++++++++++++++++++++++++++++ encryption.md | 2 ++ envoy.md | 2 ++ errors.md | 3 +++ events.md | 4 ++++ filesystem.md | 17 +++++++++++++++++ hashing.md | 4 ++++ helpers.md | 7 ++++++- homestead.md | 18 ++++++++++++++++++ horizon.md | 7 +++++++ http-client.md | 9 +++++++++ http-tests.md | 3 +++ installation.md | 10 ++++++++++ lifecycle.md | 4 ++++ localization.md | 1 + logging.md | 8 ++++++++ mail.md | 25 +++++++++++++++++++++++++ middleware.md | 1 + migrations.md | 14 ++++++++++++++ mix.md | 7 +++++++ mocking.md | 1 + notifications.md | 15 +++++++++++++++ packages.md | 6 ++++++ pagination.md | 4 ++++ passport.md | 30 ++++++++++++++++++++++++++++++ passwords.md | 5 +++++ providers.md | 2 ++ queries.md | 26 ++++++++++++++++++++++++++ queues.md | 29 +++++++++++++++++++++++++++++ redirects.md | 1 + redis.md | 5 +++++ releases.md | 15 +++++++++++++++ requests.md | 24 ++++++++++++++++++++++++ responses.md | 5 +++++ routing.md | 11 +++++++++++ sanctum.md | 5 +++++ scheduling.md | 7 +++++++ scout.md | 4 ++++ session.md | 7 +++++++ socialite.md | 2 ++ telescope.md | 1 + upgrade.md | 25 +++++++++++++++++++++++++ urls.md | 2 ++ valet.md | 9 +++++++++ validation.md | 21 +++++++++++++++++++++ views.md | 4 ++++ 66 files changed, 674 insertions(+), 1 deletion(-) diff --git a/artisan.md b/artisan.md index d284b552df7..14fe0f4d9d9 100644 --- a/artisan.md +++ b/artisan.md @@ -37,6 +37,7 @@ Every command also includes a "help" screen which displays and describes the com Laravel Tinker is a powerful REPL for the Laravel framework, powered by the [PsySH](https://github.com/bobthecow/psysh) package. + #### Installation All Laravel applications include Tinker by default. However, you may install it manually if needed using Composer: @@ -45,6 +46,7 @@ All Laravel applications include Tinker by default. However, you may install it > {tip} Looking for a graphical UI for interacting with your Laravel application? Check out [Tinkerwell](https://tinkerwell.app)! + #### Usage 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: @@ -57,6 +59,7 @@ You can publish Tinker's configuration file using the `vendor:publish` command: > {note} The `dispatch` helper function and `dispatch` method on the `Dispatchable` class depends on garbage collection to place the job on the queue. Therefore, when using tinker, you should use `Bus::dispatch` or `Queue::push` to dispatch jobs. + #### 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: @@ -65,6 +68,7 @@ Tinker utilizes a white-list to determine which Artisan commands are allowed to // App\Console\Commands\ExampleCommand::class, ], + #### Classes That Should Not Be Aliased 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: @@ -163,6 +167,7 @@ Even though this file does not define HTTP routes, it defines console based entr 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](/docs/{{version}}/container): @@ -174,6 +179,7 @@ In addition to receiving your command's arguments and options, command Closures $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: @@ -334,6 +340,7 @@ The `secret` method is similar to `ask`, but the user's input will not be visibl $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`. @@ -342,6 +349,7 @@ If you need to ask the user for a simple confirmation, you may use the `confirm` // } + #### 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: @@ -354,6 +362,7 @@ Alternatively, you may pass a Closure as the second argument to the `anticipate` // Return auto-completion options... }); + #### Multiple Choice Questions If you need to give the user a predefined set of choices, you may use the `choice` method. You may set the array index of the default value to be returned if no option is chosen: @@ -400,6 +409,7 @@ You may use the `newLine` method to display a blank line: // Write three blank lines... $this->newLine(3); + #### 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: @@ -410,6 +420,7 @@ The `table` method makes it easy to correctly format multiple rows / columns of $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: @@ -487,6 +498,7 @@ You may also specify the connection or queue the Artisan command should be dispa '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: @@ -497,6 +509,7 @@ If your command defines an option that accepts an array, you may pass an array o ]); }); + #### 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`: diff --git a/authentication.md b/authentication.md index 9d2692ae798..512effa5fe5 100644 --- a/authentication.md +++ b/authentication.md @@ -40,6 +40,7 @@ Providers define how users are retrieved from your persistent storage. Laravel s Don't worry if this all sounds confusing now! Many applications will never need to modify the default authentication configuration. + #### Getting Started Fast Want to get started fast? Install [Laravel Jetstream](https://jetstream.laravel.com) in a fresh Laravel application. After migrating your database, navigate your browser to `/register` or any other URL that is assigned to your application. Jetstream will take care of scaffolding your entire authentication system! @@ -62,6 +63,7 @@ First, consider how authentication works. When using a web browser, a user will When a remote service needs to authenticate to access an API, cookies are not typically used because there is no web browser. Instead, the remote service sends an API token to the API on each request. The application may validate the incoming token against a table of valid API tokens and "authenticate" the request as being performed by the user associated with that API token. + #### Laravel's Built-in Browser Authentication Services Laravel includes built-in authentication and session services which are typically accessed via the `Auth` and `Session` facades. These features provide cookie based authentication for requests that are initiated from web browsers. They provide methods that allow you to verify a user's credentials and authenticate the user. In addition, these services will automatically store the proper data in the user's session and issue the proper session cookie. A discussion of how to use these services is contained within this documentation. @@ -72,6 +74,7 @@ As discussed in this documentation, you can interact with these authentication s Laravel Fortify is a headless authentication backend for Laravel that implements many of the features found in this documentation, including cookie-based authentication as well as other features such as two-factor authentication and email verification. Laravel Jetstream is a UI that consumes and exposes Fortify's authentication services with a beautiful, modern UI powered by [Tailwind CSS](https://tailwindcss.com), [Laravel Livewire](https://laravel-livewire.com), and / or [Inertia.js](https://inertiajs.com). Laravel Jetstream, in addition to offering browser-based cookie authentication, includes built-in integration with Laravel Sanctum to offer API token authentication. Laravel's API authentication offerings are discussed below. + #### Laravel's API Authentication Services Laravel provides two optional packages to assist you in managing API tokens and authenticating requests made with API tokens: [Passport](/docs/{{version}}/passport) and [Sanctum](/docs/{{version}}/sanctum). Please note that these libraries and Laravel's built-in cookie based authentication libraries are not mutually exclusive. These libraries primarily focus on API token authentication while the built-in authentication services focus on cookie based browser authentication. Many applications will use both Laravel's built-in cookie based authentication services and one of Laravel's API authentication packages. @@ -88,6 +91,7 @@ Laravel Sanctum is a hybrid web / API authentication package that can manage you Laravel Sanctum is the API package we have chosen to include with the [Laravel Jetstream](https://jetstream.laravel.com) authentication scaffolding because we believe it is the best fit for the majority of web application's authentication needs. + #### Summary & Choosing Your Stack In summary, if your application will be accessed using a browser, your application will use Laravel's built-in authentication services. @@ -118,6 +122,7 @@ Laravel's `laravel/jetstream` package provides a quick way to scaffold all of th 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 `/dashboard` route will also be generated to handle post-login requests to your application's dashboard. + #### Creating Applications Including Authentication If you are starting a brand new application and would like to include the authentication scaffolding, you may use the `--jet` directive when creating your application via the Laravel Installer. This command will create a new application with all of the authentication scaffolding compiled and installed: @@ -138,6 +143,7 @@ Jetstream will also create a `resources/views/layouts` directory containing a ba Now that your application has been scaffolded for authentication, you are ready to register and authenticate! You may simply access your application in a browser since Jetstream's authentication controllers already contain the logic to authenticate existing users and store new users in the database. + #### Path Customization When a user is successfully authenticated, they will typically be redirected to the `/home` URI. You can customize the post-authentication redirect path using the `HOME` constant defined in your `RouteServiceProvider`: @@ -181,6 +187,7 @@ Alternatively, once a user is authenticated, you may access the authenticated us } } + #### Determining If The Current User Is Authenticated To determine if the user is already logged into your application, you may use the `check` method on the `Auth` facade, which will return `true` if the user is authenticated: @@ -202,6 +209,7 @@ To determine if the user is already logged into your application, you may use th // Only authenticated users may enter... })->middleware('auth'); + #### Redirecting Unauthenticated Users When the `auth` middleware detects an unauthorized user, it will redirect the user to the `login` [named route](/docs/{{version}}/routing#named-routes). You may modify this behavior by updating the `redirectTo` function in your `app/Http/Middleware/Authenticate.php` file: @@ -217,6 +225,7 @@ When the `auth` middleware detects an unauthorized user, it will redirect the us 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: @@ -272,6 +281,7 @@ The `attempt` method will return `true` if authentication was successful. Otherw 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 the user is marked as "active": @@ -282,6 +292,7 @@ If you wish, you may also add extra conditions to the authentication query in ad > {note} In these examples, `email` is not a required option, it is merely used as an example. You should use whatever column name corresponds to a "username" in your database. + #### Accessing Specific Guard Instances You may specify which guard instance you would like to utilize using the `guard` method on the `Auth` facade. This allows you to manage authentication for separate parts of your application using entirely separate authenticatable models or user tables. @@ -292,6 +303,7 @@ The guard name passed to the `guard` method should correspond to one of the guar // } + #### Logging Out To log users out of your application, you may use the `logout` method on the `Auth` facade. This will clear the authentication information in the user's session: @@ -316,6 +328,7 @@ If you are "remembering" users, you may use the `viaRemember` method to determin ### 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](/docs/{{version}}/contracts). The `App\Models\User` model included with Laravel already implements this interface. This method of authentication is useful when you already have a valid user instance, such as directly after a user registers with your application: @@ -329,6 +342,7 @@ 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: @@ -338,6 +352,7 @@ To log a user into the application by their ID, you may use the `loginUsingId` m // 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: @@ -357,6 +372,7 @@ You may use the `once` method to log a user into the application for a single re 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: @@ -444,6 +460,7 @@ After confirming their password, a user will not be asked to confirm their passw ### Routing + #### The Password Confirmation Form First, we will define the route that is needed to display a view requesting that the user confirm their password: @@ -454,6 +471,7 @@ First, we will define the route that is needed to display a view requesting that As you might expect, the view that is returned by this route should have a form containing a `password` field. In addition, feel free to include text within the view that explains that the user is entering a protected area of the application and must confirm their password. + #### Confirming The Password Next, we will define a route that will handle the form request from the "confirm password" view. This route will be responsible for validating the password and redirecting the user to their intended destination: diff --git a/authorization.md b/authorization.md index a56e4b84798..c326a7cc84e 100644 --- a/authorization.md +++ b/authorization.md @@ -110,6 +110,7 @@ You may authorize multiple actions at a time with the `any` or `none` methods: // The user cannot update or delete the post } + #### Authorizing Or Throwing Exceptions If you would like to attempt to authorize an action and automatically throw an `Illuminate\Auth\Access\AuthorizationException` if the user is not allowed to perform the given action, you may use the `Gate::authorize` method. Instances of `AuthorizationException` are automatically converted to `403` HTTP response: @@ -118,6 +119,7 @@ If you would like to attempt to authorize an action and automatically throw an ` // The action is authorized... + #### Supplying Additional Context The gate methods for authorizing abilities (`allows`, `denies`, `check`, `any`, `none`, `authorize`, `can`, `cannot`) and the authorization [Blade directives](#via-blade-templates) (`@can`, `@cannot`, `@canany`) can receive an array as the second argument. These array elements are passed as parameters to gate, and can be used for additional context when making authorization decisions: @@ -239,6 +241,7 @@ Once the policy exists, it needs to be registered. The `AuthServiceProvider` inc } } + #### Policy Auto-Discovery Instead of manually registering model policies, Laravel can auto-discover policies as long as the model and policy follow standard Laravel naming conventions. Specifically, the policies must be in a `Policies` directory at or above the directory that contains your models. So, for example, the models may be placed in the `app/Models` directory while the policies may be placed in the `app/Policies` directory. In this situation, Laravel will check for policies in `app/Models/Policies` then `app/Policies`. In addition, the policy name must match the model name and have a `Policy` suffix. So, a `User` model would correspond to a `UserPolicy` class. @@ -401,6 +404,7 @@ The `User` model that is included with your Laravel application includes two hel If a [policy is registered](#registering-policies) 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: @@ -424,6 +428,7 @@ Laravel includes a middleware that can authorize actions before the incoming req 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](/docs/{{version}}/routing#implicit-binding), a `Post` model will be passed to the policy method. If the user is not authorized to perform the given action, an 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: @@ -463,6 +468,7 @@ In addition to helpful methods provided to the `User` model, Laravel provides a } } + #### Actions That Don't Require Models As previously discussed, some actions like `create` may not require a model instance. In these situations, you should pass a class name to the `authorize` method. The class name will be used to determine which policy to use when authorizing the action: @@ -481,6 +487,7 @@ As previously discussed, some actions like `create` may not require a model inst // The current user can create blog posts... } + #### Authorizing Resource Controllers If you are utilizing [resource controllers](/docs/{{version}}/controllers#resource-controllers), you may make use of the `authorizeResource` method in the controller's constructor. This method will attach the appropriate `can` middleware definitions to the resource controller's methods. @@ -552,6 +559,7 @@ You may also determine if a user has any authorization ability from a given list // The current user can create a post @endcanany + #### Actions That Don't Require Models Like most of the other authorization methods, you may pass a class name to the `@can` and `@cannot` directives if the action does not require a model instance: diff --git a/billing.md b/billing.md index be6e042b400..7eff92dc2ce 100644 --- a/billing.md +++ b/billing.md @@ -73,6 +73,7 @@ First, require the Cashier package for Stripe with Composer: > {note} To ensure Cashier properly handles all Stripe events, remember to [set up Cashier's webhook handling](#handling-stripe-webhooks). + #### Database Migrations The Cashier service provider registers its own database migration directory, so remember to migrate your database after installing the package. The Cashier migrations will add several columns to your `users` table as well as create a new `subscriptions` table to hold all of your customer's subscriptions: @@ -213,6 +214,7 @@ If you would like to only generate the URL to the billing portal, you may use th In order to create subscriptions or perform "one off" charges with Stripe, you will need to store a payment method and retrieve its identifier from Stripe. The approach used to accomplish differs based on whether you plan to use the payment method for subscriptions or single charges, so we will examine both below. + #### Payment Methods For Subscriptions When storing credit cards to a customer for future use, the Stripe Setup Intents API must be used to securely gather the customer's payment method details. A "Setup Intent" indicates to Stripe the intention to charge a customer's payment method. Cashier's `Billable` trait includes the `createSetupIntent` to easily create a new Setup Intent. You should call this method from the route or controller that will render the form which gathers your customer's payment method details: @@ -272,6 +274,7 @@ After the card has been verified by Stripe, you may pass the resulting `setupInt > {tip} If you would like more information about Setup Intents and gathering customer payment details please [review this overview provided by Stripe](https://stripe.com/docs/payments/save-and-reuse#php). + #### Payment Methods For Single Charges Of course, when making a single charge against a customer's payment method we'll only need to use a payment method identifier a single time. Due to Stripe limitations, you may not use the stored default payment method of a customer for single charges. You must allow the customer to enter their payment method details using the Stripe.js library. For example, consider the following form: @@ -404,6 +407,7 @@ The `create` method, which accepts [a Stripe payment method identifier](#storing > {note} Passing a payment method identifier directly to the `create()` subscription method will also automatically add it to the user's stored payment methods. + #### Quantities If you would like to set a specific quantity for the plan when creating the subscription, you may use the `quantity` method: @@ -412,6 +416,7 @@ If you would like to set a specific quantity for the plan when creating the subs ->quantity(5) ->create($paymentMethod); + #### Additional Details If you would like to specify additional customer or subscription details, you may do so by passing them as the second and third arguments to the `create` method: @@ -424,6 +429,7 @@ If you would like to specify additional customer or subscription details, you ma To learn more about the additional fields supported by Stripe, check out Stripe's documentation on [customer creation](https://stripe.com/docs/api#create_customer) and [subscription creation](https://stripe.com/docs/api/subscriptions/create). + #### Coupons If you would like to apply a coupon when creating the subscription, you may use the `withCoupon` method: @@ -432,6 +438,7 @@ If you would like to apply a coupon when creating the subscription, you may use ->withCoupon('code') ->create($paymentMethod); + #### Adding Subscriptions If you would like to add a subscription to a customer who already has a default payment method set you can use the `add` method when using the `newSubscription` method: @@ -487,6 +494,7 @@ The `recurring` method may be used to determine if the user is currently subscri > {note} If a user has two subscriptions with the same name, the most recent subscription will always be returned by the `subscription` method. For example, a user might have two subscription records named `default`; however, one of the subscriptions may be an old, expired subscription, while the other is the current, active subscription. The most recent subscription will always be returned while older subscriptions are kept in the database for historical review. + #### Cancelled Subscription Status To determine if the user was once an active subscriber, but has cancelled their subscription, you may use the `cancelled` method: @@ -507,6 +515,7 @@ To determine if the user has cancelled their subscription and is no longer withi // } + #### Subscription Scopes Most subscription states are also available as query scopes so that you may easily query your database for subscriptions that are in a given state: @@ -591,6 +600,7 @@ If you would like to swap plans and immediately invoice the user instead of wait $user->subscription('default')->swapAndInvoice('provider-price-id'); + #### Prorations By default, Stripe prorates charges when swapping between plans. The `noProrate` method may be used to update the subscription's without prorating the charges: @@ -680,6 +690,7 @@ You may remove plans from subscriptions using the `removePlan` method: > {note} You may not remove the last plan on a subscription. Instead, you should simply cancel the subscription. + ### Swapping You may also change the plans attached to a multiplan subscription. For example, imagine you're on a `basic-plan` subscription with a `chat-plan` add-on and you want to upgrade to the `pro-plan` plan: @@ -707,12 +718,14 @@ If you want to swap a single plan on a subscription, you may do so using the `sw ->findItemOrFail('basic-plan') ->swap('pro-plan'); + #### Proration By default, Stripe will prorate charges when adding or removing plans from a subscription. If you would like to make a plan adjustment without proration, you should chain the `noProrate` method onto your plan operation: $user->subscription('default')->noProrate()->removePlan('chat-plan'); + #### Quantities If you would like to update quantities on individual subscription plans, you may do so using the [existing quantity methods](#subscription-quantity) and passing the name of the plan as an additional argument to the method: @@ -727,6 +740,7 @@ If you would like to update quantities on individual subscription plans, you may > {note} When you have multiple plans set on a subscription the `stripe_plan` and `quantity` attributes on the `Subscription` model will be `null`. To access the individual plans, you should use the `items` relationship available on the `Subscription` model. + #### Subscription Items When a subscription has multiple plans, it will have multiple subscription "items" stored in your database's `subscription_items` table. You may access these via the `items` relationship on the subscription: @@ -766,6 +780,7 @@ The `taxRates` method enables you to apply a tax rate on a model-by-model basis, > {note} The `taxRates` method only applies to subscription charges. If you use Cashier to make "one off" charges, you will need to manually specify the tax rate at that time. + #### Syncing Tax Rates When changing the hard-coded Tax Rate IDs returned by the `taxRates` method, the tax settings on any existing subscriptions for the user will remain the same. If you wish to update the tax value for existing subscriptions with the returned `taxTaxRates` values, you should call the `syncTaxRates` method on the user's subscription instance: @@ -774,6 +789,7 @@ When changing the hard-coded Tax Rate IDs returned by the `taxRates` method, the This will also sync any subscription item tax rates so make sure you also properly change the `planTaxRates` method. + #### Tax Exemption Cashier also offers methods to determine if the customer is tax exempt by calling the Stripe API. The `isNotTaxExempt`, `isTaxExempt`, and `reverseChargeApplies` methods are available on the billable model: @@ -868,6 +884,7 @@ You may determine if the user is within their trial period using either the `onT // } + #### Defining Trial Days In Stripe / Cashier You may choose to define how many trial days your plan's receive in the Stripe dashboard or always pass them explicitly using Cashier. If you choose to define your plan's trial days in Stripe you should be aware that new subscriptions, including new subscriptions for a customer that had a subscription in the past, will always receive a trial period unless you explicitly call the `trialDays(0)` method. @@ -944,6 +961,7 @@ To ensure your application can handle Stripe webhooks, be sure to configure the > {note} Make sure you protect incoming requests with Cashier's included [webhook signature verification](/docs/{{version}}/billing#verifying-webhook-signatures) middleware. + #### Webhooks & CSRF Protection Since Stripe webhooks need to bypass Laravel's [CSRF protection](/docs/{{version}}/csrf), be sure to list the URI as an exception in your `VerifyCsrfToken` middleware or list the route outside of the `web` middleware group: @@ -1077,6 +1095,7 @@ You may use the `findInvoice` method to retrieve a specific invoice: $invoice = $user->findInvoice($invoiceId); + #### Displaying Invoice Information When listing the invoices for the customer, you may use the invoice's helper methods to display the relevant invoice information. For example, you may wish to list every invoice in a table, allowing the user to easily download any of them: @@ -1156,6 +1175,7 @@ If your business is based in Europe you will need to abide by the Strong Custome SCA regulations often require extra verification in order to confirm and process a payment. When this happens, Cashier will throw a `PaymentActionRequired` exception that informs you that this extra verification is needed. More info on how to handle these exceptions be found [here](#handling-failed-payments). + #### Incomplete and Past Due State When a payment needs additional confirmation, the subscription will remain in an `incomplete` or `past_due` state as indicated by its `stripe_status` database column. Cashier will automatically activate the customer's subscription via a webhook as soon as payment confirmation is complete. diff --git a/blade.md b/blade.md index 1345b22cfbf..fd1e5b9f7a2 100644 --- a/blade.md +++ b/blade.md @@ -121,6 +121,7 @@ You are not limited to displaying the contents of the variables passed to the vi 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: @@ -129,6 +130,7 @@ By default, Blade `{{ }}` statements are automatically sent through PHP's `htmls > {note} Be very careful when echoing content that is supplied by users of your application. Always use the escaped, double curly brace syntax to prevent XSS attacks when displaying user supplied data. + #### Rendering JSON Sometimes you may pass an array to your view with the intention of rendering it as JSON in order to initialize a JavaScript variable. For example: @@ -147,6 +149,7 @@ However, instead of manually calling `json_encode`, you may use the `@json` Blad > {note} You should only use the `@json` directive to render existing variables as JSON. The Blade templating is based on regular expressions and attempts to pass a complex expression to the directive may cause unexpected failures. + #### 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`: @@ -190,6 +193,7 @@ The `@` symbol may also be used to escape Blade directives: @json() + #### 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: @@ -234,6 +238,7 @@ In addition to the conditional directives already discussed, the `@isset` and `@ // $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: @@ -256,6 +261,7 @@ If needed, you may specify the [authentication guard](/docs/{{version}}/authenti // The user is not authenticated... @endguest + #### Section Directives You may check if a section has content using the `@hasSection` directive: @@ -276,6 +282,7 @@ You may use the `sectionMissing` directive to determine if a section does not ha @endif + #### Environment Directives You may check if the application is running in the production environment using the `@production` directive: @@ -497,6 +504,7 @@ To create a class based component, you may use the `make:component` Artisan comm The `make:component` command will also create a view template for the component. The view will be placed in the `resources/views/components` directory. + #### Manually Registering Package Components When writing components for your own application, components are automatically discovered within the `app/View/Components` directory and `resources/views/components` directory. @@ -610,6 +618,7 @@ When your component is rendered, you may display the contents of your component' {{ $message }} + #### Casing Component constructor arguments should be specified using `camelCase`, while `kebab-case` should be used when referencing the argument names in your HTML attributes. For example, given the following component constructor: @@ -629,6 +638,7 @@ The `$alertType` argument may be provided like so: + #### Component Methods In addition to public variables being available to your component template, any public methods on the component may also be executed. For example, imagine a component that has a `isSelected` method: @@ -650,6 +660,7 @@ You may execute this method from your component template by invoking the variabl {{ $label }} + #### Using Attributes & Slots Inside The Class Blade components also allow you to access the component name, attributes, and slot inside the class's render method. However, in order to access this data, you should return a Closure from your component's `render` method. The Closure will receive a `$data` array as its only argument: @@ -674,6 +685,7 @@ The `componentName` is equal to the name used in the HTML tag after the `x-` pre The Closure should return a string. If the returned string corresponds to an existing view, that view will be rendered; otherwise, the returned string will be evaluated as an inline Blade view. + #### Additional Dependencies If your component requires dependencies from Laravel's [service container](/docs/{{version}}/container), you may list them before any of the component's data attributes and they will automatically be injected by the container: @@ -710,6 +722,7 @@ All of the attributes that are not part of the component's constructor will auto > {note} Using directives such as `@env` directly on a component is not supported at this time. + #### Default / Merged Attributes Sometimes you may need to specify default values for attributes or merge additional values into some of the component's attributes. To accomplish this, you may use the attribute bag's `merge` method: @@ -728,6 +741,7 @@ The final, rendered HTML of the component will appear like the following: + #### Non-Class Attribute Merging When merging attributes that are not `class` attributes, the values provided to the `merge` method will be considered the "default" values of attribute which can be overwritten by the component's consumer. Unlike `class` attributes, non-class attributes are not appended to each other. For example, a `button` component may look like the following: @@ -754,6 +768,7 @@ If you would like an attribute other than `class` to have its values appended to {{ $slot }} + #### Filtering Attributes You may filter attributes using the `filter` method. This method accepts a Closure which should return `true` if you wish to retain the attribute in the attribute bag: @@ -805,6 +820,7 @@ You may define the content of the named slot using the `x-slot` tag. Any content Whoops! Something went wrong! + #### Scoped Slots If you have used a JavaScript framework such as Vue, you may be familiar with "scoped slots", which allow you to access data or methods from the component within your slot. You may achieve similar behavior in Laravel by defining public methods or properties on your component and accessing the component within your slot via the `$component` variable: @@ -836,6 +852,7 @@ For very small components, it may feel cumbersome to manage both the component c blade; } + #### Generating Inline View Components To create a component that renders an inline view, you may use the `inline` option when executing the `make:component` command: @@ -853,6 +870,7 @@ You may use the `.` character to indicate if a component is nested deeper inside + #### Data Properties / Attributes Since anonymous components do not have any associated class, you may wonder how you may differentiate which data should be passed to the component as variables and which attributes should be placed in the component's [attribute bag](#managing-attributes). @@ -909,6 +927,7 @@ To include the first view that exists from a given array of views, you may use t > {note} You should avoid using the `__DIR__` and `__FILE__` constants in your Blade views, since they will refer to the location of the cached, compiled view. + #### Aliasing Includes If your Blade includes are stored in a subdirectory, 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: diff --git a/broadcasting.md b/broadcasting.md index 8bde8bd2034..a79e70f54ac 100644 --- a/broadcasting.md +++ b/broadcasting.md @@ -42,10 +42,12 @@ To assist you in building these types of applications, Laravel makes it easy to All of your application's event broadcasting configuration is stored in the `config/broadcasting.php` configuration file. Laravel supports several broadcast drivers out of the box: [Pusher Channels](https://pusher.com/channels), [Redis](/docs/{{version}}/redis), and a `log` driver for local development and debugging. Additionally, a `null` driver is included which allows you to totally disable broadcasting. A configuration example is included for each of these drivers in the `config/broadcasting.php` configuration file. + #### Broadcast Service Provider Before broadcasting any events, you will first need to register the `App\Providers\BroadcastServiceProvider`. In fresh Laravel applications, you only need to uncomment this provider in the `providers` array of your `config/app.php` configuration file. This provider will allow you to register the broadcast authorization routes and callbacks. + #### CSRF Token [Laravel Echo](#installing-laravel-echo) will need access to the current session's CSRF token. You should verify that your application's `head` HTML element defines a `meta` tag containing the CSRF token: @@ -55,6 +57,7 @@ Before broadcasting any events, you will first need to register the `App\Provide ### Driver Prerequisites + #### Pusher Channels If you are broadcasting your events over [Pusher Channels](https://pusher.com/channels), you should install the Pusher Channels PHP SDK using the Composer package manager: @@ -83,10 +86,12 @@ Finally, you will need to change your broadcast driver to `pusher` in your `.env BROADCAST_DRIVER=pusher + #### Pusher Compatible Laravel Websockets The [laravel-websockets](https://github.com/beyondcode/laravel-websockets) is a pure PHP, Pusher compatible websocket package for Laravel. This package allows you to leverage the full power of Laravel broadcasting without an external websocket provider or Node. For more information on installing and using this package, please consult its [official documentation](https://beyondco.de/docs/laravel-websockets). + #### Redis If you are using the Redis broadcaster, you should either install the phpredis PHP extension via PECL or install the Predis library via Composer: @@ -101,6 +106,7 @@ The Redis broadcaster will broadcast messages using Redis' pub / sub feature; ho 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: @@ -120,6 +126,7 @@ Next, you will need to instantiate Echo with the `socket.io` connector and a `ho 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](https://github.com/tlaverdure/laravel-echo-server) GitHub repository. + #### Queue Prerequisites Before broadcasting events, you will also need to configure and run a [queue listener](/docs/{{version}}/queues). All event broadcasting is done via queued jobs so that the response time of your application is not seriously affected. @@ -142,6 +149,7 @@ In our application, let's assume we have a page that allows users to view the sh 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: @@ -179,6 +187,7 @@ The `ShouldBroadcast` interface requires our event to define a `broadcastOn` met 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: @@ -191,6 +200,7 @@ The `channel` method accepts two arguments: the name of the channel and a callba All authorization callbacks receive the currently authenticated user as their first argument and any additional wildcard parameters as their subsequent arguments. In this example, we are using the `{orderId}` placeholder to indicate that the "ID" portion of the channel name is a wildcard. + #### Listening For Event Broadcasts Next, all that remains is to listen for the event in our JavaScript application. We can do this using Laravel Echo. First, we'll use the `private` method to subscribe to the private channel. Then, we may use the `listen` method to listen for the `ShippingStatusUpdated` event. By default, all of the event's public properties will be included on the broadcast event: @@ -347,6 +357,7 @@ The `Broadcast::routes` method will automatically place its routes within the `w Broadcast::routes($attributes); + #### Customizing The Authorization Endpoint By default, Echo will use the `/broadcasting/auth` endpoint to authorize channel access. However, you may specify your own authorization endpoint by passing the `authEndpoint` configuration option to your Echo instance: @@ -370,6 +381,7 @@ The `channel` method accepts two arguments: the name of the channel and a callba 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](/docs/{{version}}/routing#route-model-binding). For example, instead of receiving the string or numeric order ID, you may request an actual `Order` model instance: @@ -380,6 +392,7 @@ Just like HTTP routes, channel routes may also take advantage of implicit and ex return $user->id === $order->user_id; }); + #### Authorization Callback Authentication Private and presence broadcast channels authenticate the current user via your application's default authentication guard. If the user is not authenticated, channel authorization is automatically denied and the authorization callback is never executed. However, you may assign multiple, custom guards that should authenticate the incoming request if necessary: @@ -466,6 +479,7 @@ However, remember that we also broadcast the task's creation. If your JavaScript > {note} Your event must use the `Illuminate\Broadcasting\InteractsWithSockets` trait in order to call the `toOthers` method. + #### Configuration When you initialize a Laravel Echo instance, a socket ID is assigned to the connection. If you are using [Vue](https://vuejs.org) and [Axios](https://github.com/mzabriskie/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. @@ -502,6 +516,7 @@ When creating an Echo instance that uses the `pusher` connector, you may also sp 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: diff --git a/cache.md b/cache.md index 4fc8e944e52..39ed902f7cf 100644 --- a/cache.md +++ b/cache.md @@ -31,6 +31,7 @@ The cache configuration file also contains various other options, which are docu ### 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: @@ -43,6 +44,7 @@ When using the `database` cache driver, you will need to setup a table to contai > {tip} You may also use the `php artisan cache:table` Artisan command to generate a migration with the proper schema. + #### Memcached Using the Memcached driver requires the [Memcached PECL package](https://pecl.php.net/package/memcached) to be installed. You may list all of your Memcached servers in the `config/cache.php` configuration file: @@ -65,6 +67,7 @@ You may also set the `host` option to a UNIX socket path. If you do this, the `p ], ], + #### Redis Before using a Redis cache with Laravel, you will need to either install the PhpRedis PHP extension via PECL or install the `predis/predis` package (~1.0) via Composer. @@ -102,6 +105,7 @@ However, you may also use the `Cache` facade, which is what we will use througho } } + #### 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: @@ -125,6 +129,7 @@ You may even pass a `Closure` as the default value. The result of the `Closure` 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`: @@ -133,6 +138,7 @@ The `has` method may be used to determine if an item exists in the cache. This m // } + #### 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: @@ -142,6 +148,7 @@ The `increment` and `decrement` methods may be used to adjust the value of integ 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: @@ -158,6 +165,7 @@ You may use the `rememberForever` method to retrieve an item from the cache or s 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: @@ -179,12 +187,14 @@ Instead of passing the number of seconds as an integer, you may also pass a `Dat Cache::put('key', 'value', now()->addMinutes(10)); + #### Store If Not Present The `add` method will only add the item to the cache if it does not already exist in the cache store. The method will return `true` if the item is actually added to the cache. Otherwise, the method will return `false`: Cache::add('key', 'value', $seconds); + #### Storing Items Forever The `forever` method may be used to store an item in the cache permanently. Since these items will not expire, they must be manually removed from the cache using the `forget` method: @@ -275,6 +285,7 @@ In contrast, this statement would remove only caches tagged with `authors`, so ` ### Driver Prerequisites + #### Database When using the `database` cache driver, you will need to setup a table to contain the cache locks. You'll find an example `Schema` declaration for the table below: diff --git a/cashier-paddle.md b/cashier-paddle.md index fe1c581870a..0fb7b451bf4 100644 --- a/cashier-paddle.md +++ b/cashier-paddle.md @@ -61,6 +61,7 @@ First, require the Cashier package for Paddle with Composer: > {note} To ensure Cashier properly handles all Paddle events, remember to [set up Cashier's webhook handling](#handling-paddle-webhooks). + #### Database Migrations The Cashier service provider registers its own database migration directory, so remember to migrate your database after installing the package. The Cashier migrations will create a new `customers` table. In addition, a new `subscriptions` table will be created to store all of your customer's subscriptions. Finally, a new `receipts` table will be created to store all of your receipt information: @@ -181,6 +182,7 @@ To adjust the height of the inline checkout component, you may pass the `height` + #### Inline Checkout Without Pay Links Alternatively, you may customize the widget with custom options instead of using a pay link: @@ -258,6 +260,7 @@ If you retrieved prices for subscription plans you can display their initial and For more information, [check Paddle's API documentation on prices](https://developer.paddle.com/api-reference/checkout-api/prices/getprices). + #### Customers If a user is already a customer and you would like to display the prices that apply to that customer, you may do so by retrieving the prices directly from the customer instance: @@ -269,6 +272,7 @@ If a user is already a customer and you would like to display the prices that ap Internally, Cashier will use the user's [`paddleCountry` method](#customer-defaults) to retrieve the prices in their currency. So, for example, a user living in the United States will see prices in USD while a user in Belgium will see prices in EUR. If no matching currency can be found the default currency of the product will be used. You can customize all prices of a product or subscription plan in the Paddle control panel. + #### Coupons You may also choose to display prices after a coupon reduction. When calling the `productPrices` method, coupons may be passed as a comma delimited string: @@ -367,6 +371,7 @@ The `create` method will create a pay link which you can use to generate a payme After the user has finished their checkout, a `subscription_created` webhook will be dispatched from Paddle. Cashier will receive this webhook and setup the subscription for your customer. In order to make sure all webhooks are properly received and handled by your application, ensure you have properly [setup webhook handling](#handling-paddle-webhooks). + #### Additional Details If you would like to specify additional customer or subscription details, you may do so by passing them as a key / value array to the `create` method: @@ -379,6 +384,7 @@ If you would like to specify additional customer or subscription details, you ma To learn more about the additional fields supported by Paddle, check out Paddle's documentation on [generating pay links](https://developer.paddle.com/api-reference/product-api/pay-links/createpaylink). + #### Coupons If you would like to apply a coupon when creating the subscription, you may use the `withCoupon` method: @@ -388,6 +394,7 @@ If you would like to apply a coupon when creating the subscription, you may use ->withCoupon('code') ->create(); + #### Metadata You can also pass an array of metadata using the `withMetadata` method: @@ -444,6 +451,7 @@ The `recurring` method may be used to determine if the user is currently subscri // } + #### Cancelled Subscription Status To determine if the user was once an active subscriber, but has cancelled their subscription, you may use the `cancelled` method: @@ -464,6 +472,7 @@ To determine if the user has cancelled their subscription and is no longer withi // } + #### Subscription Scopes Most subscription states are also available as query scopes so that you may easily query your database for subscriptions that are in a given state: @@ -491,6 +500,7 @@ A complete list of available scopes is available below: Subscription::query()->onGracePeriod(); Subscription::query()->notOnGracePeriod(); + #### Past Due Status If a payment fails for a subscription, it will be marked as `past_due`. When your subscription is in this state it will not be active until the customer has updated their payment information. You may determine if a subscription is past due using the `pastDue` method on the subscription instance: @@ -566,6 +576,7 @@ If you would like to swap plans and immediately invoice the user instead of wait $user->subscription('default')->swapAndInvoice($premium = 34567); + #### Prorations By default, Paddle prorates charges when swapping between plans. The `noProrate` method may be used to update the subscription's without prorating the charges: @@ -672,6 +683,7 @@ You may determine if the user is within their trial period using either the `onT // } + #### Defining Trial Days In Paddle / Cashier You may choose to define how many trial days your plan's receive in the Paddle dashboard or always pass them explicitly using Cashier. If you choose to define your plan's trial days in Paddle you should be aware that new subscriptions, including new subscriptions for a customer that had a subscription in the past, will always receive a trial period unless you explicitly call the `trialDays(0)` method. @@ -736,6 +748,7 @@ To ensure your application can handle Paddle webhooks, be sure to [configure the > {note} Make sure you protect incoming requests with Cashier's included [webhook signature verification](/docs/{{version}}/cashier-paddle#verifying-webhook-signatures) middleware. + #### Webhooks & CSRF Protection Since Paddle webhooks need to bypass Laravel's [CSRF protection](/docs/{{version}}/csrf), be sure to list the URI as an exception in your `VerifyCsrfToken` middleware or list the route outside of the `web` middleware group: diff --git a/configuration.md b/configuration.md index 3cc40b91fcd..6c7a2f2c524 100644 --- a/configuration.md +++ b/configuration.md @@ -140,6 +140,7 @@ You may also provide a `retry` option to the `down` command, which will be set a php artisan down --retry=60 + #### Bypassing Maintenance Mode Even while in maintenance mode, you may use the `secret` option to specify a maintenance mode bypass token: @@ -152,6 +153,7 @@ After placing the application in maintenance mode, you may navigate to the appli When accessing this hidden route, you will then be redirected to the `/` route of the application. Once the cookie has been issued to your browser, you will be able to browse the application normally as if it was not in maintenance mode. + #### Pre-Rendering The Maintenance Mode View If you utilize the `php artisan down` command during deployment, your users may still occasionally encounter errors if they access the application while your Composer dependencies or other infrastructure components are updating. This occurs because a significant part of the Laravel framework must boot in order to determine your application is in maintenance mode and render the maintenance mode view using the templating engine. @@ -160,12 +162,14 @@ For this reason, Laravel allows you to pre-render a maintenance mode view that w php artisan down --render="errors::503" + #### Redirecting Maintenance Mode Requests While in maintenance mode, Laravel will display the maintenance mode view for all application URLs the user attempts to access. If you wish, you may instruct Laravel to redirect all requests to a specific URL. This may be accomplished using the `redirect` option. For example, you may wish to redirect all requests to the `/` URI: php artisan down --redirect=/ + #### Disabling Maintenance Mode To disable maintenance mode, use the `up` command: @@ -174,10 +178,12 @@ To disable maintenance mode, use the `up` command: > {tip} You may customize the default maintenance mode template by defining your own template at `resources/views/errors/503.blade.php`. + #### Maintenance Mode & Queues While your application is in maintenance mode, no [queued jobs](/docs/{{version}}/queues) will be handled. The jobs will continue to be handled as normal once the application is out of maintenance mode. + #### Alternatives To Maintenance Mode Since maintenance mode requires your application to have several seconds of downtime, consider alternatives like [Envoyer](https://envoyer.io) to accomplish zero-downtime deployment with Laravel. diff --git a/container.md b/container.md index 3a8a7c6109f..d4ea262fa1a 100644 --- a/container.md +++ b/container.md @@ -78,6 +78,7 @@ Almost all of your service container bindings will be registered within [service > {tip} There is no need to bind classes into the container if they do not depend on any interfaces. The container does not need to be instructed on how to build these objects, since it can automatically resolve these objects using reflection. + #### 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: @@ -88,6 +89,7 @@ Within a service provider, you always have access to the container via the `$thi 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: @@ -96,6 +98,7 @@ The `singleton` method binds a class or interface into the container that should return new \HelpSpot\API($app->make('HttpClient')); }); + #### Binding Instances You may also bind an existing object instance into the container using the `instance` method. The given instance will always be returned on subsequent calls into the container: @@ -206,6 +209,7 @@ For convenience, you may also just provide an array of class names to be resolve TooLongFilter::class, ]); + #### Variadic Tag Dependencies Sometimes a class may have a variadic dependency that is type-hinted as a given class (`Report ...$reports`). Using the `needs` and `giveTagged` methods, you may easily inject all of the container bindings with that tag for the given dependency: diff --git a/controllers.md b/controllers.md index f62e2b875e8..e7fffcd6a38 100644 --- a/controllers.md +++ b/controllers.md @@ -156,6 +156,7 @@ You may register many resource controllers at once by passing an array to the `r 'posts' => PostController::class, ]); + #### Actions Handled By Resource Controller Verb | URI | Action | Route Name @@ -168,6 +169,7 @@ 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: @@ -187,6 +189,7 @@ When declaring a resource route, you may specify a subset of actions the control '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: @@ -215,6 +218,7 @@ This route will register a nested resource that may be accessed with URIs like t /photos/{photo}/comments/{comment} + #### Scoping Nested Resources Laravel's [implicit model binding](/docs/{{version}}/routing#implicit-model-binding-scoping) feature can automatically scope nested bindings such that the resolved child model is confirmed to belong to the parent model. By using the `scoped` method when defining your nested resource, you may enable automatic scoping as well as instruct Laravel which field the child resource should be retrieved by: @@ -227,6 +231,7 @@ This route will register a scoped nested resource that may be accessed with URIs /photos/{photo}/comments/{comment:slug} + #### Shallow Nesting Often, it is not entirely necessary to have both the parent and the child IDs within a URI since the child ID is already a unique identifier. When using unique identifiers such as auto-incrementing primary keys to identify your models in URI segments, you may choose to use "shallow nesting": @@ -326,6 +331,7 @@ If you need to add additional routes to a resource controller beyond the default ## Dependency Injection & Controllers + #### Constructor Injection The Laravel [service container](/docs/{{version}}/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: @@ -357,6 +363,7 @@ The Laravel [service container](/docs/{{version}}/container) is used to resolve You may also type-hint any [Laravel contract](/docs/{{version}}/contracts). 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: diff --git a/csrf.md b/csrf.md index ed962522e4c..93a167bab8b 100644 --- a/csrf.md +++ b/csrf.md @@ -21,6 +21,7 @@ Anytime you define an HTML form in your application, you should include a hidden The `VerifyCsrfToken` [middleware](/docs/{{version}}/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 Axios HTTP library provided in the `resources/js/bootstrap.js` file automatically sends an `X-XSRF-TOKEN` header using the value of the encrypted `XSRF-TOKEN` cookie. If you are not using this library, you will need to manually configure this behavior for your application. diff --git a/database-testing.md b/database-testing.md index 64a300b8141..82253f2acf3 100644 --- a/database-testing.md +++ b/database-testing.md @@ -227,12 +227,14 @@ The `HasFactory` trait's `factory` method will use conventions to determine the return \Database\Factories\Administration\FlightFactory::new(); } + #### Applying States You may also apply any of your [states](#factory-states) to the models. If you would like to apply multiple state transformations to the models, you may simply call state methods directly: $users = User::factory()->count(5)->suspended()->make(); + #### Overriding Attributes If you would like to override some of the default values of your models, you may pass an array of values to the `make` method. Only the specified values will be replaced while the rest of the values remain set to their default values as specified by the factory: @@ -364,6 +366,7 @@ Of course, you may perform state manipulations on the related models. In additio ) ->create(); + #### Using Magic Methods For convenience, you may use the factory's magic relationship methods to define relationships. For example, the following example will use convention to determine that the related models should be created via a `posts` relationship method on the `User` model: @@ -403,6 +406,7 @@ Now that we have explored how to build "has many" relationships using factories, ])) ->create(); + #### Using Magic Methods For convenience, you may use the factory's magic relationship methods to define "belongs to" relationships. For example, the following example will use convention to determine that the three posts should belong to the `user` relationship on the `Post` model: @@ -426,6 +430,7 @@ Like [has many relationships](#has-many-relationships), "many to many" relations ->has(Role::factory()->count(3)) ->create(); + #### Pivot Table Attributes If you need to define attributes that should be set on the pivot / intermediate table linking the models, you may use the `hasAttached` method. This method accepts an array of pivot table attribute names and values as its second argument: @@ -453,6 +458,7 @@ You may provide a Closure based state transformation if your state change requir ) ->create(); + #### Using Magic Methods For convenience, you may use the factory's magic relationship methods to define many to many relationships. For example, the following example will use convention to determine that the related models should be created via a `roles` relationship method on the `User` model: @@ -472,6 +478,7 @@ For convenience, you may use the factory's magic relationship methods to define $post = Post::factory()->hasComments(3)->create(); + #### Morph To Relationships Magic methods may not be used to create `morphTo` relationships. Instead, the `for` method must be used directly and the name of the relationship must be explicitly provided. For example, imagine that the `Comment` model has a `commentable` method that defines a `morphTo` relationship. In this situation, we may create three comments that belong to a single post using the `for` method directly: @@ -480,6 +487,7 @@ Magic methods may not be used to create `morphTo` relationships. Instead, the `f Post::factory(), 'commentable' )->create(); + #### Polymorphic Many To Many Relationships Polymorphic "many to many" relationships may be created just like non-polymorphic "many to many" relationships: diff --git a/database.md b/database.md index 594c68ff069..d692b7e0a83 100644 --- a/database.md +++ b/database.md @@ -27,6 +27,7 @@ The database configuration for your application is located at `config/database.p By default, Laravel's sample [environment configuration](/docs/{{version}}/configuration#environment-configuration) is ready to use with [Laravel Homestead](/docs/{{version}}/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: @@ -38,6 +39,7 @@ To enable foreign key constraints for SQLite connections, you should set the `DB DB_FOREIGN_KEYS=true + #### Configuration Using URLs Typically, database connections are configured using multiple configuration values such as `host`, `database`, `username`, `password`, etc. Each of these configuration values has its own corresponding environment variable. This means that when configuring your database connection information on a production server, you need to manage several environment variables. @@ -85,6 +87,7 @@ Note that three keys have been added to the configuration array: `read`, `write` 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.3` will be used for the "write" connection. The database credentials, prefix, character set, and all other options in the main `mysql` array will be shared across both connections. + #### 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. @@ -105,6 +108,7 @@ You may also access the raw, underlying PDO instance using the `getPdo` method o 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: @@ -139,30 +143,35 @@ The `select` method will always return an `array` of results. Each result within 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: @@ -219,6 +228,7 @@ You may use the `transaction` method on the `DB` facade to run a set of operatio 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: @@ -229,6 +239,7 @@ The `transaction` method accepts an optional second argument which defines the n 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: diff --git a/deployment.md b/deployment.md index e329044fe11..f2f806e5fe2 100644 --- a/deployment.md +++ b/deployment.md @@ -104,6 +104,7 @@ If you aren't quite ready to manage your own server configuration or aren't comf Laravel Forge can create servers on various infrastructure providers such as DigitalOcean, Linode, AWS, and more. In addition, Forge installs and manages all of the tools needed to build robust Laravel applications, such as Nginx, MySQL, Redis, Memcached, Beanstalk, and more. + #### Laravel Vapor If you would like a totally serverless, auto-scaling deployment platform tuned for Laravel, check out [Laravel Vapor](https://vapor.laravel.com). Laravel Vapor is a serverless deployment platform for Laravel, powered by AWS. Launch your Laravel infrastructure on Vapor and fall in love with the scalable simplicity of serverless. Laravel Vapor is fine-tuned by Laravel's creators to work seamlessly with the framework so you can keep writing your Laravel applications exactly like you're used to. diff --git a/dusk.md b/dusk.md index c758a8e2cc9..6268298609c 100644 --- a/dusk.md +++ b/dusk.md @@ -150,6 +150,7 @@ The `dusk` command accepts any argument that is normally accepted by the PHPUnit php artisan dusk --group=foo + #### Manually Starting ChromeDriver By default, Dusk will automatically attempt to start ChromeDriver. If this does not work for your particular system, you may manually start ChromeDriver before running the `dusk` command. If you choose to start ChromeDriver manually, you should comment out the following line of your `tests/DuskTestCase.php` file: @@ -227,6 +228,7 @@ To get started, let's write a test that verifies we can log into our application As you can see in the example above, the `browse` method accepts a callback. A browser instance will automatically be passed to this callback by Dusk and is the main object used to interact with and make assertions against your application. + #### Creating Multiple Browsers Sometimes you may need multiple browsers in order to properly carry out a test. For example, multiple browsers may be needed to test a chat screen that interacts with websockets. To create multiple browsers, "ask" for more than one browser in the signature of the callback given to the `browse` method: @@ -246,6 +248,7 @@ Sometimes you may need multiple browsers in order to properly carry out a test. ->assertSee('Jeffrey Way'); }); + #### Resizing Browser Windows You may use the `resize` method to adjust the size of the browser window: @@ -422,6 +425,7 @@ You may use the `seeLink` method to determine if a link that has the given displ ### Text, Values, & Attributes + #### Retrieving & Setting Values Dusk provides several methods for interacting with the current display text, value, and attributes of elements on the page. For example, to get the "value" of an element that matches a given selector, use the `value` method: @@ -437,12 +441,14 @@ You may use the `inputValue` method to get the "value" of an input element that // Retrieve the value of an input element... $inputValue = $browser->inputValue('field'); + #### Retrieving Text The `text` method may be used to retrieve the display text of an element that matches the given selector: $text = $browser->text('selector'); + #### Retrieving Attributes Finally, the `attribute` method may be used to retrieve an attribute of an element matching the given selector: @@ -452,6 +458,7 @@ Finally, the `attribute` method may be used to retrieve an attribute of an eleme ### Using Forms + #### Typing Values Dusk provides a variety of methods for interacting with forms and input elements. First, let's take a look at an example of typing text into an input field: @@ -480,6 +487,7 @@ You may use the `appendSlowly` method to append text slowly: $browser->type('tags', 'foo') ->appendSlowly('tags', ', bar, baz'); + #### Dropdowns To select a value in a dropdown selection box, you may use the `select` method. Like the `type` method, the `select` method does not require a full CSS selector. When passing a value to the `select` method, you should pass the underlying option value instead of the display text: @@ -490,6 +498,7 @@ You may select a random option by omitting the second parameter: $browser->select('size'); + #### Checkboxes To "check" a checkbox field, you may use the `check` method. Like many other input related methods, a full CSS selector is not required. If an exact selector match can't be found, Dusk will search for a checkbox with a matching `name` attribute: @@ -498,6 +507,7 @@ To "check" a checkbox field, you may use the `check` method. Like many other inp $browser->uncheck('terms'); + #### Radio Buttons To "select" a radio button option, you may use the `radio` method. Like many other input related methods, a full CSS selector is not required. If an exact selector match can't be found, Dusk will search for a radio with matching `name` and `value` attributes: @@ -529,6 +539,7 @@ You may even send a "hot key" to the primary CSS selector that contains your app ### Using The Mouse + #### Clicking On Elements The `click` method may be used to "click" on an element matching the given selector: @@ -559,12 +570,14 @@ The `clickAndHold` method may be used to simulate a mouse button being clicked a ->pause(1000) ->releaseMouse(); + #### Mouseover The `mouseover` method may be used when you need to move the mouse over an element matching the given selector: $browser->mouseover('.selector'); + #### Drag & Drop The `drag` method may be used to drag an element matching the given selector to another element: @@ -629,12 +642,14 @@ You may occasionally need to execute assertions outside of the current scope. Yo When testing applications that use JavaScript extensively, it often becomes necessary to "wait" for certain elements or data to be available before proceeding with a test. Dusk makes this a cinch. Using a variety of methods, you may wait for elements to be visible on the page or even wait until a given JavaScript expression evaluates to `true`. + #### Waiting If you need to pause the test for a given number of milliseconds, use the `pause` method: $browser->pause(1000); + #### Waiting For Selectors The `waitFor` method may be used to pause the execution of the test until the element matching the given CSS selector is displayed on the page. By default, this will pause the test for a maximum of five seconds before throwing an exception. If necessary, you may pass a custom timeout threshold as the second argument to the method: @@ -661,6 +676,7 @@ You may also wait until the given selector is missing from the page: // Wait a maximum of one second until the selector is missing... $browser->waitUntilMissing('.selector', 1); + #### Scoping Selectors When Available Occasionally, you may wish to wait for a given selector and then interact with the element matching the selector. For example, you may wish to wait until a modal window is available and then press the "OK" button within the modal. The `whenAvailable` method may be used in this case. All element operations performed within the given callback will be scoped to the original selector: @@ -670,6 +686,7 @@ Occasionally, you may wish to wait for a given selector and then interact with t ->press('OK'); }); + #### Waiting For Text The `waitForText` method may be used to wait until the given text is displayed on the page: @@ -688,6 +705,7 @@ You may use the `waitUntilMissingText` method to wait until the displayed text h // Wait a maximum of one second for the text to be removed... $browser->waitUntilMissingText('Hello World', 1); + #### Waiting For Links The `waitForLink` method may be used to wait until the given link text is displayed on the page: @@ -698,6 +716,7 @@ The `waitForLink` method may be used to wait until the given link text is displa // Wait a maximum of one second for the link... $browser->waitForLink('Create', 1); + #### Waiting On The Page Location When making a path assertion such as `$browser->assertPathIs('/home')`, the assertion can fail if `window.location.pathname` is being updated asynchronously. You may use the `waitForLocation` method to wait for the location to be a given value: @@ -708,6 +727,7 @@ You may also wait for a named route's location: $browser->waitForRoute($routeName, $parameters); + #### Waiting for Page Reloads If you need to make assertions after a page has been reloaded, use the `waitForReload` method: @@ -716,6 +736,7 @@ If you need to make assertions after a page has been reloaded, use the `waitForR ->waitForReload() ->assertSee('something'); + #### Waiting On JavaScript Expressions Sometimes you may wish to pause the execution of a test until a given JavaScript expression evaluates to `true`. You may easily accomplish this using the `waitUntil` method. When passing an expression to this method, you do not need to include the `return` keyword or an ending semi-colon: @@ -728,6 +749,7 @@ Sometimes you may wish to pause the execution of a test until a given JavaScript // Wait a maximum of one second for the expression to be true... $browser->waitUntil('App.data.servers.length > 0', 1); + #### Waiting On Vue Expressions The following methods may be used to wait until a given Vue component attribute has a given value: @@ -738,6 +760,7 @@ The following methods may be used to wait until a given Vue component attribute // Wait until the component attribute doesn't contain the given value... $browser->waitUntilVueIsNot('user.name', null, '@user'); + #### Waiting With A Callback Many of the "wait" methods in Dusk rely on the underlying `waitUsing` method. You may use this method directly to wait for a given callback to return `true`. The `waitUsing` method accepts the maximum number of seconds to wait, the interval at which the Closure should be evaluated, the Closure, and an optional failure message: @@ -1369,6 +1392,7 @@ To generate a page object, use the `dusk:page` Artisan command. All page objects By default, pages have three methods: `url`, `assert`, and `elements`. We will discuss the `url` and `assert` methods now. The `elements` method will be [discussed in more detail below](#shorthand-selectors). + #### The `url` Method The `url` method should return the path of the URL that represents the page. Dusk will use this URL when navigating to the page in the browser: @@ -1383,6 +1407,7 @@ The `url` method should return the path of the URL that represents the page. Dus return '/login'; } + #### The `assert` Method The `assert` method may make any assertions necessary to verify that the browser is actually on the given page. Completing this method is not necessary; however, you are free to make these assertions if you wish. These assertions will be run automatically when navigating to the page: @@ -1450,6 +1475,7 @@ Now, you may use this shorthand selector anywhere you would use a full CSS selec $browser->type('@email', 'taylor@laravel.com'); + #### Global Shorthand Selectors After installing Dusk, a base `Page` class will be placed in your `tests/Browser/Pages` directory. This class contains a `siteElements` method which may be used to define global shorthand selectors that should be available on every page throughout your application: diff --git a/eloquent-mutators.md b/eloquent-mutators.md index 17e6588c96c..5bca0546490 100644 --- a/eloquent-mutators.md +++ b/eloquent-mutators.md @@ -138,6 +138,7 @@ As noted above, when retrieving attributes that are listed in your `$dates` prop return $user->deleted_at->getTimestamp(); + #### Date Formats By default, timestamps are formatted as `'Y-m-d H:i:s'`. If you need to customize the timestamp format, set the `$dateFormat` property on your model. This property determines how date attributes are stored in the database: @@ -258,6 +259,7 @@ Once you have defined a custom cast type, you may attach it to a model attribute ]; } + #### Value Object Casting You are not limited to casting values to primitive types. You may also cast values to objects. Defining custom casts that cast values to objects is very similar to casting to primitive types; however, the `set` method should return an array of key / value pairs that will be used to set raw, storable values on the model. @@ -323,6 +325,7 @@ When casting to value objects, any changes made to the value object will automat > {tip} If you plan to serialize your Eloquent models containing value objects to JSON or arrays, you should implement the `Illuminate\Contracts\Support\Arrayable` and `JsonSerializable` interfaces on the value object. + #### Array / JSON Serialization When an Eloquent model is converted to an array or JSON using the `toArray` method, your custom cast value objects will typically be serialized as well as long as they implement the `Illuminate\Contracts\Support\Arrayable` and `JsonSerializable` interfaces. However, when using value objects provided by third-party libraries, you may not have the ability to add these interfaces to the object. @@ -343,6 +346,7 @@ Therefore, you may specify that your custom cast class will be responsible for s return (string) $value; } + #### Inbound Casting Occasionally, you may need to write a custom cast that only transforms values that are being set on the model and does not perform any operations when attributes are being retrieved from the model. A classic example of an inbound only cast is a "hashing" cast. Inbound only custom casts should implement the `CastsInboundAttributes` interface, which only requires a `set` method to be defined. @@ -390,6 +394,7 @@ Occasionally, you may need to write a custom cast that only transforms values th } } + #### Cast Parameters When attaching a custom cast to a model, cast parameters may be specified by separating them from the class name using a `:` character and comma-delimiting multiple parameters. The parameters will be passed to the constructor of the cast class: @@ -403,6 +408,7 @@ When attaching a custom cast to a model, cast parameters may be specified by sep 'secret' => Hash::class.':sha256', ]; + #### Castables Instead of attaching the custom cast to your model, you may alternatively attach a class that implements the `Illuminate\Contracts\Database\Eloquent\Castable` interface: diff --git a/eloquent-relationships.md b/eloquent-relationships.md index c24bd0030d5..989f02ffb00 100644 --- a/eloquent-relationships.md +++ b/eloquent-relationships.md @@ -93,6 +93,7 @@ Additionally, Eloquent assumes that the foreign key should have a value matching return $this->hasOne('App\Models\Phone', 'foreign_key', 'local_key'); + #### Defining The Inverse Of The Relationship So, we can access the `Phone` model from our `User`. Now, let's define a relationship on the `Phone` model that will let us access the `User` that owns the phone. We can define the inverse of a `hasOne` relationship using the `belongsTo` method: @@ -229,6 +230,7 @@ If your parent model does not use `id` as its primary key, or you wish to join t Many-to-many relations are slightly more complicated than `hasOne` and `hasMany` relationships. An example of such a relationship is a user with many roles, where the roles are also shared by other users. For example, many users may have the role of "Admin". + #### Table Structure To define this relationship, three database tables are needed: `users`, `roles`, and `role_user`. The `role_user` table is derived from the alphabetical order of the related model names, and contains the `user_id` and `role_id` columns: @@ -245,6 +247,7 @@ To define this relationship, three database tables are needed: `users`, `roles`, user_id - integer role_id - integer + #### Model Structure Many-to-many relationships are defined by writing a method that returns the result of the `belongsToMany` method. For example, let's define the `roles` method on our `User` model: @@ -286,6 +289,7 @@ In addition to customizing the name of the joining table, you may also customize return $this->belongsToMany('App\Models\Role', 'role_user', 'user_id', 'role_id'); + #### Defining The Inverse Of The Relationship To define the inverse of a many-to-many relationship, you place another call to `belongsToMany` on your related model. To continue our user roles example, let's define the `users` method on the `Role` model: @@ -309,6 +313,7 @@ To define the inverse of a many-to-many relationship, you place another call to As you can see, the relationship is defined exactly the same as its `User` counterpart, with the exception of referencing the `App\Models\User` model. Since we're reusing the `belongsToMany` method, all of the usual table and key customization options are available when defining the inverse of many-to-many relationships. + #### Retrieving Intermediate Table Columns As you have already learned, working with many-to-many relations requires the presence of an intermediate table. Eloquent provides some very helpful ways of interacting with this table. For example, let's assume our `User` object has many `Role` objects that it is related to. After accessing this relationship, we may access the intermediate table using the `pivot` attribute on the models: @@ -331,6 +336,7 @@ If you want your pivot table to have automatically maintained `created_at` and ` > {note} When using timestamps on pivot tables, the table is required to have both `created_at` and `updated_at` timestamp columns. + #### Customizing The `pivot` Attribute Name As noted earlier, attributes from the intermediate table may be accessed on models using the `pivot` attribute. However, you are free to customize the name of this attribute to better reflect its purpose within your application. @@ -349,6 +355,7 @@ Once this is done, you may access the intermediate table data using the customiz echo $podcast->subscription->created_at; } + #### Filtering Relationships Via Intermediate Table Columns You can also filter the results returned by `belongsToMany` using the `wherePivot`, `wherePivotIn`, and `wherePivotNotIn` methods when defining the relationship: @@ -420,6 +427,7 @@ You can combine `using` and `withPivot` in order to retrieve columns from the in > **Note:** Pivot models may not use the `SoftDeletes` trait. If you need to soft delete pivot records consider converting your pivot model to an actual Eloquent model. + #### Custom Pivot Models And Incrementing IDs If you have defined a many-to-many relationship that uses a custom pivot model, and that pivot model has an auto-incrementing primary key, you should ensure your custom pivot model class defines an `incrementing` property that is set to `true`. @@ -560,6 +568,7 @@ A polymorphic relationship allows the target model to belong to more than one ty ### One To One (Polymorphic) + #### Table Structure A one-to-one polymorphic relation is similar to a simple one-to-one relation; however, the target model can belong to more than one type of model on a single association. For example, a blog `Post` and a `User` may share a polymorphic relation to an `Image` model. Using a one-to-one polymorphic relation allows you to have a single list of unique images that are used for both blog posts and user accounts. First, let's examine the table structure: @@ -580,6 +589,7 @@ A one-to-one polymorphic relation is similar to a simple one-to-one relation; ho Take note of the `imageable_id` and `imageable_type` columns on the `images` table. The `imageable_id` column will contain the ID value of the post or user, while the `imageable_type` column will contain the class name of the parent model. The `imageable_type` column is used by Eloquent to determine which "type" of parent model to return when accessing the `imageable` relation. + #### Model Structure Next, let's examine the model definitions needed to build this relationship: @@ -623,6 +633,7 @@ Next, let's examine the model definitions needed to build this relationship: } } + #### Retrieving The Relationship Once your database table and models are defined, you may access the relationships via your models. For example, to retrieve the image for a post, we can use the `image` dynamic property: @@ -650,6 +661,7 @@ The `imageable` relation on the `Image` model will return either a `Post` or `Us ### One To Many (Polymorphic) + #### Table Structure A one-to-many polymorphic relation is similar to a simple one-to-many relation; however, the target model can belong to more than one type of model on a single association. For example, imagine users of your application can "comment" on both posts and videos. Using polymorphic relationships, you may use a single `comments` table for both of these scenarios. First, let's examine the table structure required to build this relationship: @@ -670,6 +682,7 @@ A one-to-many polymorphic relation is similar to a simple one-to-many relation; commentable_id - integer commentable_type - string + #### Model Structure Next, let's examine the model definitions needed to build this relationship: @@ -713,6 +726,7 @@ Next, let's examine the model definitions needed to build this relationship: } } + #### Retrieving The Relationship Once your database table and models are defined, you may access the relationships via your models. For example, to access all of the comments for a post, we can use the `comments` dynamic property: @@ -734,6 +748,7 @@ The `commentable` relation on the `Comment` model will return either a `Post` or ### Many To Many (Polymorphic) + #### Table Structure Many-to-many polymorphic relations are slightly more complicated than `morphOne` and `morphMany` relationships. For example, a blog `Post` and `Video` model could share a polymorphic relation to a `Tag` model. Using a many-to-many polymorphic relation allows you to have a single list of unique tags that are shared across blog posts and videos. First, let's examine the table structure: @@ -755,6 +770,7 @@ Many-to-many polymorphic relations are slightly more complicated than `morphOne` taggable_id - integer taggable_type - string + #### Model Structure Next, we're ready to define the relationships on the model. The `Post` and `Video` models will both have a `tags` method that calls the `morphToMany` method on the base Eloquent class: @@ -776,6 +792,7 @@ Next, we're ready to define the relationships on the model. The `Post` and `Vide } } + #### Defining The Inverse Of The Relationship Next, on the `Tag` model, you should define a method for each of its related models. So, for this example, we will define a `posts` method and a `videos` method: @@ -805,6 +822,7 @@ Next, on the `Tag` model, you should define a method for each of its related mod } } + #### Retrieving The Relationship Once your database table and models are defined, you may access the relationships via your models. For example, to access all of the tags for a post, you can use the `tags` dynamic property: @@ -893,6 +911,7 @@ You may query the `posts` relationship and add additional constraints to the rel You are able to use any of the [query builder](/docs/{{version}}/queries) methods on the relationship, so be sure to explore the query builder documentation to learn about all of the methods that are available to you. + #### Chaining `orWhere` Clauses After Relationships As demonstrated in the example above, you are free to add additional constraints to relationships when querying them. However, use caution when chaining `orWhere` clauses onto a relationship, as the `orWhere` clauses will be logically grouped at the same level as the relationship constraint: @@ -1167,18 +1186,21 @@ For this operation, only two queries will be executed: select * from authors where id in (1, 2, 3, 4, 5, ...) + #### Eager Loading Multiple Relationships Sometimes you may need to eager load several different relationships in a single operation. To do so, just pass additional arguments to the `with` method: $books = App\Models\Book::with(['author', 'publisher'])->get(); + #### Nested Eager Loading To eager load nested relationships, you may use "dot" syntax. For example, let's eager load all of the book's authors and all of the author's personal contacts in one Eloquent statement: $books = App\Models\Book::with('author.contacts')->get(); + #### Nested Eager Loading `morphTo` Relationships If you would like to eager load a `morphTo` relationship, as well as nested relationships on the various entities that may be returned by that relationship, you may use the `with` method in combination with the `morphTo` relationship's `morphWith` method. To help illustrate this method, let's consider the following model: @@ -1213,6 +1235,7 @@ Using these model definitions and relationships, we may retrieve `ActivityFeed` ]); }])->get(); + #### Eager Loading Specific Columns You may not always need every column from the relationships you are retrieving. For this reason, Eloquent allows you to specify which columns of the relationship you would like to retrieve: @@ -1221,6 +1244,7 @@ You may not always need every column from the relationships you are retrieving. > {note} When using this feature, you should always include the `id` column and any relevant foreign key columns in the list of columns you wish to retrieve. + #### Eager Loading By Default Sometimes you might want to always load some relationships when retrieving a model. To accomplish this, you may define a `$with` property on the model: @@ -1299,6 +1323,7 @@ To load a relationship only when it has not already been loaded, use the `loadMi ]; } + #### Nested Lazy Eager Loading & `morphTo` If you would like to eager load a `morphTo` relationship, as well as nested relationships on the various entities that may be returned by that relationship, you may use the `loadMorph` method. @@ -1461,6 +1486,7 @@ To populate the default model with attributes, you may pass an array or Closure ### Many To Many Relationships + #### Attaching / Detaching Eloquent also provides a few additional helper methods to make working with related models more convenient. For example, let's imagine a user can have many roles and a role can have many users. To attach a role to a user by inserting a record in the intermediate table that joins the models, use the `attach` method: @@ -1492,6 +1518,7 @@ For convenience, `attach` and `detach` also accept arrays of IDs as input: 2 => ['expires' => $expires], ]); + #### Syncing Associations You may also use the `sync` method to construct many-to-many associations. The `sync` method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table. So, after this operation is complete, only the IDs in the given array will exist in the intermediate table: @@ -1506,18 +1533,21 @@ If you do not want to detach existing IDs, you may use the `syncWithoutDetaching $user->roles()->syncWithoutDetaching([1, 2, 3]); + #### Toggling Associations The many-to-many relationship also provides a `toggle` method which "toggles" the attachment status of the given IDs. If the given ID is currently attached, it will be detached. Likewise, if it is currently detached, it will be attached: $user->roles()->toggle([1, 2, 3]); + #### Saving Additional Data On A Pivot Table When working with a many-to-many relationship, the `save` method accepts an array of additional intermediate table attributes as its second argument: App\Models\User::find(1)->roles()->save($role, ['expires' => $expires]); + #### Updating A Record On A Pivot Table If you need to update an existing row in your pivot table, you may use `updateExistingPivot` method. This method accepts the pivot record foreign key and an array of attributes to update: diff --git a/eloquent-resources.md b/eloquent-resources.md index f50dd2c0b64..7102021a384 100644 --- a/eloquent-resources.md +++ b/eloquent-resources.md @@ -24,6 +24,7 @@ To generate a resource class, you may use the `make:resource` Artisan command. B php artisan make:resource User + #### Resource Collections In addition to generating resources that transform individual models, you may generate resources that are responsible for transforming collections of models. This allows your response to include links and other meta information that is relevant to an entire collection of a given resource. @@ -128,6 +129,7 @@ After defining your resource collection, it may be returned from a route or cont return new UserCollection(User::all()); }); + #### Preserving Collection Keys When returning a resource collection from a route, Laravel resets the collection's keys so that they are in simple numerical order. However, you may add a `preserveKeys` property to your resource class indicating if collection keys should be preserved: @@ -157,6 +159,7 @@ When the `preserveKeys` property is set to `true`, collection keys will be prese return UserResource::collection(User::all()->keyBy->id); }); + #### Customizing The Underlying Resource Class Typically, the `$this->collection` property of a resource collection is automatically populated with the result of mapping each item of the collection to its singular resource class. The singular resource class is assumed to be the collection's class name without the trailing `Collection` string. @@ -221,6 +224,7 @@ Once a resource has been defined, it may be returned directly from a route or co return new UserResource(User::find(1)); }); + #### Relationships If you would like to include related resources in your response, you may add them to the array returned by your `toArray` method. In this example, we will use the `Post` resource's `collection` method to add the user's blog posts to the resource response: @@ -245,6 +249,7 @@ If you would like to include related resources in your response, you may add the > {tip} If you would like to include relationships only when they have already been loaded, check out the documentation on [conditional relationships](#conditional-relationships). + #### Resource Collections While resources translate a single model into an array, resource collections translate a collection of models into an array. It is not absolutely necessary to define a resource collection class for each one of your model types since all resources provide a `collection` method to generate an "ad-hoc" resource collection on the fly: @@ -364,6 +369,7 @@ If you would like to disable the wrapping of the outermost resource, you may use > {note} The `withoutWrapping` method only affects the outermost response and will not remove `data` keys that you manually add to your own resource collections. + ### Wrapping Nested Resources You have total freedom to determine how your resource's relationships are wrapped. If you would like all resource collections to be wrapped in a `data` key, regardless of their nesting, you should define a resource collection class for each resource and return the collection within a `data` key. @@ -390,6 +396,7 @@ You may be wondering if this will cause your outermost resource to be wrapped in } } + ### Data Wrapping And Pagination When returning paginated collections in a resource response, Laravel will wrap your resource data in a `data` key even if the `withoutWrapping` method has been called. This is because paginated responses always contain `meta` and `links` keys with information about the paginator's state: @@ -499,6 +506,7 @@ The `when` method also accepts a Closure as its second argument, allowing you to return 'secret-value'; }), + #### Merging Conditional Attributes Sometimes you may have several attributes that should only be included in the resource response based on the same condition. In this case, you may use the `mergeWhen` method to include the attributes in the response only when the given condition is `true`: @@ -555,6 +563,7 @@ Ultimately, this makes it easier to avoid "N+1" query problems within your resou In this example, if the relationship has not been loaded, the `posts` key will be removed from the resource response entirely before it is sent to the client. + #### Conditional Pivot Information In addition to conditionally including relationship information in your resource responses, you may conditionally include data from the intermediate tables of many-to-many relationships using the `whenPivotLoaded` method. The `whenPivotLoaded` method accepts the name of the pivot table as its first argument. The second argument should be a Closure that defines the value to be returned if the pivot information is available on the model: @@ -618,6 +627,7 @@ Some JSON API standards require the addition of meta data to your resource and r When returning additional meta data from your resources, you never have to worry about accidentally overriding the `links` or `meta` keys that are automatically added by Laravel when returning paginated responses. Any additional `links` you define will be merged with the links provided by the paginator. + #### Top Level Meta Data Sometimes you may wish to only include certain meta data with a resource response if the resource is the outermost resource being returned. Typically, this includes meta information about the response as a whole. To define this meta data, add a `with` method to your resource class. This method should return an array of meta data to be included with the resource response only when the resource is the outermost resource being rendered: @@ -657,6 +667,7 @@ Sometimes you may wish to only include certain meta data with a resource respons } } + #### Adding Meta Data When Constructing Resources You may also add top-level data when constructing resource instances in your route or controller. The `additional` method, which is available on all resources, accepts an array of data that should be added to the resource response: diff --git a/eloquent-serialization.md b/eloquent-serialization.md index 593b3bc216a..6fc774a6a84 100644 --- a/eloquent-serialization.md +++ b/eloquent-serialization.md @@ -60,6 +60,7 @@ Since models and collections are converted to JSON when cast to a string, you ca return App\Models\User::all(); }); + #### Relationships When an Eloquent model is converted to JSON, its loaded relationships will automatically be included as attributes on the JSON object. Also, though Eloquent relationship methods are defined using "camel case", a relationship's JSON attribute will be "snake case". @@ -105,6 +106,7 @@ Alternatively, you may use the `visible` property to define a white-list of attr protected $visible = ['first_name', 'last_name']; } + #### Temporarily Modifying Attribute Visibility If you would like to make some typically hidden attributes visible on a given model instance, you may use the `makeVisible` method. The `makeVisible` method returns the model instance for convenient method chaining: @@ -159,6 +161,7 @@ After creating the accessor, add the attribute name to the `appends` property on Once the attribute has been added to the `appends` list, it will be included in both the model's array and JSON representations. Attributes in the `appends` array will also respect the `visible` and `hidden` settings configured on the model. + #### Appending At Run Time You may instruct a single model instance to append attributes using the `append` method. Or, you may use the `setAppends` method to override the entire array of appended properties for a given model instance: @@ -170,6 +173,7 @@ You may instruct a single model instance to append attributes using the `append` ## Date Serialization + #### Customizing The Default Date Format You may customize the default serialization format by overriding the `serializeDate` method: @@ -185,6 +189,7 @@ You may customize the default serialization format by overriding the `serializeD return $date->format('Y-m-d'); } + #### Customizing The Date Format Per Attribute You may customize the serialization format of individual Eloquent date attributes by specifying the date format in the [cast declaration](/docs/{{version}}/eloquent-mutators#attribute-casting): diff --git a/eloquent.md b/eloquent.md index c9f4cd19c21..db12d1281ae 100644 --- a/eloquent.md +++ b/eloquent.md @@ -79,6 +79,7 @@ Now, let's look at an example `Flight` model, which we will use to retrieve and // } + #### Table Names Note that we did not tell Eloquent which table to use for our `Flight` model. By convention, the "snake case", plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the `Flight` model stores records in the `flights` table, while an `AirTrafficController` model would store records in an `air_traffic_controllers` table. @@ -101,6 +102,7 @@ You can manually specify a table name by defining a `table` property on your mod protected $table = 'my_flights'; } + #### Primary Keys Eloquent will also assume that each table has a primary key column named `id`. You may define a protected `$primaryKey` property to override this convention: @@ -149,6 +151,7 @@ If your primary key is not an integer, you should set the protected `$keyType` p protected $keyType = 'string'; } + #### Timestamps By default, Eloquent expects `created_at` and `updated_at` columns to exist on your tables. If you do not wish to have these columns automatically managed by Eloquent, set the `$timestamps` property on your model to `false`: @@ -197,6 +200,7 @@ If you need to customize the names of the columns used to store the timestamps, const UPDATED_AT = 'last_update'; } + #### Database Connection By default, all Eloquent models will use the default database connection configured for your application. If you would like to specify a different connection for the model, use the `$connection` property: @@ -253,6 +257,7 @@ Once you have created a model and [its associated database table](/docs/{{versio echo $flight->name; } + #### Adding Additional Constraints The Eloquent `all` method will return all of the results in the model's table. Since each Eloquent model serves as a [query builder](/docs/{{version}}/queries), you may also add constraints to queries, and then use the `get` method to retrieve the results: @@ -264,6 +269,7 @@ The Eloquent `all` method will return all of the results in the model's table. S > {tip} Since Eloquent models are query builders, you should review all of the methods available on the [query builder](/docs/{{version}}/queries). You may use any of these methods in your Eloquent queries. + #### Refreshing Models You can refresh models using the `fresh` and `refresh` methods. The `fresh` method will re-retrieve the model from the database. The existing model instance will not be affected: @@ -310,6 +316,7 @@ If you need to process thousands of Eloquent records, use the `chunk` command. T The first argument passed to the method is the number of records you wish to receive per "chunk". The Closure passed as the second argument will be called for each chunk that is retrieved from the database. A database query will be executed to retrieve each chunk of records passed to the Closure. + #### Using Cursors The `cursor` method allows you to iterate through your database records using a cursor, which will only execute a single query. When processing large amounts of data, the `cursor` method may be used to greatly reduce your memory usage: @@ -331,6 +338,7 @@ The `cursor` returns an `Illuminate\Support\LazyCollection` instance. [Lazy coll ### Advanced Subqueries + #### Subquery Selects Eloquent also offers advanced subquery support, which allows you to pull information from related tables in a single query. For example, let's imagine that we have a table of flight `destinations` and a table of `flights` to destinations. The `flights` table contains an `arrived_at` column which indicates when the flight arrived at the destination. @@ -346,6 +354,7 @@ Using the subquery functionality available to the `select` and `addSelect` metho ->limit(1) ])->get(); + #### Subquery Ordering In addition, the query builder's `orderBy` function supports subqueries. We may use this functionality to sort all destinations based on when the last flight arrived at that destination. Again, this may be done while executing a single query against the database: @@ -388,6 +397,7 @@ The `firstOr` method also accepts an array of columns to retrieve: // ... }); + #### Not Found Exceptions Sometimes you may wish to throw an exception if a model is not found. This is particularly useful in routes or controllers. The `findOrFail` and `firstOrFail` methods will retrieve the first result of the query; however, if no result is found, an `Illuminate\Database\Eloquent\ModelNotFoundException` will be thrown: @@ -460,6 +470,7 @@ The `save` method may also be used to update models that already exist in the da $flight->save(); + #### Mass Updates Updates can also be performed against any number of models that match a given query. In this example, all flights that are `active` and have a `destination` of `San Diego` will be marked as delayed: @@ -472,6 +483,7 @@ The `update` method expects an array of column and value pairs representing the > {note} When issuing a mass update via Eloquent, the `saving`, `saved`, `updating`, and `updated` model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update. + #### Examining Attribute Changes Eloquent provides the `isDirty`, `isClean`, and `wasChanged` methods to examine the internal state of your model and determine how its attributes have changed from when they were originally loaded. @@ -560,6 +572,7 @@ If you already have a model instance, you may use the `fill` method to populate $flight->fill(['name' => 'Flight 22']); + #### Mass Assignment & JSON Columns When assigning JSON columns, each column's mass-assignable key must be specified in your model's `$fillable` array. For security, Laravel does not support updating nested JSON attributes when using the `guarded` property: @@ -573,6 +586,7 @@ When assigning JSON columns, each column's mass-assignable key must be specified 'options->enabled', ]; + #### Allowing Mass Assignment If you would like to make all attributes mass assignable, you may define the `$guarded` property as an empty array: @@ -587,6 +601,7 @@ If you would like to make all attributes mass assignable, you may define the `$g ### Other Creation Methods + #### `firstOrCreate`/ `firstOrNew` There are two other methods you may use to create models by mass assigning attributes: `firstOrCreate` and `firstOrNew`. The `firstOrCreate` method will attempt to locate a database record using the given column / value pairs. If the model can not be found in the database, a record will be inserted with the attributes from the first parameter, along with those in the optional second parameter. @@ -611,6 +626,7 @@ The `firstOrNew` method, like `firstOrCreate` will attempt to locate a record in ['delayed' => 1, 'arrival_time' => '11:30'] ); + #### `updateOrCreate` You may also come across situations where you want to update an existing model or create a new model if none exists. Laravel provides an `updateOrCreate` method to do this in one step. Like the `firstOrCreate` method, `updateOrCreate` persists the model, so there's no need to call `save()`: @@ -640,6 +656,7 @@ To delete a model, call the `delete` method on a model instance: $flight->delete(); + #### Deleting An Existing Model By Key In the example above, we are retrieving the model from the database before calling the `delete` method. However, if you know the primary key of the model, you may delete the model without explicitly retrieving it by calling the `destroy` method. In addition to a single primary key as its argument, the `destroy` method will accept multiple primary keys, an array of primary keys, or a [collection](/docs/{{version}}/collections) of primary keys: @@ -654,6 +671,7 @@ In the example above, we are retrieving the model from the database before calli > {note} The `destroy` method loads each model individually and calls the `delete` method on them so that the `deleting` and `deleted` events are fired. + #### Deleting Models By Query You can also run a delete statement on a set of models. In this example, we will delete all flights that are marked as inactive. Like mass updates, mass deletes will not fire any model events for the models that are deleted: @@ -708,6 +726,7 @@ To determine if a given model instance has been soft deleted, use the `trashed` ### Querying Soft Deleted Models + #### Including Soft Deleted Models As noted above, soft deleted models will automatically be excluded from query results. However, you may force soft deleted models to appear in a result set using the `withTrashed` method on the query: @@ -720,6 +739,7 @@ The `withTrashed` method may also be used on a [relationship](/docs/{{version}}/ $flight->history()->withTrashed()->get(); + #### Retrieving Only Soft Deleted Models The `onlyTrashed` method will retrieve **only** soft deleted models: @@ -728,6 +748,7 @@ The `onlyTrashed` method will retrieve **only** soft deleted models: ->where('airline_id', 1) ->get(); + #### Restoring Soft Deleted Models Sometimes you may wish to "un-delete" a soft deleted model. To restore a soft deleted model into an active state, use the `restore` method on a model instance: @@ -744,6 +765,7 @@ Like the `withTrashed` method, the `restore` method may also be used on [relatio $flight->history()->restore(); + #### Permanently Deleting Models Sometimes you may need to truly remove a model from your database. To permanently remove a soft deleted model from the database, use the `forceDelete` method: @@ -781,6 +803,7 @@ You may create an unsaved copy of a model instance using the `replicate` method. Global scopes allow you to add constraints to all queries for a given model. Laravel's own [soft delete](#soft-deleting) functionality utilizes global scopes to only pull "non-deleted" models from the database. Writing your own global scopes can provide a convenient, easy way to make sure every query for a given model receives certain constraints. + #### Writing Global Scopes Writing a global scope is simple. Define a class that implements the `Illuminate\Database\Eloquent\Scope` interface. This interface requires you to implement one method: `apply`. The `apply` method may add `where` constraints to the query as needed: @@ -810,6 +833,7 @@ Writing a global scope is simple. Define a class that implements the `Illuminate > {tip} If your global scope is adding columns to the select clause of the query, you should use the `addSelect` method instead of `select`. This will prevent the unintentional replacement of the query's existing select clause. + #### Applying Global Scopes To assign a global scope to a model, you should override a given model's `booted` method and use the `addGlobalScope` method: @@ -838,6 +862,7 @@ After adding the scope, a query to `User::all()` will produce the following SQL: select * from `users` where `age` > 200 + #### Anonymous Global Scopes Eloquent also allows you to define global scopes using Closures, which is particularly useful for simple scopes that do not warrant a separate class: @@ -864,6 +889,7 @@ Eloquent also allows you to define global scopes using Closures, which is partic } } + #### Removing Global Scopes If you would like to remove a global scope for a given query, you may use the `withoutGlobalScope` method. The method accepts the class name of the global scope as its only argument: @@ -922,6 +948,7 @@ Scopes should always return a query builder instance: } } + #### Utilizing A Local Scope Once the scope has been defined, you may call the scope methods when querying the model. However, you should not include the `scope` prefix when calling the method. You can even chain calls to various scopes, for example: @@ -938,6 +965,7 @@ However, since this can be cumbersome, Laravel provides a "higher order" `orWher $users = App\Models\User::popular()->orWhere->active()->get(); + #### Dynamic Scopes Sometimes you may wish to define a scope that accepts parameters. To get started, just add your additional parameters to your scope. Scope parameters should be defined after the `$query` parameter: @@ -1055,6 +1083,7 @@ If needed, you may utilize [queueable anonymous event listeners](/docs/{{version ### Observers + #### Defining Observers If you are listening for many events on a given model, you may use observers to group all of your listeners into a single class. Observer classes have method names which reflect the Eloquent events you wish to listen for. Each of these methods receives the model as their only argument. The `make:observer` Artisan command is the easiest way to create a new observer class: @@ -1162,6 +1191,7 @@ You may occasionally wish to temporarily "mute" all events fired by a model. You return User::find(2); }); + #### Saving A Single Model Without Events Sometimes you may wish to "save" a given model without raising any events. You may accomplish this using the `saveQuietly` method: diff --git a/encryption.md b/encryption.md index 34ab977abf7..bcc5223fd83 100644 --- a/encryption.md +++ b/encryption.md @@ -17,6 +17,7 @@ Before using Laravel's encrypter, you must set a `key` option in your `config/ap ## Using The Encrypter + #### Encrypting A Value You may encrypt a value using the `encryptString` method of the `Crypt` facade. 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: @@ -49,6 +50,7 @@ You may encrypt a value using the `encryptString` method of the `Crypt` facade. } } + #### Decrypting A Value You may decrypt values using the `decryptString` method of the `Crypt` facade. If the value can not be properly decrypted, such as when the MAC is invalid, an `Illuminate\Contracts\Encryption\DecryptException` will be thrown: diff --git a/envoy.md b/envoy.md index a0f5273b36a..e4f0438e955 100644 --- a/envoy.md +++ b/envoy.md @@ -30,6 +30,7 @@ Since global Composer libraries can sometimes cause package version conflicts, y > {note} Make sure to place the `$HOME/.config/composer/vendor/bin` or `$HOME/.composer/vendor/bin` directory in your PATH so the `envoy` executable is found when running the `envoy` command in your terminal. + #### Updating Envoy You may also use Composer to keep your Envoy installation up to date. Issuing the `composer global update` command will update all of your globally installed Composer packages: @@ -134,6 +135,7 @@ Envoy allows you to easily run a task across multiple servers. First, add additi php artisan migrate @endtask + #### Parallel Execution By default, tasks will be executed on each server serially. In other words, a task will finish running on the first server before proceeding to execute on the second server. If you would like to run a task across multiple servers in parallel, add the `parallel` option to your task declaration: diff --git a/errors.md b/errors.md index 1277d0e90fc..1b4d3917abe 100644 --- a/errors.md +++ b/errors.md @@ -53,6 +53,7 @@ When you register a custom exception reporting callback using the `reportable` m > {tip} To customize the exception reporting for a given exception, you may also consider using [reportable exceptions](/docs/{{version}}/errors#renderable-exceptions) + #### Global Log Context If available, Laravel automatically adds the current user's ID to every exception's log message as contextual data. You may define your own global contextual data by overriding the `context` method of your application's `App\Exceptions\Handler` class. This information will be included in every exception's log message written by your application: @@ -69,6 +70,7 @@ If available, Laravel automatically adds the current user's ID to every exceptio ]); } + #### The `report` Helper Sometimes you may need to report an exception but continue handling the current request. The `report` helper function allows you to quickly report an exception using your exception handler without rendering an error page: @@ -84,6 +86,7 @@ Sometimes you may need to report an exception but continue handling the current } } + #### Ignoring Exceptions By Type The `$dontReport` property of the exception handler contains an array of exception types that will not be logged. For example, exceptions resulting from 404 errors, as well as several other types of errors, are not written to your log files. You may add other exception types to this array as needed: diff --git a/events.md b/events.md index 92bea794234..2aef00c1266 100644 --- a/events.md +++ b/events.md @@ -104,6 +104,7 @@ If you would like to handle anonymous queued listener failures, you may provide // The queued listener failed... })); + #### 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: @@ -236,6 +237,7 @@ Next, let's take a look at the listener for our example event. Event listeners r > {tip} Your event listeners may also type-hint any dependencies they need on their constructors. All event listeners are resolved via the Laravel [service container](/docs/{{version}}/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. @@ -261,6 +263,7 @@ To specify that a listener should be queued, add the `ShouldQueue` interface to 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](/docs/{{version}}/queues). 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: @@ -308,6 +311,7 @@ If you would like to define the listener's queue at runtime, you may define a `v return 'listeners'; } + #### Conditionally Queueing Listeners Sometimes, you may need to determine whether a listener should be queued based on some data that's only available at runtime. To accomplish this, a `shouldQueue` method may be added to a listener to determine whether the listener should be queued. If the `shouldQueue` method returns `false`, the listener will not be executed: diff --git a/filesystem.md b/filesystem.md index d9dfad54eac..cc1329bebb9 100644 --- a/filesystem.md +++ b/filesystem.md @@ -58,6 +58,7 @@ When using the `local` driver, all file operations are relative to the `root` di Storage::disk('local')->put('file.txt', 'Contents'); + #### Permissions The `public` [visibility](#file-visibility) translates to `0755` for directories and `0644` for files. You can modify the permissions mappings in your `filesystems` configuration file: @@ -80,6 +81,7 @@ The `public` [visibility](#file-visibility) translates to `0755` for directories ### Driver Prerequisites + #### Composer Packages Before using the SFTP or S3 drivers, you will need to install the appropriate package via Composer: @@ -91,10 +93,12 @@ An absolute must for performance is to use a cached adapter. You will need an ad - CachedAdapter: `league/flysystem-cached-adapter ~1.0` + #### S3 Driver Configuration The S3 driver configuration information is located in your `config/filesystems.php` configuration file. This file contains an example configuration array for an S3 driver. You are free to modify this array with your own S3 configuration and credentials. For convenience, these environment variables match the naming convention used by the AWS CLI. + #### 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: @@ -113,6 +117,7 @@ Laravel's Flysystem integrations works great with FTP; however, a sample configu // '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.php` configuration file. If you need to configure a SFTP filesystem, you may use the example configuration below: @@ -200,6 +205,7 @@ When using the `local` driver, all files that should be publicly accessible shou > {note} When using the `local` driver, the return value of `url` is not URL encoded. For this reason, we recommend always storing your files using names that will create valid URLs. + #### Temporary URLs For files stored using the `s3` you may create a temporary URL to a given file using the `temporaryUrl` method. This method accepts a path and a `DateTime` instance specifying when the URL should expire: @@ -219,6 +225,7 @@ If you need to specify additional [S3 request parameters](https://docs.aws.amazo ] ); + #### URL Host Customization If you would like to pre-define the host for file URLs generated using the `Storage` facade, you may add a `url` option to the disk's configuration array: @@ -263,6 +270,7 @@ The `put` method may be used to store raw file contents on a disk. You may also 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 an `Illuminate\Http\File` or `Illuminate\Http\UploadedFile` instance and will automatically stream the file to your desired location: @@ -282,6 +290,7 @@ The `putFile` and `putFileAs` methods also accept an argument to specify the "vi 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: @@ -290,6 +299,7 @@ The `prepend` and `append` methods allow you to write to the beginning or end of 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: @@ -332,6 +342,7 @@ You may also call the `putFile` method on the `Storage` facade to perform the sa $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: @@ -348,6 +359,7 @@ You may also use the `putFileAs` method on the `Storage` facade, which will perf > {note} Unprintable and invalid unicode characters will automatically be removed from file paths. Therefore, you may wish to sanitize your file paths before passing them to Laravel's file storage methods. File paths are normalized using the `League\Flysystem\Util::normalizePath` method. + #### 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: @@ -364,6 +376,7 @@ If you are using the `storeAs` method, you may pass the disk name as the third a 's3' ); + #### Other File Information If you would like to get original name of the uploaded file, you may do so using the `getClientOriginalName` method: @@ -421,6 +434,7 @@ If necessary, you may specify the disk that the file should be deleted from: ## 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 subdirectories, you may use the `allFiles` method: @@ -431,6 +445,7 @@ The `files` method returns an array of all of the files in a given directory. If $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 subdirectories: @@ -440,12 +455,14 @@ The `directories` method returns an array of all the directories within a given // Recursive... $directories = Storage::allDirectories($directory); + #### Create A Directory The `makeDirectory` method will create the given directory, including any needed subdirectories: Storage::makeDirectory($directory); + #### Delete A Directory Finally, the `deleteDirectory` method may be used to remove a directory and all of its files: diff --git a/hashing.md b/hashing.md index 93faab97a04..e9f33356bbb 100644 --- a/hashing.md +++ b/hashing.md @@ -49,6 +49,7 @@ You may hash a password by calling the `make` method on the `Hash` facade: } } + #### 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: @@ -57,6 +58,7 @@ If you are using the Bcrypt algorithm, the `make` method allows you to manage th '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: @@ -69,6 +71,7 @@ If you are using the Argon2 algorithm, the `make` method allows you to manage th > {tip} For more information on these options, check out the [official PHP documentation](https://secure.php.net/manual/en/function.password-hash.php). + #### Verifying A Password Against A Hash The `check` method allows you to verify that a given plain-text string corresponds to a given hash: @@ -77,6 +80,7 @@ The `check` method allows you to verify that a given plain-text string correspon // 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: diff --git a/helpers.md b/helpers.md index aaa7b81d029..051120d5da7 100644 --- a/helpers.md +++ b/helpers.md @@ -22,6 +22,7 @@ Laravel includes a variety of global "helper" PHP functions. Many of these funct } + ### Arrays & Objects
@@ -61,6 +62,7 @@ Laravel includes a variety of global "helper" PHP functions. Many of these funct [last](#method-last)
+ ### Paths
@@ -76,6 +78,7 @@ Laravel includes a variety of global "helper" PHP functions. Many of these funct
+ ### Strings
@@ -128,7 +131,7 @@ Laravel includes a variety of global "helper" PHP functions. Many of these funct
- + ### Fluent Strings
@@ -188,6 +191,7 @@ Laravel includes a variety of global "helper" PHP functions. Many of these funct
+ ### URLs
@@ -201,6 +205,7 @@ Laravel includes a variety of global "helper" PHP functions. Many of these funct
+ ### Miscellaneous
diff --git a/homestead.md b/homestead.md index 9cf0d232066..e9d534a0a11 100644 --- a/homestead.md +++ b/homestead.md @@ -136,6 +136,7 @@ To use the Parallels provider, you will need to install [Parallels Vagrant plug- Because of [Vagrant limitations](https://www.vagrantup.com/docs/hyperv/limitations.html), the Hyper-V provider ignores all networking settings. + #### Installing The Homestead Vagrant Box Once VirtualBox / VMware and Vagrant have been installed, you should add the `laravel/homestead` box to your Vagrant installation using the following command in your terminal. It will take a few minutes to download the box, depending on your Internet connection speed: @@ -146,6 +147,7 @@ If this command fails, make sure your Vagrant installation is up to date. > {note} Homestead periodically issues "alpha" / "beta" boxes for testing, which may interfere with the `vagrant box add` command. If you are having issues running `vagrant box add`, you may run the `vagrant up` command and the correct box will be downloaded when Vagrant attempts to start the virtual machine. + #### Installing Homestead You may install Homestead by cloning the repository onto your host machine. Consider cloning the repository into a `Homestead` folder within your "home" directory, as the Homestead box will serve as the host to all of your Laravel projects: @@ -169,12 +171,14 @@ Once you have cloned the Homestead repository, run the `bash init.sh` command fr ### Configuring Homestead + #### Setting Your Provider The `provider` key in your `Homestead.yaml` file indicates which Vagrant provider should be used: `virtualbox`, `vmware_fusion`, `vmware_workstation`, `parallels` or `hyperv`. You may set this to the provider you prefer: provider: virtualbox + #### Configuring Shared Folders The `folders` property of the `Homestead.yaml` file lists all of the folders you wish to share with your Homestead environment. As files within these folders are changed, they will be kept in sync between your local machine and the Homestead environment. You may configure as many shared folders as necessary: @@ -215,6 +219,7 @@ You may also pass any options supported by Vagrant's [Synced Folders](https://ww rsync__args: ["--verbose", "--archive", "--delete", "-zz"] rsync__exclude: ["node_modules"] + #### Configuring Nginx Sites Not familiar with Nginx? No problem. The `sites` property allows you to easily map a "domain" to a folder on your Homestead environment. A sample site configuration is included in the `Homestead.yaml` file. Again, you may add as many sites to your Homestead environment as necessary. Homestead can serve as a convenient, virtualized environment for every Laravel project you are working on: @@ -227,6 +232,7 @@ If you change the `sites` property after provisioning the Homestead box, you sho > {note} Homestead scripts are built to be as idempotent as possible. However, if you are experiencing issues while provisioning you should destroy and rebuild the machine via `vagrant destroy && vagrant up`. + #### Enable / Disable Services Homestead starts several services by default; however, you may customize which services are enabled or disabled during provisioning. For example, you may enable PostgreSQL and disable MySQL: @@ -315,20 +321,24 @@ Optional software is installed using the "features" setting in your Homestead co - solr: true - webdriver: true + #### MariaDB Enabling MariaDB will remove MySQL and install MariaDB. MariaDB serves as a drop-in replacement for MySQL, so you should still use the `mysql` database driver in your application's database configuration. + #### MongoDB The default MongoDB installation will set the database username to `homestead` and the corresponding password to `secret`. + #### Elasticsearch You may specify a supported version of Elasticsearch, which may be a major version or an exact version number (major.minor.patch). The default installation will create a cluster named 'homestead'. You should never give Elasticsearch more than half of the operating system's memory, so make sure your Homestead machine has at least twice the Elasticsearch allocation. > {tip} Check out the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current) to learn how to customize your configuration. + #### Neo4j The default Neo4j installation will set the database username to `homestead` and corresponding password to `secret`. To access the Neo4j browser, visit `http://homestead.test:7474` via your web browser. The ports `7687` (Bolt), `7474` (HTTP), and `7473` (HTTPS) are ready to serve requests from the Neo4j client. @@ -351,6 +361,7 @@ After you have updated the `aliases` file, you should re-provision the Homestead Sometimes you may want to `vagrant up` your Homestead machine from anywhere on your filesystem. You can do this on Mac / Linux systems by adding a Bash function to your Bash profile. On Windows, you may accomplish this by adding a "batch" file to your `PATH`. These scripts will allow you to run any Vagrant command from anywhere on your system and will automatically point that command to your Homestead installation: + #### Mac / Linux function homestead() { @@ -359,6 +370,7 @@ Sometimes you may want to `vagrant up` your Homestead machine from anywhere on y Make sure to tweak the `~/Homestead` path in the function to the location of your actual Homestead installation. Once the function is installed, you may run commands like `homestead up` or `homestead ssh` from anywhere on your system. + #### Windows Create a `homestead.bat` batch file anywhere on your machine with the following contents: @@ -568,6 +580,7 @@ By default, the following ports are forwarded to your Homestead environment: - **Minio:** 9600 → Forwards To 9600
+ #### Forwarding Additional Ports If you wish, you may forward additional ports to the Vagrant box, as well as specify their protocol: @@ -653,6 +666,7 @@ To debug a PHP CLI application, use the `xphp` shell alias inside your Vagrant b xphp path/to/script + #### Autostarting Xdebug When debugging functional tests that make requests to the web server, it is easier to autostart debugging rather than modifying tests to pass through a custom header or cookie to trigger debugging. To force Xdebug to start automatically, modify `/etc/php/7.x/fpm/conf.d/20-xdebug.ini` inside your Vagrant box and add the following configuration: @@ -679,6 +693,7 @@ To enable Blackfire, use the "features" setting in your Homestead configuration Blackfire server credentials and client credentials [require a user account](https://blackfire.io/signup). Blackfire offers various options to profile an application, including a CLI tool and browser extension. Please [review the Blackfire documentation for more details](https://blackfire.io/docs/cookbooks/index). + ### Profiling PHP Performance Using XHGui [XHGui](https://www.github.com/perftools/xhgui) is a user interface for exploring the performance of your PHP applications. To enable XHGui, add `xhgui: 'true'` to your site configuration: @@ -738,6 +753,7 @@ When customizing Homestead, Ubuntu may ask you if you would like to keep a packa -o Dpkg::Options::="--force-confold" \ install your-package + ### User Customizations When using Homestead in a team setting, you may want to tweak Homestead to better fit your personal development style. You may create a `user-customizations.sh` file in the root of your Homestead directory (The same directory containing your `Homestead.yaml`). Within this file, you may make any customization you would like; however, the `user-customizations.sh` should not be version controlled. @@ -783,6 +799,7 @@ Finally, you will need to regenerate your Homestead box to utilize the latest Va ### VirtualBox + #### `natdnshostresolver` By default, Homestead configures the `natdnshostresolver` setting to `on`. This allows Homestead to use your host operating system's DNS settings. If you would like to override this behavior, add the following lines to your `Homestead.yaml` file: @@ -790,6 +807,7 @@ By default, Homestead configures the `natdnshostresolver` setting to `on`. This provider: virtualbox natdnshostresolver: 'off' + #### Symbolic Links On Windows If symbolic links are not working properly on your Windows machine, you may need to add the following block to your `Vagrantfile`: diff --git a/horizon.md b/horizon.md index f45ef7ba29e..5fd3a281d10 100644 --- a/horizon.md +++ b/horizon.md @@ -40,6 +40,7 @@ After publishing Horizon's assets, its primary configuration file will be locate > {note} You should ensure that the `environments` portion of your `horizon` configuration file contains an entry for each environment on which you plan to run Horizon. + #### Balance Options Horizon allows you to choose from three balancing strategies: `simple`, `auto`, and `false`. The `simple` strategy, which is the configuration file's default, splits incoming jobs evenly between processes: @@ -67,6 +68,7 @@ When using the `auto` strategy, you may define the `minProcesses` and `maxProces The `balanceMaxShift` and `balanceCooldown` configuration values to determine how quickly Horizon will scale to meet worker demand. In the example above, a maximum of one new process will be created or destroyed every three seconds. You are free to tweak these values as necessary based on your application's needs. + #### Job Trimming The `horizon` configuration file allows you to configure how long recent and failed jobs should be persisted (in minutes). By default, recent jobs are kept for one hour while failed jobs are kept for a week: @@ -144,6 +146,7 @@ You may gracefully terminate the master Horizon process on your machine using th If you are deploying Horizon to a live server, you should configure a process monitor to monitor the `php artisan horizon` command and restart it if it quits unexpectedly. When deploying fresh code to your server, you will need to instruct the master Horizon process to terminate so it can be restarted by your process monitor and receive your code changes. + #### Installing Supervisor Supervisor is a process monitor for the Linux operating system, and will automatically restart your `horizon` process if it fails. To install Supervisor on Ubuntu, you may use the following command: @@ -152,6 +155,7 @@ Supervisor is a process monitor for the Linux operating system, and will automat > {tip} If configuring Supervisor yourself sounds overwhelming, consider using [Laravel Forge](https://forge.laravel.com), which will automatically install and configure Supervisor for your Laravel projects. + #### Supervisor Configuration Supervisor configuration files are typically stored in the `/etc/supervisor/conf.d` directory. 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 `horizon.conf` file that starts and monitors a `horizon` process: @@ -168,6 +172,7 @@ Supervisor configuration files are typically stored in the `/etc/supervisor/conf > {note} You should ensure that the value of `stopwaitsecs` is greater than the number of seconds consumed by your longest running job. Otherwise, Supervisor may kill the job before it is finished processing. + #### Starting Supervisor Once the configuration file has been created, you may update the Supervisor configuration and start the processes using the following commands: @@ -235,6 +240,7 @@ If this job is queued with an `App\Models\Video` instance that has an `id` of `1 App\Jobs\RenderVideo::dispatch($video); + #### Manually Tagging If you would like to manually define the tags for one of your queueable objects, you may define a `tags` method on the class: @@ -263,6 +269,7 @@ If you would like to be notified when one of your queues has a long wait time, y Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel'); Horizon::routeSmsNotificationsTo('15556667777'); + #### Configuring Notification Wait Time Thresholds You may configure how many seconds are considered a "long wait" within your `config/horizon.php` configuration file. The `waits` configuration option within this file allows you to control the long wait threshold for each connection / queue combination: diff --git a/http-client.md b/http-client.md index c6135b4b829..6bb80070ff7 100644 --- a/http-client.md +++ b/http-client.md @@ -58,6 +58,7 @@ Of course, it is common when using `POST`, `PUT`, and `PATCH` to send additional 'role' => 'Network Administrator', ]); + #### GET Request Query Parameters When making `GET` requests, you may either append a query string to the URL directly or pass an array of key / value pairs as the second argument to the `get` method: @@ -67,6 +68,7 @@ When making `GET` requests, you may either append a query string to the URL dire 'page' => 1, ]); + #### Sending Form URL Encoded Requests If you would like to send data using the `application/x-www-form-urlencoded` content type, you should call the `asForm` method before making your request: @@ -76,6 +78,7 @@ If you would like to send data using the `application/x-www-form-urlencoded` con 'role' => 'Privacy Consultant', ]); + #### Sending A Raw Request Body You may use the `withBody` method if you would like to provide a raw request body when making a request: @@ -84,6 +87,7 @@ You may use the `withBody` method if you would like to provide a raw request bod base64_encode($photo), 'image/jpeg' )->post('http://test.com/photo'); + #### Multi-Part Requests If you would like to send files as multi-part requests, you should call the `attach` method before making your request. This method accepts the name of the file and its contents. Optionally, you may provide a third argument which will be considered the file's filename: @@ -123,6 +127,7 @@ You may specify basic and digest authentication credentials using the `withBasic // Digest authentication... $response = Http::withDigestAuth('taylor@laravel.com', 'secret')->post(...); + #### Bearer Tokens If you would like to quickly add an `Authorization` bearer token header to the request, you may use the `withToken` method: @@ -164,6 +169,7 @@ Unlike Guzzle's default behavior, Laravel's HTTP client wrapper does not throw e // Determine if the response has a 500 level status code... $response->serverError(); + #### Throwing Exceptions If you have a response instance and would like to throw an instance of `Illuminate\Http\Client\RequestException` if the response is a client or server error, you may use the `throw` method: @@ -214,6 +220,7 @@ For example, to instruct the HTTP client to return empty, `200` status code resp > {note} When faking requests, HTTP client middleware are not executed. You should define expectations for faked responses as if these middleware have run correctly. + #### Faking Specific URLs Alternatively, you may pass an array to the `fake` method. The array's keys should represent URL patterns that you wish to fake and their associated responses. The `*` character may be used as a wildcard character. Any requests made to URLs that have not been faked will actually be executed. You may use the `response` method to construct stub / fake responses for these endpoints: @@ -236,6 +243,7 @@ If you would like to specify a fallback URL pattern that will stub all unmatched '*' => Http::response('Hello World', 200, ['Headers']), ]); + #### Faking Response Sequences Sometimes you may need to specify that a single URL should return a series of fake responses in a specific order. You may accomplish this using the `Http::sequence` method to build the responses: @@ -264,6 +272,7 @@ If you would like to fake a sequence of responses but do not need to specify a s ->push('Hello World', 200) ->whenEmpty(Http::response()); + #### Fake Callback If you require more complicated logic to determine what responses to return for certain endpoints, you may pass a callback to the `fake` method. This callback will receive an instance of `Illuminate\Http\Client\Request` and should return a response instance: diff --git a/http-tests.md b/http-tests.md index 2f07199548d..4c545368e4c 100644 --- a/http-tests.md +++ b/http-tests.md @@ -279,6 +279,7 @@ The `Illuminate\Http\UploadedFile` class provides a `fake` method which may be u } } + #### Fake File Customization When creating files using the `fake` method, you may specify the width, height, and size of the image in order to better test your validation rules: @@ -311,6 +312,7 @@ If needed, you may get the raw, rendered view contents by casting the `TestView` $contents = (string) $this->view('welcome'); + #### Sharing Errors Some views may depend on errors shared in the global error bag provided by Laravel. To hydrate the error bag with error messages, you may use the `withViewErrors` method: @@ -321,6 +323,7 @@ Some views may depend on errors shared in the global error bag provided by Larav $view->assertSee('Please provide a valid name.'); + #### Rendering Blade & Components If necessary, you may use the `blade` method to evaluate and render a raw Blade string. Like the `view` method, the `blade` method returns an instance of `Illuminate\Testing\TestView`: diff --git a/installation.md b/installation.md index 81638e4b24d..4e781a2a9eb 100644 --- a/installation.md +++ b/installation.md @@ -36,6 +36,7 @@ However, if you are not using Homestead, you will need to make sure your server Laravel utilizes [Composer](https://getcomposer.org) to manage its dependencies. So, before using Laravel, make sure you have Composer installed on your machine. + #### Via Laravel Installer First, download the Laravel installer using Composer: @@ -58,12 +59,14 @@ Once installed, the `laravel new` command will create a fresh Laravel installati > {tip} Want to create a Laravel project with login, registration, and more features already built for you? Check out [Laravel Jetstream](https://jetstream.laravel.com). + #### Via Composer Create-Project Alternatively, you may also install Laravel by issuing the Composer `create-project` command in your terminal: composer create-project --prefer-dist laravel/laravel blog + #### Local Development Server If you have PHP installed locally and you would like to use PHP's built-in development server to serve your application, you may use the `serve` Artisan command. This command will start a development server at `http://localhost:8000`: @@ -75,24 +78,29 @@ More robust local development options are available via [Homestead](/docs/{{vers ### Configuration + #### Public Directory After installing Laravel, you should configure your web server's document / web root to be the `public` directory. The `index.php` in this directory serves as the front controller for all HTTP requests entering your application. + #### Configuration Files All of the configuration files for the Laravel framework are stored in the `config` directory. Each option is documented, so feel free to look through the files and get familiar with the options available to you. + #### Directory Permissions After installing Laravel, you may need to configure some permissions. Directories within the `storage` and the `bootstrap/cache` directories should be writable by your web server or Laravel will not run. If you are using the [Homestead](/docs/{{version}}/homestead) virtual machine, these permissions should already be set. + #### Application Key The next thing you should do after installing Laravel is set your application key to a random string. If you installed Laravel via Composer or the Laravel installer, this key has already been set for you by the `php artisan key:generate` command. Typically, this string should be 32 characters long. The key can be set in the `.env` environment file. If you have not copied the `.env.example` file to a new file named `.env`, you should do that now. **If the application key is not set, your user sessions and other encrypted data will not be secure!** + #### Additional Configuration Laravel needs almost no other configuration out of the box. You are free to get started developing! However, you may wish to review the `config/app.php` file and its documentation. It contains several options such as `timezone` and `locale` that you may wish to change according to your application. @@ -116,6 +124,7 @@ Laravel should always be served out of the root of the "web directory" configure ### Pretty URLs + #### Apache Laravel includes a `public/.htaccess` file that is used to provide URLs without the `index.php` front controller in the path. Before serving Laravel with Apache, be sure to enable the `mod_rewrite` module so the `.htaccess` file will be honored by the server. @@ -132,6 +141,7 @@ If the `.htaccess` file that ships with Laravel does not work with your Apache i RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] + #### Nginx If you are using Nginx, the following directive in your site configuration will direct all requests to the `index.php` front controller: diff --git a/lifecycle.md b/lifecycle.md index 491ba86babf..43c2a47c9ee 100644 --- a/lifecycle.md +++ b/lifecycle.md @@ -14,12 +14,14 @@ The goal of this document is to give you a good, high-level overview of how the ## Lifecycle Overview + ### First Things The entry point for all requests to a Laravel application is the `public/index.php` file. All requests are directed to this file by your web server (Apache / Nginx) configuration. The `index.php` file doesn't contain much code. Rather, it is a starting point for loading the rest of the framework. The `index.php` file loads the Composer generated autoloader definition, and then retrieves an instance of the Laravel application from `bootstrap/app.php`. The first action taken by Laravel itself is to create an instance of the application / [service container](/docs/{{version}}/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. These two kernels serve as the central location that all requests flow through. For now, let's just focus on the HTTP kernel, which is located in `app/Http/Kernel.php`. @@ -30,12 +32,14 @@ The HTTP kernel also defines a list of HTTP [middleware](/docs/{{version}}/middl The method signature for the HTTP kernel's `handle` method is quite simple: receive a `Request` and return a `Response`. Think of the Kernel as being a big black box that represents your entire application. Feed it HTTP requests and it will return HTTP responses. + #### Service Providers One of the most important Kernel bootstrapping actions is loading the [service providers](/docs/{{version}}/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. diff --git a/localization.md b/localization.md index e2bad078e80..c89b887b148 100644 --- a/localization.md +++ b/localization.md @@ -51,6 +51,7 @@ You may configure a "fallback language", which will be used when the active lang '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: diff --git a/logging.md b/logging.md index 7648fbb1eaf..4e3fe88f11f 100644 --- a/logging.md +++ b/logging.md @@ -24,6 +24,7 @@ All of the configuration for your application's logging system is housed in the 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. For more information on building stacks, check out the [documentation below](#building-log-stacks). + #### 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: @@ -34,6 +35,7 @@ By default, Monolog is instantiated with a "channel name" that matches the curre 'channels' => ['single', 'slack'], ], + #### Available Channel Drivers Name | Description @@ -50,6 +52,7 @@ Name | Description > {tip} Check out the documentation on [advanced channel customization](#advanced-monolog-channel-customization) to learn more about the `monolog` and `custom` drivers. + #### Configuring The Single and Daily Channels The `single` and `daily` channels have three optional configuration options: `bubble`, `permission`, and `locking`. @@ -60,10 +63,12 @@ Name | Description | Default `permission` | The log file's permissions | `0644` `locking` | Attempt to lock the log file before writing to it | `false` + #### Configuring The Papertrail Channel The `papertrail` channel requires the `url` and `port` configuration options. You can obtain these values from [Papertrail](https://help.papertrailapp.com/kb/configuration/configuring-centralized-logging-from-php-apps/#send-events-from-php-app). + #### Configuring The Slack Channel The `slack` channel requires a `url` configuration option. This URL should match a URL for an [incoming webhook](https://slack.com/apps/A0F7XDUAZ-incoming-webhooks) that you have configured for your Slack team. By default, Slack will only receive logs at the `critical` level and above; however, you can adjust this in your `logging` configuration file. @@ -95,6 +100,7 @@ As previously mentioned, the `stack` driver allows you to combine multiple chann 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](https://tools.ietf.org/html/rfc5424): **emergency**, **alert**, **critical**, **error**, **warning**, **notice**, **info**, and **debug**. @@ -147,6 +153,7 @@ So, you may call any of these methods to log a message for the corresponding lev } } + #### 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: @@ -226,6 +233,7 @@ When using the `monolog` driver, the `handler` configuration option is used to s ], ], + #### 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: diff --git a/mail.md b/mail.md index c0e4a42097c..8526d65a66d 100644 --- a/mail.md +++ b/mail.md @@ -40,6 +40,7 @@ The API based drivers such as Mailgun and Postmark are often simpler and faster composer require guzzlehttp/guzzle + #### Mailgun Driver To use the Mailgun driver, first install Guzzle, then set the `default` option in your `config/mail.php` configuration file to `mailgun`. Next, verify that your `config/services.php` configuration file contains the following options: @@ -57,6 +58,7 @@ If you are not using the "US" [Mailgun region](https://documentation.mailgun.com 'endpoint' => 'api.eu.mailgun.net', ], + #### Postmark Driver To use the Postmark driver, install Postmark's SwiftMailer transport via Composer: @@ -69,6 +71,7 @@ Next, install Guzzle and set the `default` option in your `config/mail.php` conf 'token' => 'your-postmark-token', ], + #### SES Driver To use the Amazon SES driver you must first install the Amazon AWS SDK for PHP. You may install this library by adding the following line to your `composer.json` file's `require` section and running the `composer update` command: @@ -115,6 +118,7 @@ All of a mailable class' configuration is done in the `build` method. Within thi ### 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: @@ -130,6 +134,7 @@ First, let's explore configuring the sender of the email. Or, in other words, wh ->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: @@ -157,6 +162,7 @@ Within a mailable class' `build` method, you may use the `view` method to specif > {tip} You may wish to create a `resources/views/emails` directory to house all of your email templates; however, you are free to place them wherever you wish within your `resources/views` directory. + #### Plain Text Emails If you would like to define a plain-text version of your email, you may use the `text` method. Like the `view` method, the `text` method accepts a template name which will be used to render the contents of the email. You are free to define both an HTML and plain-text version of your message: @@ -175,6 +181,7 @@ If you would like to define a plain-text version of your email, you may use the ### 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: @@ -227,6 +234,7 @@ Once the data has been set to a public property, it will automatically be availa Price: {{ $order->price }} + #### 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: @@ -315,6 +323,7 @@ When attaching files to a message, you may also specify the display name and / o ]); } + #### Attaching Files from Disk If you have stored a file on one of your [filesystem disks](/docs/{{version}}/filesystem), you may attach it to the email using the `attachFromStorage` method: @@ -358,6 +367,7 @@ The `attachFromStorageDisk` method may be used if you need to specify a storage ->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: @@ -388,6 +398,7 @@ Embedding inline images into your emails is typically cumbersome; however, Larav > {note} `$message` variable is not available in plain-text messages since plain-text messages do not utilize inline attachments. + #### 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: @@ -463,6 +474,7 @@ Markdown mailables use a combination of Blade components and Markdown syntax whi > {tip} 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: @@ -471,6 +483,7 @@ The button component renders a centered button link. The component accepts two a 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: @@ -479,6 +492,7 @@ The panel component renders the given block of text in a panel that has a slight 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: @@ -499,6 +513,7 @@ You may export all of the Markdown mail components to your own application for c This command will publish the Markdown mail components to the `resources/views/vendor/mail` directory. The `mail` directory will contain an `html` and a `text` 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 mail messages. @@ -550,6 +565,7 @@ You are not limited to just specifying the "to" recipients when sending a messag ->bcc($evenMoreUsers) ->send(new OrderShipped($order)); + #### Looping Over Recipients Occasionally, you may need to send a mailable to a list of recipients by iterating over an array of recipients / email addresses. Since the `to` method appends email addresses to the mailable's list of recipients, you should always re-create the mailable instance for each recipient: @@ -558,6 +574,7 @@ Occasionally, you may need to send a mailable to a list of recipients by iterati Mail::to($recipient)->send(new OrderShipped($order)); } + #### Sending Mail Via A Specific Mailer By default, Laravel will use the mailer configured as the `default` mailer in your `mail` configuration file. However, you may use the `mailer` method to send a message using a specific mailer configuration: @@ -569,6 +586,7 @@ By default, Laravel will use the mailer configured as the `default` mailer in yo ### 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](/docs/{{version}}/queues). To queue a mail message, use the `queue` method on the `Mail` facade after specifying the message's recipients: @@ -580,6 +598,7 @@ Since sending email messages can drastically lengthen the response time of your 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](/docs/{{version}}/queues) before using this feature. + #### Delayed Message Queueing If you wish to delay the delivery of a queued email message, you may use the `later` method. As its first argument, the `later` method accepts a `DateTime` instance indicating when the message should be sent: @@ -591,6 +610,7 @@ If you wish to delay the delivery of a queued email message, you may use the `la ->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: @@ -604,6 +624,7 @@ Since all mailable classes generated using the `make:mail` command make use of t ->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: @@ -646,6 +667,7 @@ To accomplish this, the `Mail` facade offers a `locale` method to set the desire 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: @@ -674,10 +696,12 @@ Once you have implemented the interface, Laravel will automatically use the pref 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](/docs/{{version}}/configuration#environment-configuration). + #### 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: @@ -687,6 +711,7 @@ Another solution provided by Laravel is to set a universal recipient of all emai 'name' => 'Example' ], + #### Mailtrap Finally, you may use a service like [Mailtrap](https://mailtrap.io) 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. diff --git a/middleware.md b/middleware.md index 2e82f9621ef..8b2ca25f3b5 100644 --- a/middleware.md +++ b/middleware.md @@ -59,6 +59,7 @@ It's best to envision middleware as a series of "layers" HTTP requests must pass > {tip} All middleware are resolved via the [service container](/docs/{{version}}/container), so you may type-hint any dependencies you need within a middleware's constructor. + #### 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: diff --git a/migrations.md b/migrations.md index bd3ff3edc0c..a03ee063da2 100644 --- a/migrations.md +++ b/migrations.md @@ -112,6 +112,7 @@ To run all of your outstanding migrations, execute the `migrate` Artisan command > {note} If you are using the [Homestead virtual machine](/docs/{{version}}/homestead), you should run this command from within your virtual machine. + #### Forcing Migrations To Run In Production Some migration operations are destructive, which means they may cause you to lose data. In order to protect you from running these commands against your production database, you will be prompted for confirmation before the commands are executed. To force the commands to run without a prompt, use the `--force` flag: @@ -133,6 +134,7 @@ The `migrate:reset` command will roll back all of your application's migrations: php artisan migrate:reset + #### Roll Back & Migrate Using A Single Command The `migrate:refresh` command will roll back all of your migrations and then execute the `migrate` command. This command effectively re-creates your entire database: @@ -146,6 +148,7 @@ You may roll back & re-migrate a limited number of migrations by providing the ` php artisan migrate:refresh --step=5 + #### Drop All Tables & Migrate The `migrate:fresh` command will drop all tables from the database and then execute the `migrate` command: @@ -170,6 +173,7 @@ To create a new database table, use the `create` method on the `Schema` facade. When creating the table, you may use any of the schema builder's [column methods](#creating-columns) to define the table's columns. + #### Checking For Table / Column Existence You may check for the existence of a table or column using the `hasTable` and `hasColumn` methods: @@ -182,6 +186,7 @@ You may check for the existence of a table or column using the `hasTable` and `h // } + #### Database Connection & Table Options If you want to perform a schema operation on a database connection that is not your default connection, use the `connection` method: @@ -212,6 +217,7 @@ To drop an existing table, you may use the `drop` or `dropIfExists` methods: Schema::dropIfExists('users'); + #### Renaming Tables With Foreign Keys Before renaming a table, you should verify that any foreign key constraints on the table have an explicit name in your migration files instead of letting Laravel assign a convention based name. Otherwise, the foreign key constraint name will refer to the old table name. @@ -228,6 +234,7 @@ The `table` method on the `Schema` facade may be used to update existing tables. $table->string('email'); }); + #### Available Column Types The schema builder contains a variety of column types that you may specify when building your tables: @@ -325,6 +332,7 @@ Modifier | Description `->generatedAs($expression)` | Create an identity column with specified sequence options (PostgreSQL) `->always()` | Defines the precedence of sequence values over input for an identity column (PostgreSQL) + #### Default Expressions The `default` modifier accepts a value or an `\Illuminate\Database\Query\Expression` instance. Using an `Expression` instance will prevent wrapping the value in quotes and allow you to use database specific functions. One situation where this is particularly useful is when you need to assign default values to JSON columns: @@ -358,12 +366,14 @@ The `default` modifier accepts a value or an `\Illuminate\Database\Query\Express ### Modifying Columns + #### Prerequisites Before modifying a column, be sure to add the `doctrine/dbal` dependency to your `composer.json` file. The Doctrine DBAL library is used to determine the current state of the column and create the SQL queries needed to make the required adjustments: composer require doctrine/dbal + #### Updating Column Attributes The `change` method allows you to modify type and attributes of existing columns. For example, you may wish to increase the size of a `string` column. To see the `change` method in action, let's increase the size of the `name` column from 25 to 50: @@ -380,6 +390,7 @@ We could also modify a column to be nullable: > {note} Only the following column types can be "changed": bigInteger, binary, boolean, date, dateTime, dateTimeTz, decimal, integer, json, longText, mediumText, smallInteger, string, text, time, unsignedBigInteger, unsignedInteger, unsignedSmallInteger and uuid. + #### Renaming Columns To rename a column, you may use the `renameColumn` method on the schema builder. Before renaming a column, be sure to add the `doctrine/dbal` dependency to your `composer.json` file: @@ -407,6 +418,7 @@ You may drop multiple columns from a table by passing an array of column names t > {note} Dropping or modifying multiple columns within a single migration while using a SQLite database is not supported. + #### Available Command Aliases Command | Description @@ -440,6 +452,7 @@ Laravel will automatically generate an index name based on the table, column nam $table->unique('email', 'unique_email'); + #### Available Index Types Each index method accepts an optional second argument to specify the name of the index. If omitted, the name will be derived from the names of the table and column(s) used for the index, as well as the index type. @@ -452,6 +465,7 @@ Command | Description `$table->index('state');` | Adds a plain index. `$table->spatialIndex('location');` | Adds a spatial index. (except SQLite) + #### Index Lengths & MySQL / MariaDB Laravel uses the `utf8mb4` character set by default, which includes support for storing "emojis" in the database. If you are running a version of MySQL older than the 5.7.7 release or MariaDB older than the 10.2.2 release, you may need to manually configure the default string length generated by migrations in order for MySQL to create indexes for them. You may configure this by calling the `Schema::defaultStringLength` method within your `AppServiceProvider`: diff --git a/mix.md b/mix.md index 4aa8fda1834..a0669548202 100644 --- a/mix.md +++ b/mix.md @@ -35,6 +35,7 @@ If you've ever been confused and overwhelmed about getting started with Webpack ## Installation & Setup + #### Installing Node Before triggering Mix, you must first ensure that Node.js and NPM are installed on your machine. @@ -44,6 +45,7 @@ Before triggering Mix, you must first ensure that Node.js and NPM are installed By default, Laravel Homestead includes everything you need; however, if you aren't using Vagrant, then you can easily install the latest version of Node and NPM using simple graphical installers from [their download page](https://nodejs.org/en/download/). + #### Laravel Mix The only remaining step is to install Laravel Mix. Within a fresh installation of Laravel, you'll find a `package.json` file in the root of your directory structure. The default `package.json` file includes everything you need to get started. Think of this like your `composer.json` file, except it defines Node dependencies instead of PHP. You may install the dependencies it references by running: @@ -61,6 +63,7 @@ Mix is a configuration layer on top of [Webpack](https://webpack.js.org), so to // 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: @@ -191,6 +194,7 @@ Though disabled by default, source maps may be activated by calling the `mix.sou mix.js('resources/js/app.js', 'public/js') .sourceMaps(); + #### Style Of Source Mapping Webpack offers a variety of [source mapping styles](https://webpack.js.org/configuration/devtool/#devtool). By default, Mix's source mapping style is set to `eval-source-map`, which provides a fast rebuild time. If you want to change the mapping style, you may do so using the `sourceMaps` method: @@ -268,6 +272,7 @@ This option is particularly useful for legacy projects where you don't require W 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](https://webpack.js.org/configuration/) that you wish to apply. @@ -280,6 +285,7 @@ Mix provides a useful `webpackConfig` method that allows you to merge any short } }); + #### 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. @@ -317,6 +323,7 @@ Because versioned files are usually unnecessary in development, you may instruct mix.version(); } + #### Custom Mix Base URLs If your Mix compiled assets are deployed to a CDN separate from your application, you will need to change the base URL generated by the `mix` function. You may do so by adding a `mix_url` configuration option to your `config/app.php` configuration file: diff --git a/mocking.md b/mocking.md index 7fbb38eff23..916c7334cdc 100644 --- a/mocking.md +++ b/mocking.md @@ -131,6 +131,7 @@ As an alternative to mocking, you may use the `Event` facade's `fake` method to > {note} After calling `Event::fake()`, no event listeners will be executed. So, if your tests use model factories that rely on events, such as creating a UUID during a model's `creating` event, you should call `Event::fake()` **after** using your factories. + #### Faking A Subset Of Events If you only want to fake event listeners for a specific set of events, you may pass them to the `fake` or `fakeFor` method: diff --git a/notifications.md b/notifications.md index d03d168ad58..0acb4c31c0d 100644 --- a/notifications.md +++ b/notifications.md @@ -148,6 +148,7 @@ If you would like to delay the delivery of the notification, you may chain the ` $user->notify((new InvoicePaid($invoice))->delay($when)); + #### Customizing Notification Channel Queues If you would like to specify a specific queue that should be used for each notification channel supported by the notification, you may define a `viaQueues` method on your notification. This method should return an array of channel name / queue name pairs: @@ -208,6 +209,7 @@ In this example, we register a greeting, a line of text, a call to action, and t > {tip} When sending mail notifications, be sure to set the `name` value 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 `view` method to specify a custom template that should be used to render the notification email: @@ -406,6 +408,7 @@ When attaching files to a message, you may also specify the display name and / o > {tip} Unlike attaching files in mailable objects, you may not attach a file directly from the storage disk using `attachFromStorage`. You should rather use `attach` method with an absolute path to the file on the storage disk. Alternatively, you could return a [mailable](/docs/{{version}}/mail#generating-mailables) from the `toMail` method. + #### Raw Data Attachments The `attachData` method may be used to attach a raw string of bytes as an attachment: @@ -484,6 +487,7 @@ Markdown mail notifications use a combination of Blade components and Markdown s {{ 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: @@ -492,6 +496,7 @@ The button component renders a centered button link. The component accepts two a 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: @@ -500,6 +505,7 @@ The panel component renders the given block of text in a panel that has a slight 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: @@ -520,6 +526,7 @@ You may export all of the Markdown notification components to your own applicati This command will publish the Markdown mail components to the `resources/views/vendor/mail` directory. The `mail` directory will contain an `html` and a `text` 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. @@ -575,6 +582,7 @@ If a notification supports being stored in a database table, you should define a ]; } + #### `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. @@ -654,6 +662,7 @@ The `broadcast` channel broadcasts notifications using Laravel's [event broadcas ]); } + #### 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`: @@ -662,6 +671,7 @@ All broadcast notifications are queued for broadcasting. If you would like to co ->onConnection('sqs') ->onQueue('broadcasts'); + #### Customizing The Notification Type In addition to the data you specify, all broadcast notifications also have a `type` field containing the full class name of the notification. If you would like to customize the notification `type` that is provided to your JavaScript client, you may define a `broadcastType` method on the notification class: @@ -688,6 +698,7 @@ Notifications will broadcast on a private channel formatted using a `{notifiable 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: @@ -775,6 +786,7 @@ Laravel also supports sending shortcode notifications, which are pre-defined mes > {tip} Like [routing SMS Notifications](#routing-sms-notifications), you should implement the `routeNotificationForShortcode` method on your notifiable model. + #### Unicode Content If your SMS message will contain unicode characters, you should call the `unicode` method when constructing the `NexmoMessage` instance: @@ -871,6 +883,7 @@ In this example we are just sending a single line of text to Slack, which will c + #### Customizing The Sender & Recipient You may use the `from` and `to` methods to customize the sender and recipient. The `from` method accepts a username and emoji identifier, while the `to` method accepts a channel or username: @@ -963,6 +976,7 @@ 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](https://api.slack.com/docs/message-formatting#message_formatting): @@ -1028,6 +1042,7 @@ Localization of multiple notifiable entries may also be achieved via the `Notifi 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: diff --git a/packages.md b/packages.md index 3690dbaf06d..1a0decede7a 100644 --- a/packages.md +++ b/packages.md @@ -47,6 +47,7 @@ In a Laravel application's `config/app.php` configuration file, the `providers` 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: @@ -102,6 +103,7 @@ Now, when users of your package execute Laravel's `vendor:publish` command, your > {note} 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: @@ -171,6 +173,7 @@ Package translations are referenced using the `package::file.line` syntax conven 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: @@ -212,10 +215,12 @@ Package views are referenced using the `package::view` syntax convention. So, on 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: @@ -260,6 +265,7 @@ Once your view components are registered in a service provider, you may referenc + #### Anonymous Components If your package contains anonymous components, they must be placed within a `components` directory of your package's "views" directory (as specified by `loadViewsFrom`). Then, you may render them by prefixing the component name with the package's view namespace: diff --git a/pagination.md b/pagination.md index 7d3e308f609..594304d3fc3 100644 --- a/pagination.md +++ b/pagination.md @@ -50,6 +50,7 @@ In this example, the only argument passed to the `paginate` method is the number > {note} Currently, pagination operations that use a `groupBy` statement 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: @@ -97,6 +98,7 @@ When calling the `paginate` method, you will receive an instance of `Illuminate\ 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 [Tailwind CSS framework](https://tailwindcss.com). + #### 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 `withPath` method: @@ -109,6 +111,7 @@ The `withPath` method allows you to customize the URI used by the paginator when // }); + #### 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`: @@ -123,6 +126,7 @@ If you wish to append a "hash fragment" to the paginator's URLs, you may use the {{ $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 `onEachSide` method: diff --git a/passport.md b/passport.md index 795f84db9dc..35a53bb59fb 100644 --- a/passport.md +++ b/passport.md @@ -262,6 +262,7 @@ Using OAuth2 with authorization codes is how most developers are familiar with O First, developers building applications that need to interact with your application's API will need to register their application with yours by creating a "client". Typically, this consists of providing the name of their application and a URL that your application can redirect to after users approve their request for authorization. + #### The `passport:client` Command The simplest way to create a client is using the `passport:client` Artisan command. This command may be used to create your own clients for testing your OAuth2 functionality. When you run the `client` command, Passport will prompt you for more information about your client and will provide you with a client ID and secret: @@ -276,6 +277,7 @@ If you would like to allow multiple redirect URLs for your client, you may speci > {note} Any URL which contains commas must be encoded. + #### JSON API Since your users will not be able to utilize the `client` command, Passport provides a JSON API that you may use to create clients. This saves you the trouble of having to manually code controllers for creating, updating, and deleting clients. @@ -284,6 +286,7 @@ However, you will need to pair Passport's JSON API with your own frontend to pro The JSON API is guarded by the `web` and `auth` middleware; therefore, it may only be called from your own application. It is not able to be called from an external source. + #### `GET /oauth/clients` This route returns all of the clients for the authenticated user. This is primarily useful for listing all of the user's clients so that they may edit or delete them: @@ -293,6 +296,7 @@ This route returns all of the clients for the authenticated user. This is primar console.log(response.data); }); + #### `POST /oauth/clients` This route is used to create new clients. It requires two pieces of data: the client's `name` and a `redirect` URL. The `redirect` URL is where the user will be redirected after approving or denying a request for authorization. @@ -312,6 +316,7 @@ When a client is created, it will be issued a client ID and client secret. These // List errors on response... }); + #### `PUT /oauth/clients/{client-id}` This route is used to update clients. It requires two pieces of data: the client's `name` and a `redirect` URL. The `redirect` URL is where the user will be redirected after approving or denying a request for authorization. The route will return the updated client instance: @@ -329,6 +334,7 @@ This route is used to update clients. It requires two pieces of data: the client // List errors on response... }); + #### `DELETE /oauth/clients/{client-id}` This route is used to delete clients: @@ -341,6 +347,7 @@ This route is used to delete clients: ### Requesting Tokens + #### Redirecting For Authorization Once a client has been created, developers may use their client ID and secret to request an authorization code and access token from your application. First, the consuming application should make a redirect request to your application's `/oauth/authorize` route like so: @@ -361,6 +368,7 @@ Once a client has been created, developers may use their client ID and secret to > {tip} Remember, the `/oauth/authorize` route is already defined by the `Passport::routes` method. You do not need to manually define this route. + #### Approving The Request When receiving authorization requests, Passport will automatically display a template to the user allowing them to approve or deny the authorization request. If they approve the request, they will be redirected back to the `redirect_uri` that was specified by the consuming application. The `redirect_uri` must match the `redirect` URL that was specified when the client was created. @@ -390,6 +398,7 @@ Sometimes you may wish to skip the authorization prompt, such as when authorizin } } + #### Converting Authorization Codes To Access Tokens If the user approves the authorization request, they will be redirected back to the consuming application. The consumer should first verify the `state` parameter against the value that was stored prior to the redirect. If the state parameter matches the consumer should issue a `POST` request to your application to request an access token. The request should include the authorization code that was issued by your application when the user approved the authorization request. In this example, we'll use the Guzzle HTTP library to make the `POST` request: @@ -421,10 +430,12 @@ This `/oauth/token` route will return a JSON response containing `access_token`, > {tip} Like the `/oauth/authorize` route, the `/oauth/token` route is defined for you by the `Passport::routes` method. There is no need to manually define this route. By default, this route is throttled using the settings of the `ThrottleRequests` middleware. + #### JSON API Passport also includes a JSON API for managing authorized access tokens. You may pair this with your own frontend to offer your users a dashboard for managing access tokens. For convenience, we'll use [Axios](https://github.com/mzabriskie/axios) to demonstrate making HTTP requests to the endpoints. The JSON API is guarded by the `web` and `auth` middleware; therefore, it may only be called from your own application. + #### `GET /oauth/tokens` This route returns all of the authorized access tokens that the authenticated user has created. This is primarily useful for listing all of the user's tokens so that they can revoke them: @@ -434,6 +445,7 @@ This route returns all of the authorized access tokens that the authenticated us console.log(response.data); }); + #### `DELETE /oauth/tokens/{token-id}` This route may be used to revoke authorized access tokens and their related refresh tokens: @@ -517,6 +529,7 @@ Before your application can issue tokens via the authorization code grant with P ### Requesting Tokens + #### Code Verifier & Code Challenge As this authorization grant does not provide a client secret, developers will need to generate a combination of a code verifier and a code challenge in order to request a token. @@ -529,6 +542,7 @@ The code challenge should be a Base64 encoded string with URL and filename-safe $codeChallenge = strtr(rtrim($encoded, '='), '+/', '-_'); + #### Redirecting For Authorization Once a client has been created, you may use the client ID and the generated code verifier and code challenge to request an authorization code and access token from your application. First, the consuming application should make a redirect request to your application's `/oauth/authorize` route: @@ -555,6 +569,7 @@ Once a client has been created, you may use the client ID and the generated code return redirect('http://your-app.com/oauth/authorize?'.$query); }); + #### Converting Authorization Codes To Access Tokens If the user approves the authorization request, they will be redirected back to the consuming application. The consumer should verify the `state` parameter against the value that was stored prior to the redirect, as in the standard Authorization Code Grant. @@ -764,6 +779,7 @@ To restrict access to the route to specific scopes you may provide a comma-delim ... })->middleware('client:check-status,your-scope'); + ### Retrieving Tokens To retrieve a token using this grant type, make a request to the `oauth/token` endpoint: @@ -811,12 +827,14 @@ Once you have created a personal access client, you may issue tokens for a given // Creating a token with scopes... $token = $user->createToken('My Token', ['place-orders'])->accessToken; + #### JSON API Passport also includes a JSON API for managing personal access tokens. You may pair this with your own frontend to offer your users a dashboard for managing personal access tokens. Below, we'll review all of the API endpoints for managing personal access tokens. For convenience, we'll use [Axios](https://github.com/mzabriskie/axios) to demonstrate making HTTP requests to the endpoints. The JSON API is guarded by the `web` and `auth` middleware; therefore, it may only be called from your own application. It is not able to be called from an external source. + #### `GET /oauth/scopes` This route returns all of the [scopes](#token-scopes) defined for your application. You may use this route to list the scopes a user may assign to a personal access token: @@ -826,6 +844,7 @@ This route returns all of the [scopes](#token-scopes) defined for your applicati console.log(response.data); }); + #### `GET /oauth/personal-access-tokens` This route returns all of the personal access tokens that the authenticated user has created. This is primarily useful for listing all of the user's tokens so that they may edit or revoke them: @@ -835,6 +854,7 @@ This route returns all of the personal access tokens that the authenticated user console.log(response.data); }); + #### `POST /oauth/personal-access-tokens` This route creates new personal access tokens. It requires two pieces of data: the token's `name` and the `scopes` that should be assigned to the token: @@ -852,6 +872,7 @@ This route creates new personal access tokens. It requires two pieces of data: t // List errors on response... }); + #### `DELETE /oauth/personal-access-tokens/{token-id}` This route may be used to revoke personal access tokens: @@ -870,6 +891,7 @@ Passport includes an [authentication guard](/docs/{{version}}/authentication#add // })->middleware('auth:api'); + #### Multiple Authentication Guards If your application authenticates different types of users that perhaps use entirely different Eloquent models, you will likely need to define a guard configuration for each user provider type in your application. This allows you to protect requests intended for specific user providers. For example, given the following guard configuration the `config/auth.php` configuration file: @@ -936,6 +958,7 @@ If a client does not request any specific scopes, you may configure your Passpor ### Assigning Scopes To Tokens + #### When Requesting Authorization Codes When requesting an access token using the authorization code grant, consumers should specify their desired scopes as the `scope` query string parameter. The `scope` parameter should be a space-delimited list of scopes: @@ -951,6 +974,7 @@ When requesting an access token using the authorization code grant, consumers sh return redirect('http://your-app.com/oauth/authorize?'.$query); }); + #### When Issuing Personal Access Tokens If you are issuing personal access tokens using the `User` model's `createToken` method, you may pass the array of desired scopes as the second argument to the method: @@ -965,6 +989,7 @@ Passport includes two middleware that may be used to verify that an incoming req 'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class, 'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class, + #### Check For All Scopes The `scopes` middleware may be assigned to a route to verify that the incoming request's access token has *all* of the listed scopes: @@ -973,6 +998,7 @@ The `scopes` middleware may be assigned to a route to verify that the incoming r // Access token has both "check-status" and "place-orders" scopes... })->middleware(['auth:api', 'scopes:check-status,place-orders']); + #### Check For Any Scopes The `scope` middleware may be assigned to a route to verify that the incoming request's access token has *at least one* of the listed scopes: @@ -981,6 +1007,7 @@ The `scope` middleware may be assigned to a route to verify that the incoming re // Access token has either "check-status" or "place-orders" scope... })->middleware(['auth:api', 'scope:check-status,place-orders']); + #### Checking Scopes On A Token Instance Once an access token authenticated request has entered your application, you may still check if the token has a given scope using the `tokenCan` method on the authenticated `User` instance: @@ -993,6 +1020,7 @@ Once an access token authenticated request has entered your application, you may } }); + #### Additional Scope Methods The `scopeIds` method will return an array of all defined IDs / names: @@ -1032,6 +1060,7 @@ This Passport middleware will attach a `laravel_token` cookie to your outgoing r console.log(response.data); }); + #### Customizing The Cookie Name If needed, you can customize the `laravel_token` cookie's name using the `Passport::cookie` method. Typically, this method should be called from the `boot` method of your `AuthServiceProvider`: @@ -1050,6 +1079,7 @@ If needed, you can customize the `laravel_token` cookie's name using the `Passpo Passport::cookie('custom_name'); } + #### CSRF Protection When using this method of authentication, you will need to ensure a valid CSRF token header is included in your requests. The default Laravel JavaScript scaffolding includes an Axios instance, which will automatically use the encrypted `XSRF-TOKEN` cookie value to send a `X-XSRF-TOKEN` header on same-origin requests. diff --git a/passwords.md b/passwords.md index 96efbb4531e..d230c5f4ea7 100644 --- a/passwords.md +++ b/passwords.md @@ -37,6 +37,7 @@ To properly implement support for allowing users to reset their passwords, we wi ### Requesting The Password Reset Link + #### The Password Reset Link Request Form First, we will define the routes that are needed to request password reset links. To get started, we will define a route that returns a view with the password reset link request form: @@ -47,6 +48,7 @@ First, we will define the routes that are needed to request password reset links The view that is returned by this route should have a form containing an `email` field, which will allow the user to request a password reset link for a given email address. + #### Handling The Form Submission Next, we will define a route will handle the form request from the "forgot password" view. This route will be responsible for validating the email address and sending the password reset request to the corresponding user: @@ -75,6 +77,7 @@ The `sendResetLink` method returns a "status" slug. This status may be translate ### Resetting The Password + #### The Password Reset Form Next, we will define the routes necessary to actually reset the password once the user clicks on the password reset link that has been emailed to them and provides a new password. First, let's define the route that will display the reset password form that is displayed when the user clicks the reset password link. This route will receive a `token` parameter that we will use later to verify the password reset request: @@ -85,6 +88,7 @@ Next, we will define the routes necessary to actually reset the password once th The view that is returned by this route should have a form containing an `email` field, a `password` field, a `password_confirmation` field, and a hidden `token` field, which should contain the value of the secret token received by our route. + #### Handling The Form Submission Of course, we need to define a route to actually handle the password reset form submission. This route will be responsible for validating the incoming request and updating the user's password in the database: @@ -129,6 +133,7 @@ The `reset` method returns a "status" slug. This status may be translated using ## Customization + #### Reset Email Customization You may easily modify the notification class used to send the password reset link to the user. To get started, override the `sendPasswordResetNotification` method on your `User` model. Within this method, you may send the notification using any notification class you choose. The password reset `$token` is the first argument received by the method: diff --git a/providers.md b/providers.md index 5cab795feba..32468c79b92 100644 --- a/providers.md +++ b/providers.md @@ -58,6 +58,7 @@ Let's take a look at a basic service provider. Within any of your service provid This service provider only defines a `register` method, and uses that method to define an implementation of `Riak\Connection` in the service container. If you don't understand how the service container works, check out [its documentation](/docs/{{version}}/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: @@ -121,6 +122,7 @@ So, what if we need to register a [view composer](/docs/{{version}}/views#view-c } } + #### Boot Method Dependency Injection You may type-hint dependencies for your service provider's `boot` method. The [service container](/docs/{{version}}/container) will automatically inject any dependencies you need: diff --git a/queries.md b/queries.md index a1019b0499a..ada48ca3309 100644 --- a/queries.md +++ b/queries.md @@ -35,6 +35,7 @@ The Laravel query builder uses PDO parameter binding to protect your application ## 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: @@ -67,6 +68,7 @@ The `get` method returns an `Illuminate\Support\Collection` containing the resul 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 `first` method. This method will return a single `stdClass` object: @@ -83,6 +85,7 @@ To retrieve a single row by its `id` column value, use the `find` method: $user = DB::table('users')->find(3); + #### 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: @@ -148,6 +151,7 @@ You may combine these methods with other clauses: ->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: @@ -159,6 +163,7 @@ Instead of using the `count` method to determine if any records exist that match ## Selects + #### Specifying A Select Clause You may not always want to select all columns from a database table. Using the `select` method, you can specify a custom `select` clause for the query: @@ -193,6 +198,7 @@ Sometimes you may need to use a raw expression in a query. To create a raw expre 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 `addSelect(DB::raw(...))`. This method accepts an optional array of bindings as its second argument: @@ -201,6 +207,7 @@ The `selectRaw` method can be used in place of `addSelect(DB::raw(...))`. This m ->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: @@ -209,6 +216,7 @@ The `whereRaw` and `orWhereRaw` methods can be used to inject a raw `where` clau ->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: @@ -219,6 +227,7 @@ The `havingRaw` and `orHavingRaw` methods may be used to set a raw string as the ->havingRaw('SUM(price) > ?', [2500]) ->get(); + #### `orderByRaw` The `orderByRaw` method may be used to set a raw string as the value of the `order by` clause: @@ -227,6 +236,7 @@ The `orderByRaw` method may be used to set a raw string as the value of the `ord ->orderByRaw('updated_at - created_at DESC') ->get(); + ### `groupByRaw` The `groupByRaw` method may be used to set a raw string as the value of the `group by` clause: @@ -239,6 +249,7 @@ The `groupByRaw` method may be used to set a raw string as the value of the `gro ## 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: @@ -249,6 +260,7 @@ The query builder may also be used to write join statements. To perform a basic ->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 `join` method: @@ -261,6 +273,7 @@ If you would like to perform a "left join" or "right join" instead of an "inner ->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: @@ -269,6 +282,7 @@ To perform a "cross join" use the `crossJoin` method with the name of the table ->crossJoin('colors') ->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: @@ -288,6 +302,7 @@ If you would like to use a "where" style clause on your joins, you may use the ` }) ->get(); + #### Subquery Joins You may use the `joinSub`, `leftJoinSub`, and `rightJoinSub` methods to join a query to a subquery. Each of these methods receive three arguments: the subquery, its table alias, and a Closure that defines the related columns: @@ -320,6 +335,7 @@ The query builder also provides a quick way to "union" two queries together. For ## 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. @@ -353,6 +369,7 @@ You may also pass an array of conditions to the `where` function: ['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: @@ -374,6 +391,7 @@ If you need to group an "or" condition within parentheses, you may pass a Closur // SQL: select * from users where votes > 100 or (name = 'Abigail' and votes > 50) + #### Additional Where Clauses **whereBetween / orWhereBetween** @@ -568,6 +586,7 @@ You may use `whereJsonLength` to query JSON arrays by their length: ## 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`: @@ -583,6 +602,7 @@ If you need to sort by multiple columns, you may invoke `orderBy` as many times ->orderBy('email', 'asc') ->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: @@ -591,6 +611,7 @@ The `latest` and `oldest` methods allow you to easily order results by date. By ->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: @@ -599,6 +620,7 @@ The `inRandomOrder` method may be used to sort the query results randomly. For e ->inRandomOrder() ->first(); + #### reorder The `reorder` method allows you to remove all the existing orders and optionally apply a new order. For example, you can remove all the existing orders: @@ -613,6 +635,7 @@ To remove all existing orders and apply a new order, provide the column and dire $usersOrderedByEmail = $query->reorder('email', 'desc')->get(); + #### groupBy / having The `groupBy` and `having` methods may be used to group the query results. The `having` method's signature is similar to that of the `where` method: @@ -631,6 +654,7 @@ You may pass multiple arguments to the `groupBy` method to group by multiple col For more advanced `having` statements, see the [`havingRaw`](#raw-methods) 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: @@ -703,6 +727,7 @@ The `upsert` method will insert rows that do not exist and update the rows that > {note} All databases except SQL Server require the columns in the second argument of the `upsert` method to have a "primary" or "unique" index. + #### Auto-Incrementing IDs If the table has an auto-incrementing id, use the `insertGetId` method to insert a record and then retrieve the ID: @@ -722,6 +747,7 @@ In addition to inserting records into the database, the query builder can also u ->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. diff --git a/queues.md b/queues.md index 81423d5684c..5af394c6dd8 100644 --- a/queues.md +++ b/queues.md @@ -65,6 +65,7 @@ Some applications may not need to ever push jobs onto multiple queues, instead p ### 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: @@ -73,6 +74,7 @@ In order to use the `database` queue driver, you will need a database table to h 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. @@ -104,6 +106,7 @@ Adjusting this value based on your queue load can be more efficient than continu > {note} 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: @@ -188,6 +191,7 @@ If you would like to take total control over how the container injects dependenc > {note} 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. + #### Handling Relationships Because loaded relationships also get serialized, the serialized job string can become quite large. To prevent relations from being serialized, you can call the `withoutRelations` method on the model when setting a property value. This method will return an instance of the model with no loaded relationships: @@ -344,6 +348,7 @@ If you would like to delay the execution of a queued job, you may use the `delay > {note} The Amazon SQS queue service has a maximum delay time of 15 minutes. + #### Dispatching After The Response Is Sent To Browser Alternatively, the `dispatchAfterResponse` method delays dispatching a job until after the response is sent to the user's browser. This will still allow the user to begin using the application even though a queued job is still executing. This should typically only be used for jobs that take about a second, such as sending an email: @@ -415,6 +420,7 @@ In addition to chaining job class instances, you may also chain Closures: > {note} 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 connection and queue that should be used for the chained jobs, you may use the `onConnection` and `onQueue` 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: @@ -425,6 +431,7 @@ If you would like to specify the connection and queue that should be used for th new ReleasePodcast, ])->onConnection('redis')->onQueue('podcasts')->dispatch(); + #### Chain Failures When chaining jobs, you may use the `catch` method to specify a Closure that should be invoked if a job within the chain fails. The given callback will receive the exception instance that caused the job failure: @@ -443,6 +450,7 @@ When chaining jobs, you may use the `catch` method to specify a Closure that sho ### 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: @@ -471,6 +479,7 @@ By pushing jobs to different queues, you may "categorize" your queued jobs and e } } + #### 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: @@ -508,6 +517,7 @@ You may chain the `onConnection` and `onQueue` methods to specify the connection ### 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: @@ -547,6 +557,7 @@ As an alternative to defining how many times a job may be attempted before it fa > {tip} You may also define a `retryUntil` method on your queued event listeners. + #### Max Exceptions Sometimes you may wish to specify that a job may be attempted many times, but should fail if the retries are triggered by a given number of exceptions. To accomplish this, you may define a `maxExceptions` property on your job class: @@ -589,6 +600,7 @@ Sometimes you may wish to specify that a job may be attempted many times, but sh In this example, the job is released for ten seconds if the application is unable to obtain a Redis lock and will continue to be retried up to 25 times. However, the job will fail if three unhandled exceptions are thrown by the job. + #### Timeout > {note} The `pcntl` PHP extension must be installed in order to specify job timeouts. @@ -728,6 +740,7 @@ To dispatch a batch of jobs, you should use `batch` method of the `Bus` facade. return $batch->id; + #### Naming Batches Some tools such as Laravel Horizon and Laravel Telescope may provide more user-friendly debug information for batches if batches are named. To assign an arbitrary name to a batch, you may call the `name` method while defining the batch: @@ -738,6 +751,7 @@ Some tools such as Laravel Horizon and Laravel Telescope may provide more user-f // All jobs completed successfully... })->name('Process Podcasts')->dispatch(); + #### Batch Connection & Queue If you would like to specify the connection and queue that should be used for the batched jobs, you may use the `onConnection` and `onQueue` methods: @@ -748,6 +762,7 @@ If you would like to specify the connection and queue that should be used for th // All jobs completed successfully... })->onConnection('redis')->onQueue('podcasts')->dispatch(); + #### Chains Within Batches You may add a set of [chained jobs](#job-chaining) within a batch by placing the chained jobs within an array. For example, we may execute two job chains in parallel. Since the two chains are batched, we will be able to inspect the batch completion progress as a whole: @@ -834,6 +849,7 @@ The `Illuminate\Bus\Batch` method that is provided to batch completion callbacks // Indicates if the batch has been cancelled... $batch->cancelled(); + #### Returning Batches From Routes All `Illuminate\Bus\Batch` instances are JSON serializable, meaning you can return them directly from one of your application's routes to retrieve a JSON payload containing information about the batch, including its completion progress. To retrieve a batch by its ID, you may use the `Bus` facade's `findBatch` method: @@ -871,6 +887,7 @@ Sometimes you may need to cancel a given batch's execution. This can be accompli When a batch job fails, the `catch` callback (if assigned) will be invoked. This callback is only invoked for the job that fails within the batch. + #### Allowing Failures When a job within a batch fails, Laravel will automatically mark the batch as "cancelled". If you wish, you may disable this behavior so that a job failure does not automatically mark the batch as cancelled. This may be accomplished by calling the `allowFailures` method while dispatching the batch: @@ -881,6 +898,7 @@ When a job within a batch fails, Laravel will automatically mark the batch as "c // All jobs completed successfully... })->allowFailures()->dispatch(); + #### Retrying Failed Batch Jobs For convenience, Laravel provides a `queue:retry-batch` Artisan command that allows you to easily retry all of the failed jobs for a given batch. The `queue:retry-batch` command accepts the UUID of the batch whose failed jobs should be retried: @@ -923,6 +941,7 @@ Alternatively, you may run the `queue:listen` command. When using the `queue:lis php artisan queue:listen + #### 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: @@ -933,6 +952,7 @@ You may customize your queue worker even further by only processing particular q php artisan queue:work redis --queue=emails + #### Processing A Specified Number Of Jobs The `--once` option may be used to instruct the worker to only process a single job from the queue: @@ -943,12 +963,14 @@ The `--max-jobs` option may be used to instruct the worker to process the given php artisan queue:work --max-jobs=1000 + #### 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 + #### Processing Jobs For A Given Number Of Seconds The `--max-time` option may be used to instruct the worker to process jobs for the given number of seconds and then exit. This option may be useful when combined with [Supervisor](#supervisor-configuration) so that your workers are automatically restarted after processing jobs for a given amount of time: @@ -956,6 +978,7 @@ The `--max-time` option may be used to instruct the worker to process jobs for t // Process jobs for one hour and then exit... php artisan queue:work --max-time=3600 + #### 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. @@ -985,12 +1008,14 @@ This command will instruct all queue workers to gracefully "die" after they fini ### 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. > {note} 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](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/AboutVT.html) 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. The `--timeout` option removes frozen processes that have exceeded that specified time limit: @@ -1001,6 +1026,7 @@ The `retry_after` configuration option and the `--timeout` CLI option are differ > {note} 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 `--timeout` option 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. @@ -1010,6 +1036,7 @@ When jobs are available on the queue, the worker will keep processing jobs with ## Supervisor Configuration + #### 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: @@ -1018,6 +1045,7 @@ Supervisor is a process monitor for the Linux operating system, and will automat > {tip} If configuring Supervisor yourself sounds overwhelming, consider using [Laravel Forge](https://forge.laravel.com), which will automatically install and configure Supervisor for your Laravel projects. + #### Configuring Supervisor Supervisor configuration files are typically stored in the `/etc/supervisor/conf.d` directory. 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: @@ -1037,6 +1065,7 @@ In this example, the `numprocs` directive will instruct Supervisor to run 8 `que > {note} You should ensure that the value of `stopwaitsecs` is greater than the number of seconds consumed by your longest running job. Otherwise, Supervisor may kill the job before it is finished processing. + #### Starting Supervisor Once the configuration file has been created, you may update the Supervisor configuration and start the processes using the following commands: diff --git a/redirects.md b/redirects.md index 82c00739378..4a7d022887a 100644 --- a/redirects.md +++ b/redirects.md @@ -35,6 +35,7 @@ If your route has parameters, you may pass them as the second argument to the `r return redirect()->route('profile', ['id' => 1]); + #### Populating Parameters Via Eloquent Models 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: diff --git a/redis.md b/redis.md index 801eeba7075..46eab443d9e 100644 --- a/redis.md +++ b/redis.md @@ -60,6 +60,7 @@ The default server configuration should suffice for development. However, you ar ], + #### Configuring The Connection Scheme By default, Redis clients will use the `tcp` scheme when connecting to your Redis servers; however, you may use TLS / SSL encryption by specifying a `scheme` configuration option in your Redis server configuration: @@ -78,6 +79,7 @@ By default, Redis clients will use the `tcp` scheme when connecting to your Redi ], + #### Configuring Clusters If your application is utilizing a cluster of Redis servers, you should define these clusters within a `clusters` key of your Redis configuration: @@ -167,6 +169,7 @@ In addition to the default `host`, `port`, `database`, and `password` server con ], ], + #### The Redis Facade To avoid class naming collisions with the Redis PHP extension itself, you will need to delete or rename the `Illuminate\Support\Facades\Redis` facade alias from your `app` configuration file's `aliases` array. Generally, you should remove this alias entirely and only reference the facade by its fully qualified class name while using the Redis PHP extension. @@ -209,6 +212,7 @@ Alternatively, you may also pass commands to the server using the `command` meth $values = Redis::command('lrange', ['name', 5, 10]); + #### Using Multiple Redis Connections You may get a Redis instance by calling the `Redis::connection` method: @@ -281,6 +285,7 @@ Now we may publish messages to the channel using the `publish` method: Redis::publish('test-channel', json_encode(['foo' => 'bar'])); }); + #### Wildcard Subscriptions Using the `psubscribe` method, you may subscribe to a wildcard channel, which may be useful for catching all messages on all channels. The `$channel` name will be passed as the second argument to the provided callback `Closure`: diff --git a/releases.md b/releases.md index bf710908c8f..9e35f78f402 100644 --- a/releases.md +++ b/releases.md @@ -27,6 +27,7 @@ For LTS releases, such as Laravel 6, bug fixes are provided for 2 years and secu Laravel 8 continues the improvements made in Laravel 7.x by introducing Laravel Jetstream, model factory classes, migration squashing, job batching, improved rate limiting, queue improvements, dynamic Blade components, Tailwind pagination views, time testing helpers, improvements to `artisan serve`, event listener improvements, and a variety of other bug fixes and usability improvements. + ### Laravel Jetstream _Laravel Jetstream was written by [Taylor Otwell](https://github.com/taylorotwell)_. @@ -35,10 +36,12 @@ _Laravel Jetstream was written by [Taylor Otwell](https://github.com/taylorotwel Jetstream is designed using [Tailwind CSS](https://tailwindcss.com) and offers your choice of [Livewire](https://laravel-livewire.com) or [Inertia](https://inertiajs.com) scaffolding. + ### Models Directory By overwhelming community demand, the default Laravel application skeleton now contains an `app/Models` directory. We hope you enjoy this new home for your Eloquent models! All relevant generator commands have been updated to assume models exist within the `app/Models` directory if it exists. If the directory does not exist, the framework will assume your models should be placed within the `app` directory. + ### Model Factory Classes _Model factory classes were contributed by [Taylor Otwell](https://github.com/taylorotwell)_. @@ -119,6 +122,7 @@ To ease the upgrade process, the [laravel/legacy-factories](https://github.com/l Laravel's re-written factories contain many more features that we think you will love. To learn more about model factories, please consult the [database testing documentation](/docs/{{version}}/database-testing#creating-factories). + ### Migration Squashing _Migration squashing was contributed by [Taylor Otwell](https://github.com/taylorotwell)_. @@ -132,6 +136,7 @@ As you build your application, you may accumulate more and more migrations over When you execute this command, Laravel will write a "schema" file to your `database/schema` directory. Now, when you attempt to migrate your database and no other migrations have been executed, Laravel will execute the schema file's SQL first. After executing the schema file's commands, Laravel will execute any remaining migrations that were not part of the schema dump. + ### Job Batching _Job batching was contributed by [Taylor Otwell](https://github.com/taylorotwell) & [Mohamed Said](https://github.com/themsaid)_. @@ -164,6 +169,7 @@ The new `batch` method of the `Bus` facade may be used to dispatch a batch of jo To learn more about job batching, please consult the [queue documentation](/docs/{{version}}/queues#job-batching). + ### Improved Rate Limiting _Rate limiting improvements were contributed by [Taylor Otwell](https://github.com/taylorotwell)_. @@ -209,6 +215,7 @@ Rate limiters may be attached to routes or route groups using the `throttle` [mi To learn more about rate limiting, please consult the [routing documentation](/docs/{{version}}/routing#rate-limiting). + ### Improved Maintenance Mode _Maintenance mode improvements were contributed by [Taylor Otwell](https://github.com/taylorotwell) with inspiration from [Spatie](https://spatie.be)_. @@ -225,6 +232,7 @@ After placing the application in maintenance mode, you may navigate to the appli When accessing this hidden route, you will then be redirected to the `/` route of the application. Once the cookie has been issued to your browser, you will be able to browse the application normally as if it was not in maintenance mode. + #### Pre-Rendering The Maintenance Mode View If you utilize the `php artisan down` command during deployment, your users may still occasionally encounter errors if they access the application while your Composer dependencies or other infrastructure components are updating. This occurs because a significant part of the Laravel framework must boot in order to determine your application is in maintenance mode and render the maintenance mode view using the templating engine. @@ -233,6 +241,7 @@ For this reason, Laravel now allows you to pre-render a maintenance mode view th php artisan down --render="errors::503" + ### Closure Dispatch / Chain `catch` _Catch improvements were contributed by [Mohamed Said](https://github.com/themsaid)_. @@ -247,6 +256,7 @@ Using the new `catch` method, you may now provide a Closure that should be execu // This job has failed... }); + ### Dynamic Blade Components _Dynamic Blade components were contributed by [Taylor Otwell](https://github.com/taylorotwell)_. @@ -257,6 +267,7 @@ Sometimes you may need to render a component but not know which component should To learn more about Blade components, please consult the [Blade documentation](/docs/{{version}}/blade#components). + ### Event Listener Improvements _Event listener improvements were contributed by [Taylor Otwell](https://github.com/taylorotwell)_. @@ -299,6 +310,7 @@ If you would like to handle anonymous queued listener failures, you may provide // The queued listener failed... })); + ### Time Testing Helpers _Time testing helpers were contributed by [Taylor Otwell](https://github.com/taylorotwell) with inspiration from Ruby on Rails_. @@ -326,16 +338,19 @@ When testing, you may occasionally need to modify the time returned by helpers s $this->travelBack(); } + ### Artisan `serve` Improvements _Artisan `serve` improvements were contributed by [Taylor Otwell](https://github.com/taylorotwell)_. The Artisan `serve` command has been improved with automatic reloading when environment variable changes are detected within your local `.env` file. Previously, the command had to be manually stopped and restarted. + ### Tailwind Pagination Views The Laravel paginator has been updated to use the [Tailwind CSS](https://tailwindcss.com) framework by default. Tailwind CSS is a highly customizable, low-level CSS framework that gives you all of the building blocks you need to build bespoke designs without any annoying opinionated styles you have to fight to override. Of course, Bootstrap 3 and 4 views remain available as well. + ### Routing Namespace Updates In previous releases of Laravel, the `RouteServiceProvider` contained a `$namespace` property. This property's value would automatically be prefixed onto controller route definitions and calls to the `action` helper / `URL::action` method. In Laravel 8.x, this property is `null` by default. This means that no automatic namespace prefixing will be done by Laravel. Therefore, in new Laravel 8.x applications, controller route definitions should be defined using standard PHP callable syntax: diff --git a/requests.md b/requests.md index 6b587f71ba6..f0642f1b53d 100644 --- a/requests.md +++ b/requests.md @@ -39,6 +39,7 @@ To obtain an instance of the current HTTP request via dependency injection, you } } + #### Dependency Injection & Route Parameters If your controller method is also expecting input from a route parameter you should list your route parameters after your other dependencies. For example, if your route is defined like so: @@ -70,6 +71,7 @@ You may still type-hint the `Illuminate\Http\Request` and access your route para } } + #### Accessing The Request Via Route Closures You may also type-hint the `Illuminate\Http\Request` class on a route Closure. The service container will automatically inject the incoming request into the Closure when it is executed: @@ -85,6 +87,7 @@ You may also type-hint the `Illuminate\Http\Request` class on a route Closure. T 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. We will discuss a few of the most important methods below. + #### 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`: @@ -97,6 +100,7 @@ The `is` method allows you to verify that the incoming request path matches a gi // } + #### Retrieving The Request URL To retrieve the full URL for the incoming request you may use the `url` or `fullUrl` methods. The `url` method will return the URL without the query string, while the `fullUrl` method includes the query string: @@ -107,6 +111,7 @@ To retrieve the full URL for the incoming request you may use the `url` or `full // 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 `isMethod` method to verify that the HTTP verb matches a given string: @@ -145,12 +150,14 @@ If you would like to disable this behavior, you may remove the two middleware fr ## Retrieving Input + #### Retrieving All Input Data You may also retrieve all of the input data as an `array` using the `all` method: $input = $request->all(); + #### 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: @@ -171,6 +178,7 @@ You may call the `input` method without any arguments in order to retrieve all o $input = $request->input(); + #### Retrieving Input From The Query String While the `input` method retrieves values from the entire request payload (including the query string), the `query` method will only retrieve values from the query string: @@ -185,6 +193,7 @@ You may call the `query` method without any arguments in order to retrieve all o $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: @@ -193,18 +202,21 @@ You may also access user input using dynamic properties on the `Illuminate\Http\ 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 Boolean Input Values When dealing with HTML elements like checkboxes, your application may receive "truthy" values that are actually strings. For example, "true" or "on". For convenience, you may use the `boolean` method to retrieve these values as booleans. The `boolean` method returns `true` for 1, "1", true, "true", "on", and "yes". All other values will return `false`: $archived = $request->boolean('archived'); + #### Retrieving A Portion Of The Input Data If you need to retrieve a subset of the input data, you may use the `only` and `except` methods. Both of these methods accept a single `array` or a dynamic list of arguments: @@ -219,6 +231,7 @@ If you need to retrieve a subset of the input data, you may use the `only` and ` > {tip} 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: @@ -268,6 +281,7 @@ To determine if a given key is absent from the request, you may use the `missing 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](/docs/{{version}}/validation), 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](/docs/{{version}}/session) so that it is available during the user's next request to the application: @@ -280,6 +294,7 @@ You may also use the `flashOnly` and `flashExcept` methods to flash a subset of $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: @@ -290,6 +305,7 @@ Since you often will want to flash input to the session and then redirect to the $request->except('password') ); + #### Retrieving Old Input To retrieve flashed input from the previous request, use the `old` method on the `Request` instance. The `old` method will pull the previously flashed input data from the [session](/docs/{{version}}/session): @@ -303,6 +319,7 @@ Laravel also provides a global `old` helper. If you are displaying old input wit ### Cookies + #### 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 `cookie` method on an `Illuminate\Http\Request` instance: @@ -315,6 +332,7 @@ Alternatively, you may use the `Cookie` facade to access cookie values: $value = Cookie::get('name'); + #### 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: @@ -335,6 +353,7 @@ Alternatively, you can use the `Cookie` facade to "queue" cookies for attachment 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 `cookie` helper. This cookie will not be sent back to the client unless it is attached to a response instance: @@ -343,6 +362,7 @@ If you would like to generate a `Symfony\Component\HttpFoundation\Cookie` instan return response('Hello World')->cookie($cookie); + #### Expiring Cookies Early You may remove a cookie by expiring it via the `forget` method of the `Cookie` facade: @@ -373,6 +393,7 @@ You may determine if a file is present on the request using the `hasFile` method // } + #### 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: @@ -381,6 +402,7 @@ In addition to checking if the file is present, you may verify that there were n // } + #### 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: @@ -389,6 +411,7 @@ The `UploadedFile` class also contains methods for accessing the file's fully-qu $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](https://api.symfony.com/master/Symfony/Component/HttpFoundation/File/UploadedFile.html) for more information regarding these methods. @@ -448,6 +471,7 @@ To solve this, you may use the `App\Http\Middleware\TrustProxies` middleware tha > {tip} If you are using AWS Elastic Load Balancing, your `$headers` value 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](https://symfony.com/doc/current/deployment/proxies.html). + #### 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: diff --git a/responses.md b/responses.md index 955c35c4f35..e96ba0db311 100644 --- a/responses.md +++ b/responses.md @@ -19,6 +19,7 @@ ## Creating 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: @@ -35,6 +36,7 @@ In addition to returning strings from your routes and controllers, you may also > {tip} Did you know you can also return [Eloquent collections](/docs/{{version}}/eloquent-collections) from your routes or controllers? They will automatically be converted to JSON. Give it a shot! + #### 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](/docs/{{version}}/views). @@ -65,6 +67,7 @@ Or, you may use the `withHeaders` method to specify an array of headers to be ad 'X-Header-Two' => 'Header Value', ]); + #### Cache Control Middleware Laravel includes a `cache.headers` middleware, which may be used to quickly set the `Cache-Control` header for a group of routes. If `etag` is specified in the list of directives, an MD5 hash of the response content will automatically be set as the ETag identifier: @@ -142,6 +145,7 @@ If your route has parameters, you may pass them as the second argument to the `r return redirect()->route('profile', ['id' => 1]); + #### Populating Parameters Via Eloquent Models 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: @@ -248,6 +252,7 @@ The `download` method may be used to generate a response that forces the user's > {note} 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: diff --git a/routing.md b/routing.md index 445e08340c7..ca87ce4d27f 100644 --- a/routing.md +++ b/routing.md @@ -33,6 +33,7 @@ The most basic Laravel routes accept a URI and a `Closure`, providing a very sim return 'Hello World'; }); + #### The Default Route Files All Laravel routes are defined in your route files, which are located in the `routes` directory. These files are automatically loaded by the framework. The `routes/web.php` file defines routes that are for your web interface. These routes are assigned the `web` middleware group, which provides features like session state and CSRF protection. The routes in `routes/api.php` are stateless and are assigned the `api` middleware group. @@ -45,6 +46,7 @@ For most applications, you will begin by defining routes in your `routes/web.php Routes defined in the `routes/api.php` file are nested within a route group by the `RouteServiceProvider`. Within this group, the `/api` URI prefix is automatically applied so you do not need to manually apply it to every route in the file. You may modify the prefix and other route group options by modifying your `RouteServiceProvider` class. + #### Available Router Methods The router allows you to register routes that respond to any HTTP verb: @@ -66,6 +68,7 @@ Sometimes you may need to register a route that responds to multiple HTTP verbs. // }); + #### CSRF Protection Any HTML forms pointing to `POST`, `PUT`, `PATCH`, or `DELETE` routes that are defined in the `web` routes file should include a CSRF token field. Otherwise, the request will be rejected. You can read more about CSRF protection in the [CSRF documentation](/docs/{{version}}/csrf): @@ -196,6 +199,7 @@ You may also specify route names for controller actions: > {note} Route names should always be unique. + #### 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: @@ -226,6 +230,7 @@ If you pass additional parameters in the array, those key / value pairs will aut > {tip} Sometimes, you may wish to specify request-wide default values for URL parameters, such as the current locale. To accomplish this, you may use the [`URL::defaults` method](/docs/{{version}}/urls#default-values). + #### 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: @@ -319,6 +324,7 @@ Laravel automatically resolves Eloquent models defined in routes or controller a Since the `$user` variable is type-hinted as the `App\Models\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 Sometimes you may wish to resolve Eloquent models using a column other than `id`. To do so, you may specify the column in the route parameter definition: @@ -341,6 +347,7 @@ Sometimes, when implicitly binding multiple Eloquent models in a single route de When using a custom keyed implicit binding as a nested route parameter, Laravel will automatically scope the query to retrieve the nested model by its parent using conventions to guess the relationship name on the parent. In this case, it will be assumed that the `User` model has a relationship named `posts` (the plural of the route parameter name) which can be used to retrieve the `Post` model. + #### Customizing The Default Key Name If you would like model binding to use a default database column other than `id` when retrieving a given model class, you may override the `getRouteKeyName` method on the Eloquent model: @@ -382,6 +389,7 @@ Since we have bound all `{user}` parameters to the `App\Models\User` model, a `U 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: @@ -458,6 +466,7 @@ Since rate limiter callbacks receive the incoming HTTP request instance, you may : Limit::perMinute(100); }); + #### Segmenting Rate Limits Sometimes you may wish to segment rate limits by some arbitrary value. For example, you may wish to allow users to access a given route 100 times per minute per IP address. To accomplish this, you may use the `by` method when building your rate limit: @@ -468,6 +477,7 @@ Sometimes you may wish to segment rate limits by some arbitrary value. For examp : Limit::perMinute(100)->by($request->ip()); }); + #### Multiple Rate Limits If needed, you may return an array of rate limits for a given rate limiter configuration. Each rate limit will be evaluated for the route based on the order they are placed within the array: @@ -494,6 +504,7 @@ Rate limiters may be attached to routes or route groups using the `throttle` [mi }); }); + #### Throttling With Redis Typically, the `throttle` middleware is mapped to the `Illuminate\Routing\Middleware\ThrottleRequests` class. This mapping is defined in your application's HTTP kernel. However, if you are using Redis as your application's cache driver, you may wish to change this mapping to use the `Illuminate\Routing\Middleware\ThrottleRequestsWithRedis` class. This class is more efficient at managing rate limiting using Redis: diff --git a/sanctum.md b/sanctum.md index b2e1697af0e..7af3f0e5fa9 100644 --- a/sanctum.md +++ b/sanctum.md @@ -29,12 +29,14 @@ Laravel Sanctum provides a featherweight authentication system for SPAs (single Laravel Sanctum exists to solve two separate problems. + #### API Tokens First, it is a simple package to issue API tokens to your users without the complication of OAuth. This feature is inspired by GitHub "access tokens". For example, imagine the "account settings" of your application has a screen where a user may generate an API token for their account. You may use Sanctum to generate and manage those tokens. These tokens typically have a very long expiration time (years), but may be manually revoked by the user at anytime. Laravel Sanctum offers this feature by storing user API tokens in a single database table and authenticating incoming requests via the `Authorization` header which should contain a valid API token. + #### SPA Authentication Second, Sanctum exists to offer a simple way to authenticate single page applications (SPAs) that need to communicate with a Laravel powered API. These SPAs might exist in the same repository as your Laravel application or might be an entirely separate repository, such as a SPA created using Vue CLI. @@ -66,6 +68,7 @@ Next, if you plan to utilize Sanctum to authenticate an SPA, you should add Sanc \Illuminate\Routing\Middleware\SubstituteBindings::class, ], + #### Migration Customization If you are not going to use Sanctum's default migrations, you should call the `Sanctum::ignoreMigrations` method in the `register` method of your `AppServiceProvider`. You may export the default migrations using `php artisan vendor:publish --tag=sanctum-migrations`. @@ -151,12 +154,14 @@ For this feature, Sanctum does not use tokens of any kind. Instead, Sanctum uses ### Configuration + #### Configuring Your First-Party Domains First, you should configure which domains your SPA will be making requests from. You may configure these domains using the `stateful` configuration option in your `sanctum` configuration file. This configuration setting determines which domains will maintain "stateful" authentication using Laravel session cookies when making requests to your API. > {note} If you are accessing your application via a URL that includes the port (`127.0.0.1:8000`), you should ensure that you include the port number with the domain. + #### Sanctum Middleware Next, you should add Sanctum's middleware to your `api` middleware group within your `app/Http/Kernel.php` file. This middleware is responsible for ensuring that incoming requests from your SPA can authenticate using Laravel's session cookies, while still allowing requests from third parties or mobile applications to authenticate using API tokens: diff --git a/scheduling.md b/scheduling.md index 229df9116ed..a823babeb7a 100644 --- a/scheduling.md +++ b/scheduling.md @@ -21,6 +21,7 @@ In the past, you may have generated a Cron entry for each task you needed to sch 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](https://forge.laravel.com) which can manage the Cron entries for you: @@ -29,6 +30,7 @@ When using the scheduler, you only need to add the following Cron entry to your 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. + ### Starting The Scheduler Locally Typically, you would not add a scheduler Cron entry to your local development machine. Instead you may use the `schedule:work` Artisan command. This command will run in the foreground and invoke the scheduler every minute until you exit the command: @@ -172,6 +174,7 @@ Method | Description `->when(Closure);` | Limit the task based on a truth test `->environments($env);` | Limit the task to specific environments + #### Day Constraints The `days` method may be used to limit the execution of a task to specific days of the week. For example, you may schedule a command to run hourly on Sundays and Wednesdays: @@ -180,6 +183,7 @@ The `days` method may be used to limit the execution of a task to specific days ->hourly() ->days([0, 3]); + #### Between Time Constraints The `between` method may be used to limit the execution of a task based on the time of day: @@ -194,6 +198,7 @@ Similarly, the `unlessBetween` method can be used to exclude the execution of a ->hourly() ->unlessBetween('23:00', '4:00'); + #### Truth Test Constraints The `when` method may be used to limit the execution of a task based on the result of a given truth test. In other words, if the given `Closure` returns `true`, the task will execute as long as no other constraining conditions prevent the task from running: @@ -210,6 +215,7 @@ The `skip` method may be seen as the inverse of `when`. If the `skip` method ret When using chained `when` methods, the scheduled command will only execute if all `when` conditions return `true`. + #### Environment Constraints The `environments` method may be used to execute tasks only on the given environments: @@ -354,6 +360,7 @@ If output is available from your command, you may access it in your `after`, `on // The task failed... }); + #### Pinging URLs Using the `pingBefore` and `thenPing` methods, the scheduler can automatically ping a given URL before or after a task is complete. This method is useful for notifying an external service, such as [Laravel Envoyer](https://envoyer.io), that your scheduled task is commencing or has finished execution: diff --git a/scout.md b/scout.md index d072e3b3972..099b0eb824c 100644 --- a/scout.md +++ b/scout.md @@ -68,6 +68,7 @@ Once you have configured a queue driver, set the value of the `queue` option in ### Driver Prerequisites + #### Algolia When using the Algolia driver, you should configure your Algolia `id` and `secret` credentials in your `config/scout.php` configuration file. Once your credentials have been configured, you will also need to install the Algolia PHP SDK via the Composer package manager: @@ -206,6 +207,7 @@ Once you have added the `Laravel\Scout\Searchable` trait to a model, all you nee $order->save(); + #### Adding Via Query If you would like to add a collection of models to your search index via an Eloquent query, you may chain the `searchable` method onto an Eloquent query. The `searchable` method will [chunk the results](/docs/{{version}}/eloquent#chunking-results) of the query and add the records to your search index. Again, if you have configured Scout to use queues, all of the chunks will be added in the background by your queue workers: @@ -385,6 +387,7 @@ If you need to customize the search behavior of an engine you may pass a callbac ## Custom Engines + #### Writing The Engine If one of the built-in Scout search engines doesn't fit your needs, you may write your own custom engine and register it with Scout. Your engine should extend the `Laravel\Scout\Engines\Engine` abstract class. This abstract class contains eight methods your custom engine must implement: @@ -402,6 +405,7 @@ If one of the built-in Scout search engines doesn't fit your needs, you may writ You may find it helpful to review the implementations of these methods on the `Laravel\Scout\Engines\AlgoliaEngine` class. This class will provide you with a good starting point for learning how to implement each of these methods in your own engine. + #### Registering The Engine Once you have written your custom engine, you may register it with Scout using the `extend` method of the Scout engine manager. You should call the `extend` method from the `boot` method of your `AppServiceProvider` or any other service provider used by your application. For example, if you have written a `MySqlSearchEngine`, you may register it like so: diff --git a/session.md b/session.md index 0251b8badc4..cce9ae78d8f 100644 --- a/session.md +++ b/session.md @@ -39,6 +39,7 @@ The session `driver` configuration option defines where session data will be sto ### 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: @@ -58,6 +59,7 @@ You may use the `session:table` Artisan command to generate this migration: php artisan migrate + #### Redis Before using Redis sessions with Laravel, you will need to either install the PhpRedis PHP extension via PECL or install the `predis/predis` package (~1.0) via Composer. For more information on configuring Redis, consult its [Laravel documentation page](/docs/{{version}}/redis#configuration). @@ -104,6 +106,7 @@ When you retrieve an item from the session, you may also pass a default value as 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: @@ -121,12 +124,14 @@ You may also use the global `session` PHP function to retrieve and store data in > {tip} There is little practical difference between using the session via an HTTP request instance versus using the global `session` helper. Both methods are [testable](/docs/{{version}}/testing) via the `assertSessionHas` method which is available in all of your test cases. + #### 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 `has` method returns `true` if the item is present and is not `null`: @@ -152,12 +157,14 @@ To store data in the session, you will typically use the `put` method or the `se // 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: diff --git a/socialite.md b/socialite.md index 9e1cc7b4a22..defb14c93d9 100644 --- a/socialite.md +++ b/socialite.md @@ -146,12 +146,14 @@ Once you have a user instance, you can grab a few more details about the user: $user->getEmail(); $user->getAvatar(); + #### Retrieving User Details From A Token (OAuth2) If you already have a valid access token for a user, you can retrieve their details using the `userFromToken` method: $user = Socialite::driver('github')->userFromToken($token); + #### Retrieving User Details From A Token And Secret (OAuth1) If you already have a valid pair of token / secret for a user, you can retrieve their details using the `userFromTokenAndSecret` method: diff --git a/telescope.md b/telescope.md index ee9489023b9..9738461f3ad 100644 --- a/telescope.md +++ b/telescope.md @@ -53,6 +53,7 @@ After installing Telescope, publish its assets using the `telescope:install` Art php artisan migrate + ### Installing Only In Specific Environments If you plan to only use Telescope to assist your local development, you may install Telescope using the `--dev` flag: diff --git a/upgrade.md b/upgrade.md index 5c101d14b95..61420335750 100644 --- a/upgrade.md +++ b/upgrade.md @@ -28,6 +28,7 @@ ## Upgrading To 8.0 From 7.x + #### Estimated Upgrade Time: 15 Minutes > {note} We attempt to document every possible breaking change. Since some of these breaking changes are in obscure parts of the framework only a portion of these changes may actually affect your application. @@ -66,8 +67,10 @@ In addition, the Laravel installer has been updated to support `composer create- Finally, examine any other third-party packages consumed by your application and verify you are using the proper version for Laravel 8 support. + ### Collections + #### The `isset` Method **Likelihood Of Impact: Low** @@ -82,6 +85,7 @@ To be consistent with typical PHP behavior, the `offsetExists` method of `Illumi // Laravel 8.x - false isset($collection[0]); + ### Database @@ -123,6 +127,7 @@ Next, in your `composer.json` file, remove `classmap` block from the `autoload` } }, + ### Eloquent @@ -134,6 +139,7 @@ Laravel's [model factories](/docs/{{version}}/database-testing#creating-factorie composer require laravel/legacy-factories + #### The `Castable` Interface **Likelihood Of Impact: Low** @@ -142,14 +148,17 @@ The `castUsing` method of the `Castable` interface has been updated to accept an public static function castUsing(array $arguments); + #### Increment / Decrement Events **Likelihood Of Impact: Low** Proper "update" and "save" related model events will now be dispatched when executing the `increment` or `decrement` methods on Eloquent model instances. + ### Events + #### The `Dispatcher` Contract **Likelihood Of Impact: Low** @@ -158,6 +167,7 @@ The `listen` method of the `Illuminate\Contracts\Events\Dispatcher` contract has public function listen($events, $listener = null); + ### Framework @@ -180,26 +190,31 @@ The [maintenance mode](/docs/{{version}}/configuration#maintenance-mode) feature The `--message` option of the `php artisan down` command has been removed. As an alternative, consider [pre-rendering your maintenance mode views](/docs/{{version}}/configuration#maintenance-mode) with the message of your choice. + #### Manager `$app` Property **Likelihood Of Impact: Low** The previously deprecated `$app` property of the `Illuminate\Support\Manager` class has been removed. If you were relying on this property, you should use the `$container` property instead. + #### The `elixir` Helper **Likelihood Of Impact: Low** The previously deprecated `elixir` helper has been removed. Applications still using this method are encouraged to upgrade to [Laravel Mix](https://github.com/JeffreyWay/laravel-mix). + ### Mail + #### The `sendNow` Method **Likelihood Of Impact: Low** The previously deprecated `sendNow` method has been removed. Instead, please use the `send` method. + ### Pagination @@ -213,6 +228,7 @@ The paginator now uses the [Tailwind CSS framework](https://tailwindcss.com) for Paginator::useBootstrap(); + ### Queue @@ -259,8 +275,10 @@ If you plan to use the [job batching](/docs/{{version}}/queues#job-batching) fea Next, the `failed.driver` configuration option within your `queue` configuration file should be updated to `database-uuids`. + ### Routing + #### Automatic Controller Namespace Prefixing **Likelihood Of Impact: Optional** @@ -335,16 +353,20 @@ If you would like to continue using the original auto-prefixed controller routin } } + ### Scheduling + #### The `cron-expression` Library **Likelihood Of Impact: Low** Laravel's dependency on `dragonmantank/cron-expression` has been updated from `2.x` to `3.x`. This should not cause any breaking change in your application unless you are interacting with the `cron-expression` library directly. If you are interacting with this library directly, please review its [change log](https://github.com/dragonmantank/cron-expression/blob/master/CHANGELOG.md). + ### Session + #### The `Session` Contract **Likelihood Of Impact: Low** @@ -360,6 +382,7 @@ The `Illuminate\Contracts\Session\Session` contract has received a new `pull` me */ public function pull($key, $default = null); + ### Testing @@ -376,8 +399,10 @@ The `decodeResponseJson` method that belongs to the `Illuminate\Testing\TestResp The `assertExactJson` method now requires numeric keys of compared arrays to match and be in the same order. If you would like to compare JSON against an array without requiring numerically keyed arrays to have the same order, you may use the `assertSimilarJson` method instead. + ### Validation + ### Database Rule Connections **Likelihood Of Impact: Low** diff --git a/urls.md b/urls.md index b4d795a2f6a..cd9c922630f 100644 --- a/urls.md +++ b/urls.md @@ -102,6 +102,7 @@ If you would like to generate a temporary signed route URL that expires, you may '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`: @@ -178,6 +179,7 @@ It is cumbersome to always pass the `locale` every time you call the `route` hel 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. + #### URL Defaults & Middleware Priority Setting URL default values can interfere with Laravel's handling of implicit model bindings. Therefore, you should [prioritize your middleware](https://laravel.com/docs/{{version}}/middleware#sorting-middleware) that set URL defaults to be executed before Laravel's own `SubstituteBindings` middleware. You can accomplish this by making sure your middleware occurs before the `SubstituteBindings` middleware within the `$middlewarePriority` property of your application's HTTP kernel. diff --git a/valet.md b/valet.md index 8f739628dcf..0e4258885c2 100644 --- a/valet.md +++ b/valet.md @@ -87,10 +87,12 @@ Once Valet is installed, try pinging any `*.test` domain on your terminal using Valet will automatically start its daemon each time your machine boots. There is no need to run `valet start` or `valet install` ever again once the initial Valet installation is complete. + #### Database If you need a database, try MySQL by running `brew install mysql@5.7` on your command line. Once MySQL has been installed, you may start it using the `brew services start mysql@5.7` command. You can then connect to the database at `127.0.0.1` using the `root` username and an empty string for the password. + #### PHP Versions Valet allows you to switch PHP versions using the `valet use php@version` command. Valet will install the specified PHP version via Brew if it is not already installed: @@ -101,6 +103,7 @@ Valet allows you to switch PHP versions using the `valet use php@version` comman > {note} Valet only serves one PHP version at a time, even if you have multiple PHP versions installed. + #### Resetting Your Installation If you are having trouble getting your Valet installation to run properly, executing the `composer global update` command followed by `valet install` will reset your installation and can solve a variety of problems. In rare cases it may be necessary to "hard reset" Valet by executing `valet uninstall --force` followed by `valet install`. @@ -156,6 +159,7 @@ To "unsecure" a site and revert back to serving its traffic over plain HTTP, use Valet even includes a command to share your local sites with the world, providing an easy way to test your site on mobile devices or share it with team members and clients. No additional software installation is required once Valet is installed. + ### Sharing Sites Via Ngrok To share a site, navigate to the site's directory in your terminal and run the `valet share` command. A publicly accessible URL will be inserted into your clipboard and is ready to paste directly into your browser or share with your team. @@ -164,12 +168,14 @@ To stop sharing your site, hit `Control + C` to cancel the process. > {tip} You may pass additional parameters to the share command, such as `valet share --region=eu`. For more information, consult the [ngrok documentation](https://ngrok.com/docs). + ### Sharing Sites Via Expose If you have [Expose](https://beyondco.de/docs/expose) installed, you can share your site by navigating to the site's directory in your terminal and running the `expose` command. Consult the expose documentation for additional command-line parameters it supports. After sharing the site, Expose will display the sharable URL that you may use on your other devices or amongst team members. To stop sharing your site, hit `Control + C` to cancel the process. + ### Sharing Sites On Your Local Network Valet restricts incoming traffic to the internal `127.0.0.1` interface by default. This way your development machine isn't exposed to security risks from the Internet. @@ -229,6 +235,7 @@ Once you have completed your custom Valet driver, place it in the `~/.config/val Let's take a look at a sample implementation of each method your custom Valet driver should implement. + #### The `serves` Method The `serves` method should return `true` if your driver should handle the incoming request. Otherwise, the method should return `false`. So, within this method you should attempt to determine if the given `$sitePath` contains a project of the type you are trying to serve. @@ -248,6 +255,7 @@ For example, let's pretend we are writing a `WordPressValetDriver`. Our `serves` return is_dir($sitePath.'/wp-admin'); } + #### The `isStaticFile` Method The `isStaticFile` should determine if the incoming request is for a file that is "static", such as an image or a stylesheet. If the file is static, the method should return the fully qualified path to the static file on disk. If the incoming request is not for a static file, the method should return `false`: @@ -271,6 +279,7 @@ The `isStaticFile` should determine if the incoming request is for a file that i > {note} The `isStaticFile` method will only be called if the `serves` method returns `true` for the incoming request and the request URI is not `/`. + #### The `frontControllerPath` Method The `frontControllerPath` method should return the fully qualified path to your application's "front controller", which is typically your "index.php" file or equivalent: diff --git a/validation.md b/validation.md index c39b93d7587..119aecef47d 100644 --- a/validation.md +++ b/validation.md @@ -126,6 +126,7 @@ You may use the `validateWithBag` method to validate a request and store any err 'body' => ['required'], ]); + #### Stopping On First Validation Failure Sometimes you may wish to stop running validation rules on an attribute after the first validation failure. To do so, assign the `bail` rule to the attribute: @@ -137,6 +138,7 @@ Sometimes you may wish to stop running validation rules on an attribute after th In this example, if the `unique` rule on the `title` attribute fails, the `max` rule will not be checked. Rules will be validated in the order they are assigned. + #### A Note On Nested Attributes If your HTTP request contains "nested" parameters, you may specify them in your validation rules using "dot" syntax: @@ -181,6 +183,7 @@ So, in our example, the user will be redirected to our controller's `create` met + #### The `@error` Directive You may also use the `@error` [Blade](/docs/{{version}}/blade) directive to quickly check if validation error messages exist for a given attribute. Within an `@error` directive, you may echo the `$message` variable to display the error message: @@ -258,6 +261,7 @@ So, how are the validation rules evaluated? All you need to do is type-hint the 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, an 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 evaluated: @@ -461,6 +465,7 @@ The validator also allows you to attach callbacks to be run after validation is 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: @@ -469,6 +474,7 @@ To retrieve the first error message for a given field, use the `first` method: 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 `get` method: @@ -483,6 +489,7 @@ If you are validating an array form field, you may retrieve all of the messages // } + #### Retrieving All Error Messages For All Fields To retrieve an array of all messages for all fields, use the `all` method: @@ -491,6 +498,7 @@ To retrieve an array of all messages for all fields, use the `all` method: // } + #### Determining If Messages Exist For A Field The `has` method may be used to determine if any error messages exist for a given field: @@ -519,6 +527,7 @@ In this example, the `:attribute` placeholder will be replaced by the actual nam '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: @@ -538,6 +547,7 @@ In most cases, you will probably specify your custom messages in a language file ], ], + #### Specifying Custom Attribute Values 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: @@ -554,6 +564,7 @@ You may also pass the custom attributes as the fourth argument to the `Validator $validator = Validator::make($input, $rules, $messages, $customAttributes); + #### 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_type` has a value of `cc`: @@ -841,12 +852,14 @@ The field under validation will be excluded from the request data returned by th 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' @@ -928,10 +941,12 @@ The field under validation must be an integer. 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. @@ -970,6 +985,7 @@ To determine the MIME type of the uploaded file, the file's contents will be rea 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' @@ -1203,6 +1219,7 @@ The field under validation must be a valid RFC 4122 (version 1, 3, 4, or 5) univ ## Conditionally Adding Rules + #### Skipping Validation When Fields Have Certain Values You may occasionally wish to not validate a given field if another field has a given value. You may accomplish this using the `exclude_if` validation rule. In this example, the `appointment_date` and `doctor_name` fields will not be validated if the `has_appointment` field has a value of `false`: @@ -1221,6 +1238,7 @@ Alternatively, you may use the `exclude_unless` rule to not validate a given fie 'doctor_name' => 'exclude_unless:has_appointment,true|required|string', ]); + #### Validating When Present In some situations, you may wish to run validation checks against a field **only** if that field is present in the input array. To quickly accomplish this, add the `sometimes` rule to your rule list: @@ -1233,6 +1251,7 @@ In the example above, the `email` field will only be validated if it is present > {tip} If you are attempting to validate a field that should always be present but may be empty, check out [this note on optional fields](#a-note-on-optional-fields) + #### Complex Conditional Validation Sometimes you may wish to add validation rules based on more complex conditional logic. For example, you may wish to require a given field only if another field has a greater value than 100. Or, you may need two fields to have a given value only when another field is present. Adding these validation rules doesn't have to be a pain. First, create a `Validator` instance with your _static rules_ that never change: @@ -1403,6 +1422,7 @@ 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 `custom` array, which is only for attribute-specific error messages: @@ -1448,6 +1468,7 @@ For a rule to run even when an attribute is empty, the rule must imply that the > {note} An "implicit" extension only _implies_ that the attribute is required. Whether it actually invalidates a missing or empty attribute is up to you. + #### Implicit Rule Objects If you would like a rule object to run when an attribute is empty, you should implement the `Illuminate\Contracts\Validation\ImplicitRule` interface. This interface serves as a "marker interface" for the validator; therefore, it does not contain any methods you need to implement. diff --git a/views.md b/views.md index 264f7654972..b2529f675a1 100644 --- a/views.md +++ b/views.md @@ -35,6 +35,7 @@ Views may also be nested within subdirectories of the `resources/views` director > {note} View directory names should not contain the `.` character. + #### Determining If A View Exists If you need to determine if a view exists, you may use the `View` facade. The `exists` method will return `true` if the view exists: @@ -45,6 +46,7 @@ If you need to determine if a view exists, you may use the `View` facade. The `e // } + #### 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: @@ -195,6 +197,7 @@ Just before the view is rendered, the composer's `compose` method is called with > {tip} All view composers are resolved via the [service container](/docs/{{version}}/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: @@ -210,6 +213,7 @@ The `composer` method also accepts the `*` character as a wildcard, allowing you // }); + #### 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: