Deploying PHP Apps on Heroku
Last updated December 02, 2024
Table of Contents
This article describes how to take an existing PHP app and deploy it to Heroku.
If you are new to Heroku, you might want to start with the Getting Started with PHP on Heroku tutorial.
Prerequisites
The best practices in this article assume that you have:
- an existing PHP app that uses Composer for dependency management.
- PHP installed
- Composer installed
- a free Heroku account
- the Heroku CLI
Overview
The details of Heroku’s PHP Support are described in the Heroku PHP Support article.
Heroku PHP Support will be applied to applications only when the application has a file named composer.json
in the root directory. Even if an application has no Composer dependencies, it must include an empty composer.json
in order to be recognized as a PHP application.
Manage dependencies
Heroku uses Composer for dependency management in PHP projects. If your app has any dependencies, the composer.json
file should specify them. It will look something like this:
{
"require": {
"monolog/monolog": "^3.0",
}
}
Your PHP app can then make use of the dependencies that Composer installed. Dependencies are usually installed to the vendor/
directory after including the autoloader generated by Composer, typically like this:
require('vendor/autoload.php');
Vendor libraries are usually installed to vendor/
by Composer, but some projects re-define the name of this directory. Run composer config vendor-dir
to find the right path name.
Whenever you add or change dependencies in composer.json
, you must regenerate the lock file. This lock file is important to ensure reproducible behavior for your dependencies across multiple environments. It also helps ensure dev/prod parity. To generate your composer.lock
file, make sure you have Composer installed and then type:
$ composer update
After updating your dependencies and re-generating the lock file, don’t forget to add and commit the changes to your Git repository:
$ git add composer.json composer.lock
$ git commit
Whenever an app gets deployed, Heroku reads the composer.lock
file and installs the appropriate production dependencies into the vendor
directory by running composer install --no-dev
during the build. For more information, see PHP build behavior.
Each developer on your team will run composer install
to install the same dependencies as everyone else, because composer.lock
has “remembered” them.
How to keep build artifacts out of Git
Prevent build artifacts from going into revision control by creating a .gitignore
file. The Composer vendor
directory should be included in your .gitignore
file. This keeps repository sizes small, simplifies dependency updates, and allows Composer to reliably install an application’s dependencies based on composer.lock
Here’s a typical .gitignore
file:
vendor/
.env
Specify runtimes and extensions
Optionally, you can specify which engine (PHP or HHVM) and version to use at runtime. For more information, see the selecting a runtime article.
Any PHP extensions that are not enabled by default can be enabled via composer.json
. The extensions article has a detailed list of available extensions and instructions about how to activate them.
The Procfile
A Procfile is a text file in the root directory of your application that defines process types and explicitly declares what command should be executed to start your app. Your Procfile
will look something like this:
web: heroku-php-apache2
This declares a single process type, web
, and the command needed to run it. The name, web
, is important here. It declares that this process type will be attached to the HTTP routing stack of Heroku, and receive web traffic when deployed.
Selecting a web server
Depending on the runtime (PHP or HHVM) and web server (Apache2 or Nginx) you would like to use to run your application, the command for the web
process type in your Procfile
will be different. The possible options are documented in the web servers article. For example, to use Nginx as the web server instead, the Procfile
would contain:
web: heroku-php-nginx
These boot scripts (heroku-php-apache2
or heroku-php-nginx
) accept different options and arguments for fine-tuning the configuration of your application. Please refer to Customizing web server and runtime settings for PHP for more information.
Configuring the document root
Optionally, you can use a document root for your application that’s not the root directory of your app. To do this, modify your Procfile
to add an argument at the end of the bootscript. The argument will be the name of the directory that should be used as the document root, relative to your application’s root directory.
For example, if you have a folder named public
that contains your JavaScript, CSS, images and index.php
file, your Procfile
would define the Apache web server with that directory used as document root as follows:
web: heroku-php-apache2 public/
Deploy your application to Heroku
After you commit your changes to git, you can deploy your app to Heroku.
$ git add .
$ git commit -m "Added a Procfile."
$ heroku login
Enter your Heroku credentials.
...
$ heroku create
Creating arcane-lowlands-8408... done, stack is cedar
http://arcane-lowlands-8408.herokuapp.com/ | git@heroku.com:arcane-lowlands-8408.git
Git remote heroku added
$ git push heroku master
...
-----> PHP app detected
...
-----> Launching... done
http://arcane-lowlands-8408.herokuapp.com deployed to Heroku
To open the app in your browser, type heroku open
.
One-off dynos
Heroku allows you to run commands in a one-off dyno by using the heroku run
command. Use this for scripts and applications that only need to be executed when needed, such as maintenance tasks, loading fixtures into a database, or database migrations during application updates.
For example, you can use heroku run
to do a database migration for your application using Doctrine by doing something similar to this:
$ heroku run "php app/console doctrine:migrations:migrate"
Running `php app/console doctrine:migrations:migrate` attached to terminal... up, run.4062
Migrating up to 20100416130452 from 0
>> migrating 20100416130452
-> CREATE TABLE users (username VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL) ENGINE = InnoDB
>> migrated
For debugging purposes, such as to examine the state of your application after a deploy, you can use heroku run bash
for a full shell into a one-off dyno. But remember that this will not connect you to one of the web dynos that may be running at the same time.
$ heroku run bash
Running `bash` attached to terminal... up, run.5662
$ cat Procfile
web: heroku-php-apache2
$ exit
Logging
Heroku treats logs as streams and expects them to be written to STDOUT and STDERR and not to its ephemeral filesystem.
The most basic way of sending logging information is to write to the php://stderr
stream in your code like this:
file_put_contents("php://stderr", "something happened!");
Refer to the logging documentation for more general information about logging on Heroku.
Next steps
- Read the Heroku PHP Support documentation to learn about available versions, extensions, features and behaviors.
- Learn how to customize web server and runtime settings for PHP, in particular how to set the document root for your application.
- Use a custom GitHub OAuth token for Composer.
- Explore the PHP category on Dev Center.