loading...

Deploy a Laravel 5 app to Heroku

connor11528 profile image Connor Leech Updated on ・4 min read

Heroku is an awesome platform originally built on top of AWS and currently owned by Salesforce. Laravel is a powerful PHP web framework for building applications.

In this short tutorial we're going to generate an app from laravel-5-boilerplate and deploy it to Heroku.

By the end of the tutorial we will have a user management and permission system built with Laravel, Bootstrap and live to the internets powered by Heroku.

If you prefer to have a generic Laravel 5 app instead of a massive boilerplate follow this gist. Besides step 1 everything else will be the same.

Without further ado, let's get started.

Steps:

  • Download Laravel 5 Boilerplate according to the Quick Start Documentation. Also git init for the project.

  • Create a local MySQL database for development:

$ mysql -uroot -p
> create database MY_DATABASE_NAME;
Ctrl-C to exit
  • Create a Procfile to teach Heroku how to boot up our app:
$ echo web: vendor/bin/heroku-php-apache2 public/ > Procfile
  • Create a Heroku app. You will need the Heroku CLI installed.
$ heroku create YOUR_APP_NAME
  • Add a PHP buildpack:
$ heroku buildpacks:set https://github.com/heroku/heroku-buildpack-php
  • Add MySQL to our Heroku project:
$ heroku addons:add cleardb

This creates a config variable called CLEARDB_DATABASE_URL which you can view using the following command. Add CLEARDB_DATABASE_URL to our .env file.

$ heroku config | grep CLEARDB_DATABASE_URL

Modify config/database.php so that we connect to our Heroku database.

<?php

$url = parse_url(getenv("CLEARDB_DATABASE_URL"));

$host = $url["host"];
$username = $url["user"];
$password = $url["pass"];
$database = substr($url["path"], 1);

return [
    ...
    'connections' => [
        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', $host),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', $database),
            'username' => env('DB_USERNAME', $username),
            'password' => env('DB_PASSWORD', $password),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],
  • Set an heroku config variables. Remember, your .env file is not checked into version control so we need to let heroku know about our specific config.:
$ php artisan key:generate --show
$ heroku config:set APP_KEY=app_key_goes_here
$ heroku config:set APP_URL=your_app_name.herokuapp.com

Push to Heroku.

When we created the heroku app through the CLI it automatically added a git remote called "heroku". We can push our code to a Heroku server using this git remote.

$ git remote -v 
$ git add -A
$ git commit -m 'heroku deployment stuff'
$ git push heroku master
$ heroku open

The first command displays the git remotes available to you. The next command adds everything into git including new or deleted files. Then we commit and push. The final command will open your new Laravel heroku app in the browser.

Database stuff

We added a ClearDB database but we have not run our migrations to create our tables. To do this we can run

$ heroku run php artisan migrate

There is a common error many people experience (outlined above)
Now that SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes. Fortunately, Eric Barnes has a solution outlined in this post.

Head into app/Providers/AppServiceProvider.php and add a default string length to the boot method:

use Illuminate\Support\Facades\Schema;

...

public function boot()
{
   Schema::defaultStringLength(191);
}

Commit this change and push to heroku. In order to get our database set up without issue try this command:

$ heroku run php artisan migrate:reset 

If you run a plain old php artisan migrate first the terminal will sqwuak that SQLSTATE[42S01]: Base table or view already exists. Running reset successfully runs our migrations.


SSL/HTTPS stuff

I wrote a more thorough guide on setting up HTTPS through SSL certificates for a custom domain on Medium. For some reason Laravel apps will display HTTP urls which the browser will mark as "Not Secure". Heroku uses https:// by default for deployments. Loading pages over http:// could give us a Mixed Content, insecure stylesheet or insecure script error.

One fix for this is to configure Laravel to load assets over HTTPS in production. To do this, head into App/Providers/AppServiceProvider.php and configure to load everything over HTTPS in production:

use Illuminate\Support\Facades\URL;

...

// Force SSL in production
if ($this->app->environment() == 'production') {
    URL::forceScheme('https');
}

Fin

Congrats! You've deployed your Laravel 5 application to the internet using Heroku.

If you have questions hit me up on twitter. Also, I've got a mailing list going that I send out twice a week with legit tutorials covering Laravel, Vue, Heroku and other fun stuff in addition to open source projects and jobs

Sign up here! http://connorleech.info/

Update:

  • You can make a database using the ClearDB plugin. Then from Sequel Pro or a similar tool you can connect to the production db using this info from the URL: CLEARDB_DATABASE_URL => mysql://[username]:[password]@[host]/[database name]?reconnect=true. Set the config variables for the heroku app with the heroku config command.

Discussion

pic
Editor guide
Collapse
mostueck profile image
Moritz Stückler

My deployment seems to work finde, until php artisan is running some script which is trying to connect to the database (which doesn't exist yet, because I haven't run migrations yet). Any idea what that happens?

...

  • Installing graham-campbell/manager (v4.0.0): Downloading (100%)
  • Installing vinkla/hashids (4.0.0): Downloading (100%) Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover

In Connection.php line 664:

SQLSTATE[HY000] [2002] Connection refused (SQL: select * from questions)

...

Collapse
connor11528 profile image
Connor Leech Author

you need to have a production database connected to heroku

Collapse
azazqadir profile image
Muhammad Azaz Qadir

I have never used Heroku. Is it like Forge, where you have to pay separate invoice to provider and the platform. Or like Cloudways (cloudways.com/en/laravel-hosting.php ), where you only have to pay the invoice to the platform.

Collapse
connor11528 profile image
Connor Leech Author

It’s based on traffic and cpu. Most of the time it’s free. If you need special features the hobby plan is $7/month heroku.com/pricing

Collapse
antoine profile image
Antoine Gagnon

Great tutorial ! Seems like everything worked for me :) Now onto your Vue tutorial ;)

Collapse
zaratedev profile image
Jonathan Zarate

Thanks! awesome tutorial. :D

Collapse
khalifa profile image
khalifa

Great tutorial
Huge thing missing though:

heroku run composer install

Collapse
r2luna profile image
Rafael Lunardelli

I'm trying to deploy my laravel app but I'm having problem with the npm run production command. Can you helps us with that?

Collapse
connor11528 profile image
Connor Leech Author

maybe. What's the error?

Collapse
connor11528 profile image
Connor Leech Author

There's another helpful tutorial here that uses more steps through the Heroku UI: mikateach.com/setting-up-laravel-5...

Collapse
youdevs profile image
Carlos Hernández

Thank you bro <3

Collapse
its_phronesis profile image
Joey K

I'm getting an error! That the host, user, and pass indexes of $url are undefined indexes. What am I missing?

Collapse
connor11528 profile image
Connor Leech Author

Do you have CLEARDB_DATABASE_URL as an environment variable set in heroku? You can check by typing herou config devcenter.heroku.com/articles/conf...

Collapse
roniemeque profile image
Ronie

man I just had to deploy an Laravel app for a client to see how the project was going in like a EXTREMELY BIG HURRY. You saved my life, for real. God bless you.