5 PHP Components every Drupal 8 Developer should know: Part 1 -- Composer

Drupal 8 has made a lot of changes. Architectural and technical changes abound, but Drupal 8 has also brought social changes. We’re not really feeling the full effects of those changes quite yet, but with time, I believe the implications of Drupal 8’s new direction will have an amazing impact for the good of our community. A big part of those changes was the decision to adopt outside code. The 180 degree turn from a primarily NIH (Not Invented Here) culture to a PFE/PIE (Proudly Found Elsewhere/Proudly Invented Elsewhere) culture has been shocking and dramatic. We’re still feeling those effects and this series is intended to give you a jumpstart on taking advantage of all these changes.

Drupal is not the only system changing though. PHPBB, EZPublish and even non-product PHP systems at large are beginning to take advantage of the changes in PHP’s culture. This is what’s been termed the “PHP Renaissance”. Interoperability is the driving force of this renaissance and that interoperability has been fueled by a combination of:

PHP 5.3’s namespacing & object orientation capabilities
The PHP Framework Interop Group (PHP-FIG) through the creation of class autoloading specifications PSR-0 and PSR-4
The timely appearance of a tool known as Composer.

Composer, at its core, is a dependency management utility, but its ability to compose various PHP components from repositories all over the web into a coherent whole makes it an indispensable tool for the modern PHP developer. In this article we’re going to dig into the basics of Composer, discuss what it does for us, how to leverage it, and some of its exciting features.

Installation:
Getting composer installed is actually fairly straight forward and instructions for a number of different *nix approaches and Windows can be found here:
*nix Installation
Windows Installation
I would suggest the global installation. Installing per project is completely possible, but is less that ideal under most circumstances.

The Basics:
Once you have composer installed, you can begin working with it immediately. Let’s get into our htdocs folder and create a new directory.

cd /path/to/htdocs
mkdir composer_test

Once we have a directory to play around in, create and edit a composer.json file.

vim composer.json

The composer.json file’s most basic usage is just to declare the various code components you wish to utilize in your php project. If you’re familiar with Drush make this will feel very familiar (and yet foreign). If you’re not familiar with Drush make, don’t worry because we’re going to walk through every step together.

In order to declare a dependency on a particular component you need to know what component you want. In our case we’re going to just depend on a popular sub component of the larger code package known as Guzzle. You can copy and paste the following code into your composer.json file and then save it.

{
    "require": {
       "guzzlehttp/guzzle": "4.0.*"
    }
}

If you’re not familiar with JSON, this is an array definition of requirements with one item in the array. Currently we’re requiring version 4.0.x of the guzzle core component of the greater guzzlehttp library. If you haven’t saved and exited your composer.json file, do so at this time.

Protip: Composer also provides a “composer init” command that will walk you through a simple wizard to build your own composer file. This will make some assumption that were not required for this tutorial so I did not use it, but give it a spin and unpack more of the goodness that composer ships with.

With an initial composer.json file created, we can now perform the exciting task of getting our component(s) for the first time. I’m going to assume you installed composer globally, if not you should be able to supplement any call to “composer” with “php composer.phar”. For more information read this documentation. In the same directory as your composer.json simply run:

composer install

Composer is going to make a request(s) to a site called packagist, which can be use to find other PHP components. It find any required components in the composer.json file and downloads the specified version of them into a newly created vendor directory. Since we asked for the 4.0.x version of Guzzle, we’ll get the newest point release in the 4.0 branch. In addition, Composer will generate a composer.lock file in the same directory as our composer.json file.

Unlike Drush make, Composer is actually taking an extra step to protect us and our collaborators with the lock file. If you’ve worked with Drush make for a while now, you’ll know that pinning specific versions of modules is heavily encouraged as a best practice. This is done in order to ensure that your version of modules, and a fellow developer’s version of modules in the same install profile are always the same. While you can certain pin a specific version of a component to get in composer, the lock file actually indicates exactly which version was delivered to you when you installed the component initially, and now all your collaborators will get the same version of that component. This means the lock file has to be intentionally updated and committed back to the shared repository before other developers are going to get a new version. This is a good thing, and worth the extra step, because updating your code is an important step that the whole team should be aware of and should NEVER happen implicitly. This is one of the sanity saving features of Composer and it is often overlooked and misunderstood.

At this point you should have the guzzle component installed in the vendor directory, so let’s investigate what we just got:

cd vendor/guzzlehttp
ls -l

You should have two directories here, guzzle and streams. This may seem odd since we only asked for “guzzle” so let’s investigate further.

cd guzzle
ls -al

The first thing to take note of here is that there’s a composer.json file present here as well. Let’s take a look at that.

vim composer.json

This has a lot more in it that just a simple list of requirements, though if we look at the values in the “require” array, we’ll notices first that this components requires php 5.4.0 or greater and that it requires the 1.x version of “guzzlehttp/streams”. This explains why we have the streams directory inside of vendor/guzzlehttp.

There are other things of note within this file. First off the code we just downloaded is licensed MIT. It also has a name and a description, some keywords by which it can be found and some custom autoloading instructions for particular namespaces and particular files. If you’re familiar with Drupal’s traditional .info file (now a .info.yml file in Drupal 8) this should be looking remarkably similar. We could spend a lot of time dissecting every element of this composer.json file, but I’ll leave that as an exercise to the reader.

It’s worth pointing out that composer is more than just a dependency management & component downloading tool, it also happens to create and manage a very capable class autoloader. Let’s look at what composer has already set up for us in this regard. In your vendor directory you will notice there is also a “composer” directory, so let’s check out what we have here.

