In the past couple of weeks, I’ve had to update a few of my Laravel projects. I am incrementally upgrading them to the latest version of Laravel. However this is a guide for anyone who is looking to upgrade their Laravel Project from 5.6 to 8.
Disclaimer : There is already a well known paid package that does this. If you want to save some time and have some money to spend then check out Laravel Shift .
Right lets get to it!
- Before you start look through all the external packages you are using that aren’t part of the default Laravel installation, and ensure they have been updated for Laravel 8.x. Check through
composer.json
and through packagist to check the compatibility. If your project packages have been built by well known companies from the community such as Spatie, Tighten then you shouldn’t have much to worry about - First things first, in your project we are going to create a new git branch:
git checkout -b "upgrade/laravel-8"
- Go through your project’s
composer.json
files and check if there are any packages that are not being used and remove them. - To help with this process we are going to create another separate blank Laravel 8 project using composer ( I know this is weird but follow along with me). This will create a laravel 8 project in a folder called “demo” :
composer create-project --prefer-dist laravel/laravel:^8.0 demo
- Ensure you are running PHP 7.4 on your localised demo and existing project folders. If you are using Laravel Valet on MacOS, use the following commands on both your project and the demo project to localise your project to PHP 7.4 :
valet isolate php@7.4
To set the PHP version.
Henceforth, if you need to use composer then runvalet composer
and forvalet php
to run PHP. - Run
composer update
(Remember if you are using Laravel Valet then dovalet composer update
). - Go into the demo project and start a git repo and commit it as initial commit
- Replace the following dev dependencies in your existing
composer.json
if you have them as they are no longer used in the Laravel :
"filp/whoops"
was replaced with"facade/ignition": "^2.5"
and"fzaninotto/faker"
was replaced with"fakerphp/faker": "^1.9.1"
- Within the demo project, add the following repositories :
"laravel/helpers": "^1.6"
This provides backwards compabitlity for helper functions that were in laravel 5.8 which have been put intoArr
andStr
. If you prefer to replace it manually across your project then here is the full list of methods that need replacing. Remember to import the classes if you decide to do this:use Illuminate\Support\Arr;
and
use Illuminate\Support\Collection;
Method Name Replacement array_add Arr::add array_collapse Arr::collapse array_divide Arr::divide array_dot Arr::dot array_except Arr::except array_first Arr::first array_flatten Arr::flatten array_forget Arr::forget array_get Arr::get array_has Arr::has array_last Arr::last array_only Arr::only array_pluck Arr::pluck array_prepend Arr::prepend array_pull Arr::pull array_random Arr::random array_set Arr::set array_sort Arr::sort array_sort_recursive Arr::sortRecursive array_where Arr::where array_wrap Arr::wrap camel_case Str::camel ends_with Str::endsWith kebab_case Str::kebab snake_case Str::snake starts_with Str::startsWith str_after Str::after str_before Str::before str_contains Str::contains str_finish Str::finish str_is Str::is str_limit Str::limit str_plural Str::plural str_random Str::random str_replace_array Str::replaceArray str_replace_first Str::replaceFirst str_replace_last Str::replaceLast str_singular Str::singular str_slug Str::slug str_start Str::start studly_case Str::studly title_case Str::title "laravel/ui": "3.4.6"
which provides : The Bootstrap and Vue scaffolding provided by Laravel.
- Review your current project’s
composer.json
file and copy across any necessary required or dev dependencies that are not present in the demo project’scomposer.json
. - For all the new dependencies you just copied from the above step replace the version number with “*” . I know this sounds crazy but i have tested with a repo which had over 20 packages and i can confirm it works. For example. I had a repository which had this:
"barryvdh/laravel-dompdf": "*", "barryvdh/laravel-ide-helper": "*", "friendsofphp/php-cs-fixer": "*", "maatwebsite/excel": "*", "owen-it/laravel-auditing": "*", "plank/laravel-mediable": "*", "spatie/laravel-analytics": "*", "spatie/laravel-failed-job-monitor": "*", "spatie/laravel-permission": "*", "spatie/laravel-responsecache": "*", "tightenco/ziggy": "*", "tucker-eric/eloquentfilter": "*"
- Now run
composer update
and it should install most of the packages. If you have any problems, try and do a few packages at a time and keep adding more until you find the problematic one, skip that one and try and fix that at the end until you get a full working composer.json within the demo project with all your dependences. - If you are using PHPStorm, you should now see the version that was installed and replace all of the “*” with the actual version and then copy it back into your demo projects composer.json file, otherwise use the composer.lock file to see which version is installed. If you want to save yourself some time here is a python script that will do it for you)
- Now you can easily copy
composer.json
file from the demo folder to your project. - Once the above step is complete, in your current project, you can run
composer update
and ensure it installs properly. Sometimes if errors occur, I delete thecomposer.lock
andvendor
folder and try again withcomposer install
- At this point, it’s best to do a git commit to your project file (remember you should be in your upgrade/laravel-8 branch)
- Laravel Passport Projects:
Passport::personalAccessClientId('Some Client Name');
was removed from Laravel Passport, so remove this from yourapp/Providers/AuthServiceProvider.php
file. Then look within your oauth_clients database table, and copy the name and secret to your .env file :PASSPORT_PERSONAL_ACCESS_CLIENT_ID="Some Client Name" PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET="Secret From oauth_clients table for Some Client Name"
- Replace
Handler.php
atapp/exceptions/Handler.php
with the one within the demo project folder. - Go to routes/web.php and replace any instances of
$this->
withRoute::
For example :// Authentication Routes... $this->get('login', 'Auth\LoginController@showLoginForm')->name('login'); $this->post('login', 'Auth\LoginController@login'); $this->post('logout', 'Auth\LoginController@logout')->name('logout');
to this – make sure you include
use Illuminate\Support\Facades\Route;
on top of the file// Authentication Routes... Route::get('login', 'Auth\LoginController@showLoginForm')->name('login'); Route::post('login', 'Auth\LoginController@login'); Route::post('logout', 'Auth\LoginController@logout')->name('logout');
- Rename your
seeds
folder toseeders
within your database folder and namespace all of yourseeders
files with :<?php namespace Database\Seeders;
- In Laravel 8, factories are now classes that extend the base Laravel factory class. Namespace all of your ‘factories’ class :
-
<?php
namespace Database\Factories;
and update all of your factories to a class based version like the one found with the demo project under database/factories/UserFactory.php
- Apply the has
HasFactory
trait to all your Models which have factories and use the HasFactory namepsace, look at the example found in the demo folder - Update your
session
config file’ssecure
option will a fallback value of null :'secure' => env('SESSION_SECURE_COOKIE', null),
- Although this is mentioned in Laravel 9 Upgrade Guide, Within your
app/Http/Middleware/TrustProxies.php
file, updateuse Fideloper\Proxy\TrustProxies as Middleware
touse Illuminate\Http\Middleware\TrustProxies as Middleware
. - If you use Bootstrap for your front end, you should add the following method call to the
boot
method of your application’sAppServiceProvider:
use Illuminate\Pagination\Paginator; Paginator::useBootstrap();
- The users table has a new field called
email_verified_at
which gives you email verification functionalityTherefore create a new migration file on your current project by typingphp artisan make:migration add_email_verified_field_to_users_table
with the following code :public function up() { Schema::table('users', function (Blueprint $table) { $table->timestamp('email_verified_at')->nullable()->after('email'); }); } public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('email_verified_at'); }); }
- Compare everything within the following folders from your demo project and copy all of the files from there into your current project. Certain functionalities may have changed but ensure you don’t blindly copy and retain certain functionality :
- app
- config
- routes
- You should go through the official upgrade guides to see if anything has been missed that is specific to your project.
- Run composer update and make sure your project is now working as expected
composer update
. - Update your
gitignore
file from the demo project. - At this point if you have any problems, delete your composer.lock file and vendor directory and run composer install.
- Run phpunit and ensure all your tests are working (hopefully you have been writing them)!
- Do a git commit at this point within your project
- Up until this point we only concentrated on the php side of the upgrades. Now we are going to focus on the front end.
Front End changes from Laravel 5 to Laravel 8
- The best way to work through this is if you install the main framework such as vue or react first
- Go to the official npm website search the framework you are using i.e. vue or react and then find the latest version of your release version from your current project i.e. i had a project in react 17 so i ran
npm i react@17.0.2
andnpm i react-dom@17.0.2
- The default asset bundler is still Laravel Mix. However you need ensure your you put .vue() or .react() within your webpack dependencing on which package you use. Start by doing this in the demo project. Let’s say i am using react this is what my
webpack.mix.js
file would look like :mix.js('resources/js/app.js', 'public/js') .postCss('resources/css/app.css', 'public/css', [ // ]).react();
- Now
run npm install && npm run dev
. This will install all the necessary packages related to getting React or Vue Working - For React with Typescript install these packages :
npm i @types/react @types/react-dom npm i ts-loader typescript @babel/preset-react --dev
and For Vue :
npm i vue@next vue-router vue-loader @vue/compiler-sfc npm i typescript ts-loader --dev
Copy your
tsconfig.json
file from your project to the demo project - Now copy some of your react/vue components into your resources folder and then configure
webpack.mix.js
file to render them using . Fix any errors you get start with minimal components.
A React Setup Would look like this :const mix = require("laravel-mix"); mix.ts("resources/js/app.tsx", "public/js").react();
And the same vue version would look like this :
const mix = require("laravel-mix"); mix.ts("resources/js/app.tsx", "public/js").vue({ version: 3 })
Now run
npm install && npm run dev
and ensure its working then runnpm run prod
to ensure production builds are working too - If you are using tailwind css :
npm i tailwindcss
and your mix file would look like this :
mix.postCss("resources/css/app.css", "public/css", [require("tailwindcss")]);
Again repeat run
npm install && npm run dev
and ensure its working then runnpm run prod
to ensure production builds are working too - Now do a git commit on your demo project
- Copy all of your js files into demo and ensure all of your components and files are rendering. Use the
--legacy-peer-deps
to install the correct packages accordingly: The are the three commands i repeated using during this process :npm i --legacy-peer-deps npm_package_name npm i --legacy-peer-deps npm_package_name --save-dev npm run dev npm run prod rm -rf node_modules package-lock.json
Since this is a demo project you can safely delete the nodes_modules folder and package.json folder and test until you get this process right
- Once you have a working version replace your project’s webpack.mix.js with the one within the demo and run
npm install && npm run dev
followed benpm run build
- Now do a git commit of your upgrade/laravel-8 branch and create a PR for it.
- Deploy the branch on a testing environment and ensure it all works.
I wrote this guide as a simple reference when i am upgrading my old Laravel repositories. Hopefully these steps work for you.