PHP Deployment Best Practices When Using Composer
Tags: php, webdev
Published: 2020-03-01 05:43:47

## Overview
Composer is the de-facto dependency manager for PHP applications which was initially released almost 8 years ago March 2012.

Using Composer in your PHP can be used to increase one’s code reusability and enable your project to easily integrate maintained PHP libraries from [Packagist](https://packagist.org), the main PHP Composer repository. Today we’ll highlight a few deployment best practices.

## Composer Can Get Slow

This post will focus on how to make composer faster and remove the need to install packages with a fresh composer install each time you deploy your application.

Magento is an example of a composer project requiring lots of memory. Can you imagine how much memory you’d need if you needed to do a composer install for each of your deployments? Composer may fail with an Out of Memory error which is described in this [Stack Overflow post](https://stackoverflow.com/questions/33299302/composer-update-failed-out-of-memory).

Although it’s easy to add packages to your project, here at Amezmo we take a conservative approach to adding a new project dependency for the following reasons.

- Slows down the initial composer install
- Each composer package increases the chances of new security issues



## Best Practices

This one is a no-brainer. Audit our composer.json file and of course remove any package references that aren’t required.

The second one, which is the reason I made this post is to ensure you’re running composer with the following flags.


```bash
composer \
    --no-ansi \
    --no-interaction \
    --optimize-autoloader \
    --no-progress \
    --no-dev \
    --profile \
    install
```

This command is documented in Amezmo’s documentation on [installing composer packages with deployment hooks](https://www.amezmo.com/docs/deployments/dependencies). Let’s go through these flags one by one


## --no-ansi

This flag disables ANSI output which means that colorful output will be disabled. Colorful output as in green and red font colors and background colors that are pleasing to the human eye. This is great for when we’re running composer manually, but for automated deployments, we don’t want to clutter our log files with strange characters.

## --no-interaction

Again, in the context of automated deployments, we do not want a deployment to be stalled waiting for input. This flag prevents composer from asking for user input.

## --optimize-autoloader

This flag tells Composer to [automize the autoloader](https://getcomposer.org/doc/articles/autoloader-optimization.md) code that gets generated. The autoloader is what gets invoked when your entry point does require 'vendor/autoload.php';

## --no-progress

Since progress reporting uses special terminal ANSI codes, we don’t want to report progress since it will clutter our log files. It’s completely unnecessary when doing non-interactive deployments and composer installs.

## --no-dev

This one is vital. We never want to install our development packages onto our production servers. Things such as phpunit and other packages that should never make it to production are considered a “dev” package. They have a special entry in the composer.json file under the “require-dev” property.

## --profile

This one is optional, but I always like to include it because it shows how much memory Composer uses to install an individual dependency.


## How to Cache Composer Packages at Deployment Time

Now that we’ve got our production-grade composer install command defined, let’s go through a simple way of making Composer faster when it comes to deploying.

Step 1.
Create a global Composer vendor directory somewhere completely outside of your webroot, and of course not publicly accessible.

Note: Amezmo uses a root directory layout as illustrated below, so we’re going to use this in our bash commands below. You can of course replace these directories with your own and the desired outcome will be achieved.


```bash
/webroot
|----logs
|----vendor
|----storage
|----current -> /webroot/release/${TIMESTAMP}.${COMMIT_ID}
|----release
|-------${TIMESTAMP}.${COMMIT_ID}
|-------${TIMESTAMP}.${COMMIT_ID
```

`/webroot/vendor` is our global wide package directory from which a link will be created for each release.

Run the following command to create the linked vendor directory from your release directory, to the global vendor directory. You must do this each time you deploy, and BEFORE running composer install from your release directory.

```bash
ln -sT /webroot/vendor webroot/release/${TIMESTAMP}.${COMMIT_ID}/vendor
```

Note it’s vital to run the above command prior to running composer install from your release directory. Here are the steps in order:

- The release directory should be created
- Run Git to get your source code
- Execute the above command,
- Finally run composer install

Having done everything in the above order, your packages will be “cached” into the `/webroot/vendor` directory and you will not need to freshly intstall your packages each time you deploy your application.

## Conclusion
- Defined a Composer command that eliminates any non-essential functionality.
- Highlighted a best-practice deployment pattern for caching Composer packages at deploy time

Our mission at Amezmo is to remove the friction in secure [PHP hosting](https://www.amezmo.com/php-hosting) and deployment and provide the best possible platform for PHP developers like myself. If you liked this post, please support the platform by hosting your code with us.