DEV Community

Cover image for PHP Deployment Best Practices When Using Composer
ryan
ryan

Posted on • Originally published at blog.amezmo.com

PHP Deployment Best Practices When Using Composer

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, 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.

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.

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. 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 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.

/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.

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 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.

Top comments (8)

Collapse
 
brandinchiu profile image
Brandin Chiu

What benefits do you get from a technique like this over leveraging something like the existing composer lock file, which I believe already skips the dependcy tree calculations which is the part that uses the most memory of your installs?

Collapse
 
rickmills profile image
Rick Mills

Nice post!

One thing to add, someone wrote a package for composer that you (generally) install into your global composer file. What it does is allows multiple simultaneous downloads streams to run at the same time.

Using my own Laravel project as a reference, before it would take ~1 minute to run. After its ~20 seconds.

Well worth taking a look at: github.com/hirak/prestissimo

Collapse
 
sonyarianto profile image
Sony AK

This is great tip :) I will try it when next composer install needed :)

Collapse
 
ryan1 profile image
ryan

Excellent!! I'm glad it helped! :)

Collapse
 
biros profile image
Boris Jamot ✊ /

So helpful, thanks !

Collapse
 
arielmejiadev profile image
Ariel Mejia

great post!

Collapse
 
ryan1 profile image
ryan

I'm so happy to hear that!

Collapse
 
machineno15 profile image
Tanvir Shaikh

Great That's So helpful for my laravel project.
also nice to see something for PHP this days.
Thanks.