Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

JeffreyWay's avatar

Any questions about upgrading to Laravel 5?

Hey, all -

Last night, I sat down and upgraded the Laracasts codebase to Laravel 5. I can't in good conscience tell you that it was an enjoyable process. Having said that, it took around 4 hours - so not too bad in the long run. Dedicate a half-day to it, and you're done.

It's important to note that it's not like you have to upgrade to L5 right away. You can stay on L4; no issues there. However, if you're planning to make the jump and have some questions about the process, ask away and I'll do my best to answer.

(I'll group all answers in the reply directly below this.)

0 likes
51 replies
JeffreyWay's avatar
JeffreyWay
OP
Best Answer
Level 59

To start:


"Model::remember()" is Gone

I had to update a number of repositories to fix this one. Taylor removed the ability to cache a database query, using the remember() method. So, this will no longer work:

Question::remember(1440)->get();

The same is true for the cacheTags method. Instead, just use Cache::remember(), and then wrap your Eloquent query within it.


Pagination

A couple things have changed with pagination. The big one is that, for the page links, $paginator->links() no longer works. Change all those calls to $paginator->render().


Controllers

All controllers in Laravel 5 are namespaced, by default (following PSR-4). This can be a pretty big pain, in terms of upgrading. I decided to go through with the manual process of updating all the classes, and ensuring that everything was imported properly. If you'd rather skip this, you can add the controllers directory to your composer.json file (in the classmap autoload section). Finally, go to your RouteServiceProvider, and set the namespace property to null.

That said, if you have the time, I recommend just updating everything to be namespaced. It's good for consistency.


Configuration

Configuration is pretty different in Laravel 5 (but better). For your Laravel 4 apps, you know how you have, for example, an app/config/local/mail.php file, which handles mail configuration for the local environment, right? Well it's not quite like that anymore. Instead, you'll just have one config/mail.php file, where you'll use environment variables to set the values.

As an example, your config/database.php section might have something like this:

'mysql' => [
            'driver'    => 'mysql',
            'host'      => env('DB_HOST', 'localhost'),
            'database'  => env('DB_NAME', 'forge'),
            'username'  => env('DB_USER', 'forge'),
            'password'  => env('DB_PASSWORD', 'secret'),
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
            'strict'    => false,
        ]

env is a little helper function that Laravel provides. It allows you to reference an environment variable, or use a default if one does not exist. Now, you'll create a .env file for each environment, and set these values, like so:

DB_HOST=localhost
DB_NAME=homestead
DB_USER=homestead
DB_PASSWORD=secret

So, for production, you'll manually create a .env file, and set those values to whatever is appropriate for your production db.


Helper Functions

Laravel 5 offers a number of convenient helper functions to handle common tasks, like View::make() or Redirect::to or Event::fire(). For those three examples, you can now use view(), redirect(), and event().

So, you can do a quick search and replace within your controllers directory to update these. So, to clarify:

return View::make('posts.index')

can be updated to:

return view('posts.index');

Next, if you fire any events from your controllers:

Event::fire('UserSignedUp', [$user]);

You can search and replace to:

event('UserSignedUp', [$user]);

And last, but not least (there's a number of them), for redirections, these...

return Redirect::to('articles');
return Redirect::route('articles_path');
return Redirect::back();
return Redirect::home();

...can be updated to:

return redirect('articles');
return redirect()->route('articles_path');
return back();
return redirect()->home();

One nice benefit to this is that you don't have to import all those facades for every namespaced controller.


Form and Html Facades are Gone

Taylor stripped the FormBuilder and HtmlBuilder classes from core. As a result, if you still want to do things, like:

{{ Form::open() }}

{{ Form::close() }}

Then you'll need to:

  • Composer require illuminate/html
  • Add Illuminate\Html\HtmlServiceProvider to your config/app.php section.
  • Add facade aliases to that same file at the bottom ('Form' => 'Illuminate\Html\FormFacade')

Now, you're back to normal.


Blade Braces

On that note, when you load your updated app in the browser, you'll see all the HTML from things like {{ Form::open() }}. Laravel changed how these were treated, to help with security. Everything is escaped by default, now. If you want to override that, then you must use:

{!! Form::open() !!}

{!! Form::close() !!}

For a big app, this could be a very lengthy process, so, temporarily, you can bring back the old Blade defaults (until you have time to update everything). From the Laravel docs:

However, if you must use the old Blade syntax, add the following lines at the bottom of AppServiceProvider@register:

\Blade::setRawTags('{{', '}}');
\Blade::setContentTags('{{{', '}}}');
\Blade::setEscapedContentTags('{{{', '}}}');

Catching Exceptions

In Laravel 4, you might have caught exceptions from your global.php file, like so:

App::error(function(Illuminate\Database\Eloquent\ModelNotFoundException $exception)
{
    return Redirect::to('foo')->with('flash_message', 'Had trouble loading that page. Sorry!');
});

You can't do that in version 5. Instead, you can store this sort of logic in app/Exceptions/Handler.php, within the render() method. Let's convert the snippet from above:

public function render($request, Exception $e)
{
    if ($e instanceof ModelNotFoundException) {
        return redirect('foo')->with(
            'flash_message',
            'Had trouble loading that page. Sorry!'
        );
    }

    return parent::render($request, $e);
}

Notice how we check the type of the instance. Also, on a related note, if you use a service, like Bugsnag (highly recommended), then you can add the necessary setup to the report method in that file. Maybe something like:

app('bugsnag')->setNotifyReleaseStages(['production']);

Views

Directories have been moved around in Laravel 5. Your views used to be stored in app/views. Move those to resources/views.


Artisan Commands

I had to move around my Artisan commands to get those to work. First, move all the commands from app/commands to the new app/Console/Commands. Don't forget to upgrade the namespaces in the process. Next, rather than registering your commands with something like Artisan::add() or Artisan::resolve(), instead update the $commands array within app/Console/Kernel.php. Yours may look something like:


/** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ 'Laracasts\Console\Commands\ClearHistoryCommand', 'Laracasts\Console\Commands\SignupsReportCommand', 'Laracasts\Console\Commands\WelcomeUserCommand', ];

That should do it!

32 likes
opb's avatar

@JeffreyWay was anything difficult or unexpected, or was it just long and dull due to size of the project?

xingfucoder's avatar

Many thanks @JeffreyWay for speak us about your experience in the upgrading process.

I think it will depends on the size of the application.

I have not upgraded any application because I'm in a learning process but I think it may be difficult for big applications.

I always recommend to maintain separated the Business Logic for this reason, because we can port this logic without fear to break the main application basecode.

Thanks again for your comments.

browner12's avatar

I had asked you on twitter what your process was for dealing with your git repo, since the suggested upgrade path was to start with a fresh copy of L5 and copy all the files from your L4 project into it. Maybe you could add a brief overview of how you decided to handle this here in the forums so others can benefit from it as well.

Thanks!

Craftyx's avatar

@browner12 : here's how I did it to keep my git history :

  1. Create a copy of your project . It's basically a backup, and it will useful to copy your files too
  2. Back in your project, create a branch from your existing codebase (ex: git checkout -b Feature/UpgradeToLaravel5)
  3. Remove EVERYTHING but the .git folder
  4. The goals is to get Laravel 5 files now. Choose one solution :

At this point, you can commit if you want to have some history of the fresh Laravel 5 app 5. Start the migration, step by step. If you have some automated tests, run them often. 6. merge back to your main branch

Craftyx's avatar

I'm actually rewriting Laravel.fr from scratch, but i still want to keep my git history, so yeah this method works well.

mattstauffer--personal's avatar

There's one step you can simplify: You can clone the Laravel 5 files directly into your empty folder right after step 3 of @AoSiX's process. I walked through it here:

http://mattstauffer.co/blog/upgrading-from-laravel-4-to-laravel-5

I got the tip originally from someone on Twitter, but can't find the link at the moment.

git remote add laravel https://github.com/laravel/laravel.git
git fetch laravel
git merge laravel/master --squash

@JeffreyWay, I think the main thing I would wonder from you is, did you find any changes to any of the component APIs? For example, $pagination links changing to render.. but I also saw that you DI a Cache instance a little differently now. Did you find any other ways you had to change your code?

2 likes
heliocorreia's avatar

One question. .where is the best place to put our helper file?

xingfucoder's avatar

Hi @heliocorreia,

I think that if your helper files work supporting your Business Logic you could put within a Domain folder App\Domain\Helpers but if those helpers are related with the application functionality you may put within the App\Helpers folder or namespace.

jekinney's avatar

If you have a working L4 app, what is the benefit to upgrading to l5? Yes our new projects (where I work) are being developed in l5, but we don't see the need to upgrade the older projects. Granted changes aren't being made on a large scale mainly updates.

JeffreyWay's avatar

@jekinney - If you don't see any value in upgrading, then don't. Personally, I want to use a lot of the new stuff, so it's worth a few hours of my time to upgrade.

4 likes
baao's avatar

Hi @JeffreyWay,

I've been upgrading my app to L5 yesterday. I had issues with pagination on grouped by queries (as stated on the laravel website) and with the missing Remote/SSH class. I've writen a little helper for SSH which is using phpseclib and it's working, but I'm wondering if I should make a 'bigger' project out of it or if L5 will get the SSH class again once it's finished.

Can you say something about pagination and SSH support in early version of L5 final? Thank you very much, also thank you for the great screencasts you are publishing!

1 like
LukeJoyce's avatar

I have a large app in production and upgrading isn't really practical right now. I'm wondering if the L5 route caching feature could be back-ported to L4 for a quick performance boost?

Lenius's avatar

In Laravel4 is used this method to set my env.

$env = $app->detectEnvironment(function(){
    $hosts = array(
        'localhost' => 'da',
        'site.dk' => 'da',
        'site.de' => 'de',
        'site.no' => 'no'
    );

    if(isset($hosts[@$_SERVER['SERVER_NAME']])){
        return $hosts[@$_SERVER['SERVER_NAME']];
    }
});

And then overwrite my app configuration to target the domain.

config
    da/app.php
    de/app.php 
app.php 

Is that not possible anymore.

jasteralan's avatar

I want to register some local only providers. In L4, I can write in config/local/app.php like this :

return [
    // ...
    'providers' => append_config([
        'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider'
    ])
];

But in L5, it seems I can't do it anymore.

Any other ways to do it ? Thank you :)

JeffreyWay's avatar

@jasterlan - You can register that from your AppServiceProvider. Just check the environment and proceed:

if ($this->app->environment() == 'local') {
    $this->app->register('...');
}
4 likes
Kussie's avatar

@Lenius No that is not possible anymore. Cascading configs and subdirectory based configs are no longer supported. My approach for my app was to convert items in my configs to use settings pulled from the .env file where ever they were needed.

It also gave me a good reason to clean up my config file structure and files as well.

DanSmith's avatar

I see that by default, pagination is set up to work with Bootstrap. I prefer to use Foundation and I'd like to know the best way to do this.

I have set up my own FoundationPresenter class which implements the Illuminate\Contracts\Pagination\Presenter interface, however I'm making this work by including the following in my views:

{!! $records->render(new \App\Presenters\FoundationPresenter($records)) !!}

Which just feels wrong.

isimmons's avatar

@DanSmith as far as I can tell looking at the code passing an instance of your own custom presenter to the render method is the way to override it but I agree that newing up an instance of your presenter inside the view doesn't seem right. I don't see any documentation available on that yet.

@JeffreyWay a lesson on creating and using a custom paginator please?

vincej's avatar

@JeffreyWay

Just wondering, of all the L4 lesson topics which ones are now to be ignored given the vast changes which have occurred to L5.

I ask as I do not to waste time applying L4 knowledge to L5. Additionally I wish to target my L5 learning to those topics which are critical.

Many thanks !

JeffreyWay's avatar

@vincej - Not sure what you mean. Most of your L4 knowledge will apply to L5. The APIs are almost identical. So nothing is being ignored.

RachidLaasri's avatar

@JeffreyWay I almost finished an app i created using L5 two weeks ago, what if i want to upgrade to the stable release?

Should i just run

composer update
vincej's avatar

@JeffreyWay

What I mean is, of all those L4 lessons which are the one's whose content no longer apply. Or put a different way, which are the ones which I need to relearn the "L5 way". Or, can I just use L4 lessons and apply them universally to L5 ? Thanks !

ChrisB's avatar

@RachidLaasri Yesterday I had to do the same thing. Here are the steps I took:

  1. I started with composer update ... but that stopped authentication from working, and some facades were broken too
  2. install a new copy of Laravel 5 in a new folder
  3. use WinMerge or Beyond Compare or Araxis Merge or Kaleidoscope to compare the new site against my own. (Skipped the /vendor/ folder of course, since composer took care of that part)
  4. There were a lot of namespace differences (just \App vs my own), but there were a number of the core /app/ folder files that had clearly been changed significantly, so I simply merged the new changes into my own files.

Then everything worked again.

Next

Please or to participate in this conversation.