Deploy Symfony 3 on Heroku

Leveraging Heroku’s Platform for Symfony Projects

Some Background

In my experience with Heroku, I discovered how hard their team has worked to ensure developers have the tools they need to quickly deploy new projects and scale easily if needed. I myself have done just that and for a few years now. It’s the home for all of my personal projects. What really sets it apart for me are the tools, the documentation, and that wonderful free tier. Unlimited projects that give you the full Heroku toolset, and you can run as long as you want? Sign me up.

When I started out in web development, I used Rails. Heroku and Rails work together like best friends. Now that I have more experience, I’ve included PHP into my toolbelt and even more recently, added Symfony. Symfony gives me the familiar concepts that I love with Rails, but it also gives me some of the powerful built in tools that I love with PHP.

Heroku supports PHP, but it doesn’t include specific support for Symfony. And if you want to throw in some front end frameworks (SCSS anybody?) then you’re moving into uncharted waters. For a recent project I was working on, I decided I’d wade deeper into these waters so I can leverage my favorite part of the Heroku ecosystem, free hosting, for a new personal project.

First Step — Get Heroku Ready

The first step to creating a project on Heroku is to create an account, install the CLI, and get familiar with the flow. I won’t cover that here, but another reason I’m such a big fan of Heroku is its wonderful documentation. Take a look in the link below if you need any help getting started in that area:

https://devcenter.heroku.com/articles/getting-started-with-php

After you’ve created your Heroku project, (through the CLI or the web interface) and your Symfony project is running locally, you can start adding in settings for you prod environment. I decided to stick with MySQL for this project, so we’ll need an add-on to provision a database.

I used the ClearDB heroku addon to add MySQL because it has decent documentation and the always important free tier. To add it to your project from the CLI use

heroku addons:add cleardb:ignite

After adding it, you can go to the ClearDB add-on page for you project and grab the username, password, and url for your project so we can add it to the Symfony config later.

Next, we need to add a Procfile so Heroku knows what server we want to use and where we want it to point. Create a Procfile in the root directory of your project (Just Procfile, no file extension) and add:

web: vendor/bin/heroku-php-apache2 web/

This tells Heroku you want to use apache for your PHP project, and you want to use the /web directory as the root for you website.

Your final step will be to add some environment variables to Heroku so Symfony can use them later.

heroku config:set SYMFONY_ENV=prod 
heroku config:set DB_PASS={Your ClearDB password}
heroku config:set DB_USER={Your ClearDB User}
heroku config:set CLEARDB_DATABASE_URL={The clearDB URL}

These commands will make sure Symfony knows to run in production mode on Heroku and it will give us the database credentials we’ll need later to get everything talking.

There will also be one bonus step that you have to do if you’d like to use a frontend framework to compile your assets on build. I like to use SCSS, and I like NPM, so I wanted to be sure I could keep using them on Heroku. Unfortunately, Heroku will only auto detect one buildpack based on what is in your root directory, so your npm commands won’t work in a build script.

We’ll have to tell Heroku that we’re using composer and npm to get everything working. We’ll need two build backpacks to do this, so run:

heroku buildpacks:set heroku/nodejs
heroku buildpacks:set heroku/php --index 2

This will tell Heroku that this project uses npm and composer, and we’d like for it to do the composer actions after we’ve done our node work.

I like to keep all of my npm files in /web so all of my assets are out of the root directory, but if you don’t have a package.json in your root directory Heroku won’t know to run npm install! I created a symbolic link so I could keep my preferred file structure and not have to update two files.

ln -s web/package.json package.json

After all of that, we’re ready to get Symfony ready for our deployment.

Next Step — Getting Symfony Ready

Our first step to get Symfony ready will be to tell it where it’s new database credentials will be.

Since we’re using ClearDB we need to give a URL to doctrine. I include this in config_prod.yml to avoid changes on my dev environment.

# Doctrine Configuration
doctrine:
dbal:
url: "%env(CLEARDB_DATABASE_URL)%"

The next step will be to make sure Symfony knows that the database credentials it needs are set in environment variables, so update paramters.yml.dist to add these during the build process.

parameters:
database_host: %env(CLEARDB_DATABASE_URL)%
database_port: ~
database_name: 'symfony'
database_user: %env(DB_USER)%
database_password: %env(DB_PASS)%

This will give Symfony and doctrine everything they need to start talking with our database.

Final Step — Launch!

The final step to launch is to configure your build. To give you control over what your build looks like Heroku will check a special key named “compile” in your composer.json file. Any commands you include there will be run when you deploy your project, so we’ll want to make sure all of our last minute work that needs doing goes in there.

"compile": [
"bin/console doctrine:schema:update --force",
"mv node_modules web",
"cd web && node_modules/.bin/gulp scss:prod",
"cd web && rm app_dev.php"

]

Above is an example of what your compile section could look like. In it we’re applying any database updates through doctrine, moving the node_modules folder to web, running Gulp to compile our SCSS and removing app_dev.php from our production environment.

It is important to note that for this build the node_modules folder was not included in the git repository. This was generated after npm install was run by Heroku in the first part of the build. This is why our buildpack commands

heroku buildpacks:set heroku/nodejs
heroku buildpacks:set heroku/php --index 2

made sure to specify that the PHP build (ie composer install) should run after the nodejs build (npm install). That way we can run the node commands to build out our frontend files while composer does its work. I also like to move the node_modules folder to web, just to keep assets together.

After the Build

After you get your base build up and running, you can start to use Heroku’s other tools to make your deployment process even smoother. By doing this, you can try different add-ons for monitoring, add more test environments, and integrate with Pipelines. And all for the very affordable cost of $0 a month! PHP is a powerful language, Symfony is a powerful framework, and Heroku is a powerful platform, so build build build as the options are limitless.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.