www.qgates.com

Page: https://www.qgates.com/articles/blog/howto-update-laravel-4

Howto: Update Laravel 4

Posted by Seb T in blog on

Laravel 4 PHP framework

In this guide I walk through the steps I took to bring my Laravel 4 codebases bang up to date. Intended audience:

  • you've been focused on learning and developing Laravel 4 code for a number of months, with possibly >1 Laravel 4 codebases installed locally and in various stages of active development.
  • some you don't care too much about so you've hacked them around and run composer update often.
  • others are for more serious projects and, having broken your "carefree" L4 installs several times with composer update and other methods of staying up-to-date, you got wary and decided to stay with a particular (old) L4 codebase for a while so you could concentrate on your own work.
  • though you may be comfortable with git and use it for your work, your L4 installs are not tied to laravel's github repos, so git diffing and merging with remote repos may not be appropriate for you.

With much fanfare Laravel 4 was released to the world in stable form on 28th May 2013. The Laravel 4 dev branch is committed and tagged 4.0. 4.1 is already cooking, with developer-stable interim releases happing weekly or faster. So you want to bring everything nicely up to date without breaking your code?

Backups. Make 'em before anything else

Probably the most important rule before you start goofing around with your source branches. Make a backup and keep it safe. Choose whatever you're comfortable with, zip, tar, rar, whatever. Depending on how you're using git or other version control, you could rely upon that for this purpose, but my preference is to have an additional layer of backup before any major changes, adopting the KISS approach. Just make sure your entire L4 directory branch is backed up and labelled in a manner that makes sense to you.

Yes, there's some hassle...

...and here's why. The first reason is that L4 brings with it some increased complexity due to its modular architecture and dependence on third-party components. The second is that your pre-4.0 L4 codebases are "unstable". I put that in quotes because I found the code to be production ready and runtime robust/stable for quite a number of weeks before the release. I mention it because as such things can (and did) change. Some changes affected the L4 API and however small these changes could break your code. Thanks to the skill of the L4 team and the quality of their work, these things will likely be pretty easy to fix so long as you're not working with really early L4 code.

What's going to change?

There seems to be quite some confusion surrounding updating Laravel 4, largely due to misunderstandings about what composer update will and won't do. It will update everything under /vendor, which includes the laravel framework, but won't update anything else - ie. the laravel app skeleton you fleshed out for your killer app. So to completely bring everything up-to-date, the following needs to be done:

  1. The Laravel 4 app skeleton, base scripts and configuration. In all likelihood you installed L4 by installing this either from github.com/laravel/laravel, or by downloading a zipfile containing same; you then ran composer install to pull in the rest of the components.
  2. The Laravel framework, along with third party components used either by Laravel directly or installed by you. Basically, everything under /vendor. This is the stuff that's managed/controlled by composer, a PHP package and dependency manager. Packages are updated when you run composer update so you shouldn't modify anything under /vendor directly. So long as you didn't, this should be pretty straightforward.
  3. Your code, which will likely be at least modifications to files within the Laravel app skeleton.
  4. Composer itself, contained entirely in the php bundle composer.phar

Depending on the complexity of your app, steps 1 and 3 will likely be the most involved. All the above steps can be carried out in a number of different ways, and git is your friend for this kind of work. But for this exercise I'm going to assume you're working mainly on a Windows box and without convenient access to git. I'm doing it this way because others have covered the git way of doing things (links to other helpful articles at the bottom) and not everyone is with the program when it comes to vcs and/or using git. Life isn't about discrimination :)

1. Updating the L4 app skeleton

First things first: the L4 skeleton should only change with a given tagged release of L4. So you should only need bother yourself with this step when updating between L4 releases (tagged in git as eg. 4.0.1), or when updating from L4 prerelease code to L4 release code - the situation at the time of writing.