cd vendor/composer
ls -al

composerdir.png

There are a number of different files here. The first two I’d like to draw your attention to are ClassLoader.php and autoload_real.php. We’re not going to dig into these too much except to point out that they are primarily responsible for the autoloading process that occurs. The autoload_real.php file has a class with a hash for a name in it, and this will correspond to at least one other place in the code base for the autoloading process. More interesting are the various other autoload_*.php files. Each of these has a different purpose, so as a quick overview these are the functions they serve:

files: An index of files containing namespaced raw functions. This has a special notation in the composer.json
namespaces: An indexed array of PSR-0-following namespaces to their corresponding directories (currently empty because of how Guzzle is setup)
psr4: An indexed array of PSR-4-following namespaces to their corresponding directories (not empty since Guzzle leverages PSR-4)
classmap: An indexed array of full class names to full file paths. (again currently empty)

This is super interesting because we can immediately learn a number of things just by looking at the contents of these files.

Guzzle is using the PSR-4 autoloading standard.
Guzzle has a number of namespaced functions in addition to their classes.

As we intermix various projects these files will fill out more and more, however I’d like to draw your attention to the classmap as this is a great feature of composer. In order to get the fastest autoloading experience you want a classmap at your disposal, and composer can build one for you. This process essentially finds every single class and their corresponding file making it a simple include call in order to get access to a class. Composer doesn’t generate this for all classes out of the box, but it can be made to do so with a single command, and any time you add a new component to your project, you should probably run this command: (do so from the directory where our initial composer.json was generated)

composer dump-autoload -o

After successfully running this command you can:

vim vendor/composer/autoload_classmap.php

And you’ll see you have something that should look like this:

classmap.png

This is a list of every single component class that resides within our code base thus far (excluding Composer’s classes). For any code that has the autoloader available simply stating:

// This will initialize composer’s autoloader
$loader = require_once __DIR__ . '/vendor/autoload.php';
// Instantiates a new guzzle client.
$client = new GuzzleHttp\Client();

This would yield a new Guzzle Client.

Protip: The classmap autoloader should generally be used in production only. During development it could necessitate rebuilding your classmap regularly if you are actively creating/renaming/deleting classes in your own custom component(s).

From a Drupal perspective this is great because we no longer have to add class containing files to the *.info file in order to get them autoloaded, and we’ve standardized on the same class autoloading standard(s) as the rest of PHP. Modules currently support both PSR-0 and PSR-4 class autoloading, and this is really powerful because it begins to open to door to more portable code coming into Drupal and in the future, perhaps allowing our code to be portable outside of Drupal.

There are a lot of really great things Composer can do that I’ve not even touched the surface of in this blog post, but in my follow up posts we’ll continue to use Composer to build our example project. I’ll add links to the documentation below and hopefully you’ll find Composer to be a powerful ally in your future projects.

Comments

Posted on by Ashok Modi (not verified).

First off, great article.

Based off where you say "Modules currently support both PSR-0 and PSR-4 class autoloading", I wanted a clarification. I recall hearing during Drupalcon that PSR-0 support was going to be for a short time while developers become accustomed and move over to the PSR-4 structure. Is that no longer the case (and that PSR-0 support is here to stay)?

Posted on by Kris Vanderwater.

Yeah, I was unclear on this as well. I think the intent it to support PSR-0 until core modules are transitioned to PSR-4. Both are great and you should understand both standards, but PSR-4 is a natural fit for modules and the standard you're more likely to see going forward.

Posted on by Anonymous (not verified).

That is a JSON object not a JSON array. {} are used for objects [] are used for arrays.

Posted on by Kris Vanderwater.

Heh, caught me. :-)

Posted on by Oscar Merida (not verified).

I didn't see it explicity in your article but readers should be aware that you do not want to commit your /vendor directory to git, or whatever your VCS repo is using. You *should* commit the composer.lock file, so everyone uses the same versions of a module.

Posted on by Kris Vanderwater.

That's a great point Oscar, and I failed to mention it. Thanks for pointing it out.

To just dig into that more the composer.lock will assure that other developers get the same code in /vendor across all devs in the team, so you don't have to commit code in /vendor to your VCS.

Again thanks Oscar, great catch.

Posted on by Oscar Merida (not verified).

You're welcome! I've also learned that using --prefer-dist can help minimize update frequency to the vendors/ directory. If I understand it correctly, composer would then download and install a zip or other packaged file instead of cloning a repository.

Posted on by Kris Vanderwater.

Care to write up a small snippet example for people who read this?

Posted on by Aaron Manire (not verified).

Just a note that the contents of

----
cd vendor/guzzlehttp
ls -l
----

are not what the screenshot shows above. I think you meant to say

----
cd vendor/composer
ls -l
----

and then cd over to ../guzzlehttp/

Posted on by Kris Vanderwater.

Indeed, I misplaced the image when I brought the document into Drupal. Thanks for pointing that out. Very appreciated.

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.

Filtered HTML

  • Use [acphone_sales], [acphone_sales_text], [acphone_support], [acphone_international], [acphone_devcloud], [acphone_extra1] and [acphone_extra2] as placeholders for Acquia phone numbers. Add class "acquia-phones-link" to wrapper element to make number a link.
  • To post pieces of code, surround them with <code>...</code> tags. For PHP code, you can use <?php ... ?>, which will also colour it based on syntax.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <h4> <h5> <h2> <img>
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.