Upgrade Guide

    Estimated Upgrade Time: 1-2 Hours

    Update your dependency to 5.4.* in your composer.json file. In addition, you should update your phpunit/phpunit dependency to ~5.7.

    Removing Compiled Services File

    If it exists, you may delete the bootstrap/cache/compiled.php file. It is no longer used by the framework.

    Flushing The Cache

    After upgrading all packages, you should run php artisan view:clear to avoid Blade errors related to the removal of Illuminate\View\Factory::getFirstLoop(). In addition, you may need to run php artisan route:clear to flush the route cache.

    Laravel Cashier

    Laravel Cashier is already compatible with Laravel 5.4.

    Laravel Passport

    Laravel Passport 2.0.0 has been released to provide compatibility with Laravel 5.4 and the Axios JavaScript library. If you are upgrading from Laravel 5.3 and using the pre-built Passport Vue components, you should make sure the Axios library is globally available to your application as axios.

    Laravel Scout

    Laravel Scout 3.0.0 has been released to provide compatibility with Laravel 5.4.

    Laravel Socialite

    Laravel Socialite 3.0.0 has been released to provide compatibility with Laravel 5.4.

    Laravel Tinker

    In order to continue using the tinker Artisan command, you should also install the laravel/tinker package:

    Once the package has been installed, you should add Laravel\Tinker\TinkerServiceProvider::class to the providers array in your config/app.php configuration file.

    Guzzle

    Laravel 5.4 requires Guzzle 6.0 or greater.

    Authorization

    The getPolicyFor Method

    Previous, when calling the Gate::getPolicyFor($class) method, an exception was thrown if no policy could be found. Now, the method will return null if no policy is found for the given class. If you call this method directly, make sure you refactor your code to check for null:

    1. $policy = Gate::getPolicyFor($class);
    2. if ($policy) {
    3. // code that was previously in the try block
    4. } else {
    5. // code that was previously in the catch block

    Blade

    @section Escaping

    In Laravel 5.4, inline content passed to a section is automatically escaped:

    1. @section('title', $content)

    If you would like to render unescaped content in a section, you must declare the section using the traditional "long form" style:

    1. @section('title')
    2. {!! $content !!}
    3. @stop

    Bootstrappers

    If you are manually overriding the $bootstrappers array on your HTTP or Console kernel, you should rename the DetectEnvironment entry to LoadEnvironmentVariables and remove ConfigureLogging.

    Broadcasting

    Channel Model Binding

    When defining channel name placeholders in Laravel 5.3, the * character is used. In Laravel 5.4, you should define these placeholders using {foo} style placeholders, like routes:

    1. Broadcast::channel('App.User.{userId}', function ($user, $userId) {
    2. return (int) $user->id === (int) $userId;
    3. });

    Collections

    The every Method

    The behavior of the every method has been moved to the nth method to match the method name defined by Lodash.

    The random Method

    Calling $collection->random(1) will now return a new collection instance with one item. Previously, this would return a single object. This method will only return a single object if no arguments are supplied.

    Container

    Aliasing Via bind / instance

    In previous Laravel releases, you could pass an array as the first parameter to the bind or instance methods to register an alias:

    1. $container->bind(['foo' => FooContract::class], function () {
    2. return 'foo';
    3. });

    However, this behavior has been removed in Laravel 5.4. To register an alias, you should now use the alias method:

    1. $container->alias(FooContract::class, 'foo');

    Binding Classes With Leading Slashes

    Binding classes into the container with leading slashes is no longer supported. This feature required a significant amount of string formatting calls to be made within the container. Instead, simply register your bindings without a leading slash:

    1. $container->bind('Class\Name', function () {
    2. //
    3. });
    4. $container->bind(ClassName::class, function () {
    5. //
    6. });

    make Method Parameters

    The container's make method no longer accepts a second array of parameters. This feature typically indicates a code smell. Typically, you can always construct the object in another way that is more intuitive.

    If must continue to pass an array of parameters, you may use the makeWith method.

    Resolving Callbacks

    The container's resolving and afterResolving method now must be provided a class name or binding key as the first argument to the method:

    1. $container->resolving('Class\Name', function ($instance) {
    2. //
    3. });
    4. $container->afterResolving('Class\Name', function ($instance) {
    5. //
    6. });

    share Method Removed

    The share method has been removed from the container. This was a legacy method that has not been documented in several years. If you are using this method, you should begin using the singleton method instead:

    1. $container->singleton('foo', function () {
    2. return 'foo';
    3. });

    The Illuminate\Console\AppNamespaceDetectorTrait Trait

    If you are directly referencing the Illuminate\Console\AppNamespaceDetectorTrait trait, update your code to reference Illuminate\Console\DetectsApplicationNamespace instead.

    Database

    Array Argument to orWhere

    When passing an array as first argument to the orWhere method, the inner conditions now use OR between each array element:

    1. $query->orWhere(['a' => 1, 'b' => 2])
    2. OR (a = 1 AND b = 2) // Prior Behavior...
    3. OR (a = 1 OR b = 2) // New Behavior...

    Custom Connections

    If you were previously binding a service container binding for a db.connection.{driver-name} key in order to resolve a custom database connection instance, you should now use the Illuminate\Database\Connection::resolverFor method in the register method of your AppServiceProvider:

    1. use Illuminate\Database\Connection;
    2. Connection::resolverFor('driver-name', function ($connection, $database, $prefix, $config) {
    3. //
    4. });

    Fetch Mode

    Laravel no longer includes the ability to customize the PDO "fetch mode" from your configuration files. Instead, PDO::FETCH_OBJ is always used. If you would still like to customize the fetch mode for your application you may listen for the new Illuminate\Database\Events\StatementPrepared event:

    Eloquent

    Date Casts

    Foreign Key Conventions

    If the foreign key is not explicitly specified when defining a relationship, Eloquent will now use the table name and primary key name for the related model to build the foreign key. For the vast majority of applications, this is not a change of behavior. For example:

    1. public function user()
    2. {
    3. return $this->belongsTo(User::class);
    4. }

    Just like previous Laravel releases, this relationship will typically use user_id as the foreign key. However, the behavior could be different from previous releases if you are overriding the $primaryKey property or getKeyName method of the User model. For example:

    1. public function getKeyName()
    2. {
    3. return 'key';
    4. }

    When this is the case, Laravel will now respect your customization and determine the foreign key column name is user_key instead of user_id.

    BelongsToMany setJoin

    The setJoin method has been renamed to performJoin.

    BelongsToMany getRelatedIds

    The getRelatedIds method has been renamed to allRelatedIds.

    Has One / Many createMany

    The createMany method of a hasOne or hasMany relationship now returns a collection object instead of an array.

    Has One / Many getPlainForeignKey

    The getPlainForeignKey method has been renamed to getForeignKeyName.

    Related models will now use the same connection as the parent model. For example, if you execute a query like:

    1. User::on('example')->with('posts');

    Eloquent will query the posts table on the example connection instead of the default database connection. If you want to read the posts relationship from the default connection, you should to explicitly set the model's connection to your application's default connection.

    The chunk Method

    The query builder chunk method now requires an orderBy clause, which provides consistency with the each method. An exception will be thrown if an orderBy clause is not supplied. For example:

    1. foreach ($users as $user) {
    2. //
    3. }
    4. });

    The Eloquent query builder chunk method will automatically apply an orderBy clause on the model's primary key if one is not supplied.

    The create & forceCreate Methods

    The Model::create & Model::forceCreate methods have been moved to the Illuminate\Database\Eloquent\Builder class in order to provide better support for creating models on multiple connections. However, if you are extending these methods in your own models, you will need to modify your implementation to call the create method on the builder. For example:

    1. public static function create(array $attributes = [])
    2. {
    3. $model = static::query()->create($attributes);
    4. // ...
    5. return $model;
    6. }

    The hydrate Method

    If you are currently passing a custom connection name to this method, you should now use the on method:

    1. User::on('connection')->hydrate($records);

    hydrateRaw Method

    The Model::hydrateRaw method has been renamed to fromQuery. If you are passing a custom connection name to this method, you should now use the on method:

    1. User::on('connection')->fromQuery('...');

    The whereKey Method

    The whereKey($id) method will now add a "where" clause for the given primary key value. Previously, this would fall into the dynamic "where" clause builder and add a "where" clause for the "key" column. If you used the whereKey method to dynamically add a condition for the key column you should now use where('key', …) instead.

    The factory Helper

    Calling factory(User::class, 1)->make() or factory(User::class, 1)->create() will now return a collection with one item. Previously, this would return a single model. This method will only return a single model if the amount is not supplied.

    The newPivot Method

    The Model::newPivot method signature has been updated to add a new $using argument. The new signature is as follows:

    1. /**
    2. * Create a new pivot model instance.
    3. *
    4. * @param \Illuminate\Database\Eloquent\Model $parent
    5. * @param array $attributes
    6. * @param string $table
    7. * @param bool $exists
    8. * @param string|null $using
    9. * @return \Illuminate\Database\Eloquent\Relations\Pivot
    10. */
    11. public function newPivot(Model $parent, array $attributes, $table, $exists, $using = null);

    Events

    Contract Changes

    If you are manually implementing the Illuminate\Contracts\Events\Dispatcher interface in your application or package, you should rename the fire method to dispatch.

    Event Priority

    Support for event handler "priorities" has been removed. This undocumented feature typically indicates an abuse of the event feature. Instead, consider using a series of synchronous method calls. Alternatively, you may dispatch a new event from within the handler of another event in order to ensure that a given event's handler fires after an unrelated handler.

    Wildcard Event Handler Signatures

    Wildcard event handlers now receive the event name as their first argument and the array of event data as their second argument. The Event::firing method has been removed:

    1. Event::listen('*', function ($eventName, array $data) {
    2. //
    3. });

    The kernel.handled Event

    The kernel.handled event is now an object based event using the Illuminate\Foundation\Http\Events\RequestHandled class.

    The locale.changed Event

    The locale.changed event is now an object based event using the Illuminate\Foundation\Events\LocaleUpdated class.

    The illuminate.log Event

    The illuminate.log event is now an object based event using the Illuminate\Log\Events\MessageLogged class.

    Exceptions

    The Illuminate\Http\Exception\HttpResponseException has been renamed to Illuminate\Http\Exceptions\HttpResponseException. Note that Exceptions is now plural. Likewise, the Illuminate\Http\Exception\PostTooLargeException has been renamed to Illuminate\Http\Exceptions\PostTooLargeException.

    Mail

    [email protected] Syntax

    Sending mail using syntax is no longer supported. For example:

    1. Mail::send('view.name', $data, '[email protected]');

    If you are sending mail in this way you should convert these calls to .

    New Configuration Options

    In order to provide support for Laravel 5.4's new Markdown mail components, you should add the following block of configuration to the bottom of your mail configuration file:

    1. 'markdown' => [
    2. 'theme' => 'default',
    3. 'paths' => [
    4. resource_path('views/vendor/mail'),
    5. ],
    6. ],

    Queueing Mail With Closures

    In order to queue mail, you now must use a mailable. Queuing mail using the Mail::queue and Mail::later methods no longer supports using Closures to configure the mail message. This feature required the use of special libraries to serialize Closures since PHP does not natively support this feature.

    Queue

    Failed Jobs Table

    If your application contains a failed_jobs table, you should add an exception column to the table:

    Improved Clustering Support

    1. 'redis' => [
    2. 'client' => 'predis',
    3. 'options' => [
    4. 'cluster' => 'redis',
    5. ],
    6. 'default' => [
    7. [
    8. 'host' => env('REDIS_HOST', '127.0.0.1'),
    9. 'password' => env('REDIS_PASSWORD', null),
    10. 'port' => env('REDIS_PORT', 6379),
    11. 'database' => 0,
    12. ],
    13. ],
    14. ],
    15. ],

    Routing

    Post Size Middleware

    The class Illuminate\Foundation\Http\Middleware\VerifyPostSize has been renamed to Illuminate\Foundation\Http\Middleware\ValidatePostSize.

    The middleware Method

    The middleware method of the Illuminate\Routing\Router class has been renamed to aliasMiddleware(). It is likely that most applications never call this method manually, as it is typically only called by the HTTP kernel to register route-level middleware defined in the $routeMiddleware array.

    Route Methods

    The getUri method of the Illuminate\Routing\Route class has been removed. You should use the uri method instead.

    The getMethods method of the Illuminate\Routing\Route class has been removed. You should use the methods method instead.

    The getParameter method of the Illuminate\Routing\Route class has been removed. You should use the parameter method instead.

    The getPath method of the Illuminate\Routing\Route class has been removed. You should use the uri method instead.

    Sessions

    Symfony Compatibility

    Laravel's session handlers no longer implements Symfony's SessionInterface. Implementing this interface required us to implement extraneous features that were not needed by the framework. Instead, a new Illuminate\Contracts\Session\Session interface has been defined and may be used instead. The following code changes should also be applied:

    All calls to the ->set() method should be changed to ->put(). Typically, Laravel applications would never call the set method since it has never been documented within the Laravel documentation. However, it is included here out of caution.

    All calls to the ->getToken() method should be changed to ->token().

    All calls to the $request->setSession() method should be changed to setLaravelSession().

    Testing

    Laravel 5.4's testing layer has been re-written to be simpler and lighter out of the box. If you would like to continue using the testing layer present in Laravel 5.3, you may install the laravel/browser-kit-testing into your application. This package provides full compatibility with the Laravel 5.3 testing layer. In fact, you can run the Laravel 5.4 testing layer side-by-side with the Laravel 5.3 testing layer.

    In order to allow Laravel to autoload any new tests you generate using the Laravel 5.4 test generators, you should add the Tests namespace to your composer.json file's block:

    1. "psr-4": {
    2. "Tests\\": "tests/"
    3. }

    Running Laravel 5.3 & 5.4 Tests In A Single Application

    First install the laravel/browser-kit-testing package:

    1. composer require --dev laravel/browser-kit-testing "1.*"

    Once the package has been installed, create a copy of your tests/TestCase.php file and save it to your tests directory as BrowserKitTestCase.php. Then, modify the file to extend the Laravel\BrowserKitTesting\TestCase class. Once you have done this, you should have two base test classes in your tests directory: TestCase.php and BrowserKitTestCase.php. In order for your BrowserKitTestCase class to be properly loaded, you may need to add it to your composer.json file:

    1. "autoload-dev": {
    2. "psr-4": {
    3. "Tests\\": "tests/"
    4. }
    5. }

    Tests written on Laravel 5.3 will extend the BrowserKitTestCase class while any new tests that use the Laravel 5.4 testing layer will extend the TestCase class. Your BrowserKitTestCase class should look like the following:

    1. <?php
    2. use Illuminate\Contracts\Console\Kernel;
    3. use Laravel\BrowserKitTesting\TestCase as BaseTestCase;
    4. abstract class BrowserKitTestCase extends BaseTestCase
    5. {
    6. /**
    7. * The base URL of the application.
    8. *
    9. * @var string
    10. */
    11. public $baseUrl = 'http://localhost';
    12. /**
    13. * Creates the application.
    14. *
    15. * @return \Illuminate\Foundation\Application
    16. */
    17. public function createApplication()
    18. {
    19. $app = require __DIR__.'/../bootstrap/app.php';
    20. $app->make(Kernel::class)->bootstrap();
    21. return $app;
    22. }
    23. }

    Once you have created this class, make sure to update all of your tests to extend your new BrowserKitTestCase class. This will allow all of your tests written on Laravel 5.3 to continue running on Laravel 5.4. If you choose, you can slowly begin to port them over to the new or Laravel Dusk.

    Installing Dusk In An Upgraded Application

    If you would like to install Laravel Dusk into an application that has been upgraded from Laravel 5.3, first install it via Composer:

    1. composer require --dev laravel/dusk "1.*"

    Next, you will need to create a CreatesApplication trait in your tests directory. This trait is responsible for creating fresh application instances for test cases. The trait should look like the following:

    1. <?php
    2. use Illuminate\Contracts\Console\Kernel;
    3. trait CreatesApplication
    4. {
    5. /**
    6. * Creates the application.
    7. *
    8. * @return \Illuminate\Foundation\Application
    9. */
    10. public function createApplication()
    11. {
    12. $app = require __DIR__.'/../bootstrap/app.php';
    13. $app->make(Kernel::class)->bootstrap();
    14. return $app;
    15. }
    16. }

    Once you have completed these preparatory steps, you can follow the normal Dusk installation instructions.

    Environment

    The Laravel 5.4 test class no longer manually forces putenv('APP_ENV=testing') for each test. Instead, the framework utilizes the APP_ENV variable from the loaded .env file.

    Event Fake

    The Event fake's assertFired method should be updated to assertDispatched, and the assertNotFired method should be updated to assertNotDispatched. The method's signatures have not been changed.

    Mail Fake

    The Mail fake has been greatly simplified for the Laravel 5.4 release. Instead of using the assertSentTo method, you should now simply use the assertSent method and utilize the hasTo, hasCc, etc. helper methods within your callback:

    1. Mail::assertSent(MailableName::class, function ($mailable) {
    2. return $mailable->hasTo('[email protected]');
    3. });

    Translation

    {Inf} Placeholder

    If you are using the {Inf} placeholder for pluralizing your translation strings, you should update your translation strings to use the * character instead:

    1. {0} First Message|{1,*} Second Message

    The trans Helpers

    The trans helper signature has been updated to remove the unnecessary $domain argument. The new signature is as follows:

    1. /**
    2. * Translate the given message.
    3. *
    4. * @param string $id
    5. * @param array $replace
    6. * @param string $locale
    7. * @return \Illuminate\Contracts\Translation\Translator|string|array|null
    8. */
    9. function trans($id = null, $replace = [], $locale = null);

    In addition, the trans_choice helper has been updated:

    1. /**
    2. * Translates the given message based on a count.
    3. *
    4. * @param string $id
    5. * @param int|array|\Countable $number
    6. * @param array $replace
    7. * @param string $locale
    8. * @return string
    9. */
    10. function trans_choice($id, $number, array $replace = [], $locale = null);

    URL Generation

    The forceSchema Method

    The forceSchema method of the Illuminate\Routing\UrlGenerator class has been renamed to forceScheme.

    Validation

    Date Format Validation

    Date format validation is now more strict and supports the placeholders present within the documentation for the PHP date function. In previous releases of Laravel, the timezone placeholder P would accept all timezone formats; however, in Laravel 5.4 each timezone format has a unique placeholder as per the PHP documentation.

    Method Names

    We also encourage you to view the changes in the GitHub repository. While many of these changes are not required, you may wish to keep these files in sync with your application. Some of these changes will be covered in this upgrade guide, but others, such as changes to configuration files or comments, will not be. You can easily view the changes with the and choose which updates are important to you.