There are a few ways to skin this but essentially they all boil down to the same thing: the L4 app skeleton contains all the stuff you're likely to have modified while developing your worldbeating facebook replacement. Your mods will either be new files (eg. views, database migration and seeds for your models, etc.) or changes to existing files (eg. routes.php, filters.php for handling your app logic or composer.json for managing your composer packages). So you're going to need to do some diffing and merging; again, use approaches and tools that are familiar to you for the purpose.

Most recently I went through this process with a commercial L4 app I'm working on. It hadn't received any L4 or composer updates for some time (six+ weeks). So, without using git and on a windows running Uniform server, here's what was done:

  1. Pulled down a copy of Laravel 4, also available as a zipfile directly from laravel.com and placed it alongside my in-development L4 branch on my server.
  2. dev/
    my-l4-app/
    laravel-master/      <-- Laravel 4 master.zip extracted here!
    
  3. It's important to note that the L4 master (skeleton) app should not be installed further by running composer install or whatever. Just extract the zip, it's all we want here.
  4. Running windows I dig out my oldie-but-goodie Windiff for diffing, instruct it to compare directories, then point it at "my-l4-app" and "laravel-master" which become left and right respectively for the purposes of diffing.
  5. Set Windiff to hide identical files and left-only files. The latter means that everything in vendor/ and the non-skeletal parts of laravel are left out of the diffing process, which is exactly what we want.
  6. The diff process results in a list of files that either
    a) you modified as part of your development, or
    b) are part of laravel core that have been updated/changed by team laravel (ie. unchanged by you), or
    c) both, ie. as (b) but also modified by you.
  7. Deal with the these files in the following ways:
    (a) files can be left as-is
    (b) files should be copied from right to left, overwriting the originals in the my-l4-app/ branch
    (c) your changes must be merged in by hand to the file in the right-hand branch (ie. laravel-master branch), then copied over to the left-hand branch (your app)

In practice the above is quite easy.

Examples: composer.json and ./app/config/app.php will almost certainly fall into group (c) above, whilst routes.php and filters.php will likely be part of group (a). During my update process files including ./app/config/session.php, ./app/config/mail.php and ./app/start/global.php fell into group (b).

2. Updating laravel framework and components with composer

In theory you're just a composer update away. I ran into a few gotchas though:

  1. Take note that if you were using composer install --prefer-dist or composer update --prefer-dist in your L4 prerelease code composer installs, it seems that you can now leave out --prefer-dist since the config option:
    "config": { "preferred-install": "dist" }
    has been added to the L4 release composer.json file.
  2. When I ran composer update I ran into a problem. The L4 release composer.json file has a new entry:
    "pre-update-cmd": [ php artisan clear-compiled"]
    a script which gets called prior to running the update. For me, this script (and thus the update) failed with an error relating to a new entry in the providers array in ./app/config/app.php. The new provider is: 'Illuminate\Foundation\Providers\MaintenanceServiceProvider'
    which wasn't present in L4 in the weeks prior to its release. My guess is that the new artisan script clear-compiled checks that provider source exists in the tree before performing its function and, of course, that one didn't since we haven't pulled it in yet! The solution was to delete ./bootstrap/compiled.php (a file that's autogenerated or manually updated with artisan optimize), then temporarily remove "pre-update-cmd": [ php artisan clear-compiled"] from composer.php. Then run composer update again, reintroduce the removed line above and you should be good.

Other issues of note:

  • Once composer got to the stage of pulling down, removing and installing new versions of packages, the script would bomb along the lines of the following:
    - Removing symfony/routing (dev-master v2.3.0-BETA1)
    - Installing symfony/routing (dev-master 93fa88b)
    Downloading: connection...
    [Composer\Downloader\TransportException]
    The "https://api.github.com/repos/symfony/Routing/zipball/93fa88b2494d3262c87ca0762551a658cc390669"
    file could not be downloaded (HTTP/1.1 502 Bad Gateway)
    
    Issuing the composer update command again, it would succeed on the offending package then throw the same exception on a subsequent package. In the end I solved this by running composer update again each time I saw the above error. I can only put this down to a misbehaving api.github.com; in my case it took four update commands for the update to complete successfully. A little googling confirms this; a potential issue with github which will hopefully be resolved by the time you're reading this.
  • The final oddity is more of an open question, perhaps revealing my limited familiarity with composer. This happened with a number of the packages (mainly symfony); I'll pick one to illustrate. Upon successfully completing composer update, package symfony/process installed with the following message:
    - Removing symfony/process (dev-master v2.3.0-BETA1)
    - Installing symfony/process (dev-master 75c8101)
    Downloading: 100%
    
    Immediately re-running composer update again, the same package was removed and reinstalled a second time:
    - Removing symfony/process (dev-master 75c8101)
    - Installing symfony/process (2.3.x-dev v2.3.0-RC1)
    Downloading: 100%
    
    Note the hashes/comments. It seems that the first update installed a "newer but not newest" build, where the second update removed that version and updated it again to the very latest. Likely this behaviour is down to dependencies; ie. some other packages had a dependency constraint on the above staying at older versions; with the subsequent call to update removing that constraint. I'd love to hear more if someone would care to chime in.

3. Your code

So you've carefully gone through the above process, point your browser at your laravel site and it bombs with laravel's colourful exception (whoops) screen? Chances are something's changed in the laravel API. The older the L4 codebase you've been working with, the more likely you are to see this.

Thankfully, given the sterling job done by Taylor and team Laravel, L4's spec and APIs were functionally stabilised fairly early in L4's evolution. Most of the API changes that took place over the last month or so have been cosmetic. Honestly, I ran into very few issues with my updates. The best part is that in many cases the clues to potential problems will come from the diff exercise carried out in step 1.

As example, ./app/config/app.php registers class aliases for most of laravel's classes, so if any of those have been name-changed you'll see it while diffing in step 1. One such example is the HTML:: class facade whose name has been uppercased in the final release of L4 for consistency with other classes (URL:: etc.). So any calls to methods of Html:: in your code (in blade templates based on older L4) will need to be uppercased to HTML::

In cases where changes are more complicated (eg. changes to parameters passed in to framework APIs, or data returned), the exception screen you'll see will indicate the offending call and browsing into laravel's source tree will reveal the API changes. Update your code to reflect these changes and you should be good to go. The best news is that, at least in my experience, nothing has changed radically. Part of Taylor's design goals with laravel have been stablising the API interfaces as early on as possible, making the experience of "being along for the ride" of laravel's evolution as painless as possible.

I'd welcome your experiences on this since mine were fairly painless. Tweet me!

4. Updating composer

So I've left the easiest to last. You'll possibly receive a warning from composer that it's own script has been updated, along with a very helpful message indicating exactly how to pull it down. So simple that it barely warrants explanation. As a precaution I'd recommend doing this early-on and preferably before performing the updates in step 2 above.

 

Other useful docs I found with regard to updating can be found at the foot of this blogpost from Jason Lewis. But hey, while you're there, why not read the whole thing and take a look around his site?!

Feel free to contact me with any thoughts or questions. As a final checklist, be sure to check out:

We design documentation systems for emergency, first response and global industries. Queensgate Studios built our online presence, ordering system and EDIS, our first electronic system.

Carl Wallin, CWC Services, UK

We specialise in wealth management for Doctors and Dentists. Queensgate Studios built a site to showcase us and allow our advisers to regularly inform clients about financial matters which matter to them.

Laurence Newman, Legal and Medical Investments Ltd., UK

We needed Android support for Flexicall, a system designed around legacy Windows Mobile 6 devices. Queensgate Studios delivered on time and on budget.

Cuda Drinks Co., Plymouth, UK

As a creative photographer, I wanted a responsive website with a unique style to showcase and sell my work. Seb delivered a beautiful site that also works brilliantly on phones and tablets.

Pam West, H-Pinkness Photography, Brighton, UK