Better Dependency Management In Team-Based WordPress Projects With Composer

Advertisement

WordPress has come a long way since its genesis in 2003. Once reserved for humble blogs, it now powers websites for some of the world’s largest companies1 and is even being promoted as a platform to power the next generation of Web apps.

As a result of this increasing popularity, over the last couple of years my team and I have been regularly tasked with building ever more complex WordPress websites and apps. As the sizes of these projects increased and our team grew, however, we noticed that keeping the various dependencies of a given project in sync across our development team was becoming increasingly difficult. With different developers joining a project at any given time, plugin versions became out of sync and different releases of WordPress core were being used. We soon realized that the situation was getting rapidly out of hand, leading to divergent code bases, as well as increasing the likelihood of errors being introduced into our projects.

In this article, I’ll share with you how my team has used the PHP dependency-management tool Composer to streamline our development processes and to maintain our WordPress project dependencies across the development team consistently and reliably.

The article will pan out as follows:

  • We’ll start with some context, a brief introduction to dependency management, including more on why it’s important and the benefits of the process.
  • Next, we’ll introduce Composer, covering the basics before moving on to how to use it to manage WordPress dependencies.
  • The meat and potatoes of the article will be to retrofit an existing project with Composer for dependency management (there’s a GitHub repository for that2).
  • We’ll learn a neat way to define WordPress core itself as a Composer dependency, as well as learn how to maintain in-house plugins using private GitHub repositories.
  • We’ll round things up with a list of resources to take your Composer skills to the next level.

If you’re ready, let’s get going.

What Is A Dependency?

First things first. Let’s define what we mean by a “dependency.”

A dependency is typically a library, framework or component, usually provided by a third party and upon which your website’s functionality depends. It could be a simple date-conversion library3 or an entire framework.

As you can imagine, a typical website depends on several libraries, each of which provides prebuilt functionality on which to base your code. These elements are an integral part of the website’s code base; as a result, it’s critical that all developers work with an identical set of these dependencies at all times.

To facilitate this, we can define a process for managing the various libraries, frameworks and components on which a particular code base depends. This dependency-management process is often controlled with a central tool that keeps track of the versions of the packages required by a project.

Dependencies In The Context Of WordPress

So, what are dependencies in the context of WordPress?

A typical WordPress project has several dependencies. These might include the following:

  • Plugins
    Many plugins provide functionality that is critical to the operation of websites.
  • Themes
    Although most themes are customized, a parent theme could warrant being defined as a dependency.
  • WordPress core
    This is the core framework, without which the website would not function at all!

Unfortunately, all too often little attention is paid to managing these critical dependencies consistently and reliably. As a team gets larger, getting into a situation where different developers have different dependencies installed is quite easy.

For example, imagine Developer A and Developer B are working on a WordPress project that uses the Advanced Custom Fields (ACF) plugin. The functionality of the website depends on version 3 of this plugin. One day, Developer A needs to implement a new feature, but he discovers that version 3 of ACF doesn’t provide the functionality he requires. Luckily, a new version is out that will solve his problems. Developer A downloads and upgrades ACF to version 4 and implements the new feature in double quick time. Unfortunately, Developer B isn’t aware of the upgrade and continues to work on other functionality using version 3 of the plugin. At this point, the project has a major problem, with the two developers working with different dependencies on what is now, in effect, two different code bases. Granted, this example is a tad contrived, but it’s easy to see how a problem like this could occur.

Small teams with good direct communication are more easily able to avoid such problems. In large distributed teams, the problem can quickly get out of hand and dramatically increase the likelihood of errors being introduced into the project’s code — errors that can and will cause major headaches down the line (usually on launch day!).

Benefits Of A Dependency-Management Tool

As you can see, if you’re going to be doing any serious team-based development on WordPress, then tools and processes for managing your dependencies will make your life a heck of a lot easier.

The benefits of a managed approach include the following:

  • Consistency
    All team members can be confident that the project’s dependencies are locked to specific versions, ensuring that everyone is developing from an identical platform.
  • Visibility
    The project’s dependencies are clearly defined in a single place and, thus, easily viewable by participants in the project.
  • Ease of use
    Management is handled by a single tool, simplifying and streamlining the installation and updating processes.

“Why Can’t I Just Check Everything Into My VCS And Be Done With It?”

This issue often arises in discussions on the merits of a dependency-management system. The question usually runs something along these lines:

Why should I go to the trouble of learning and introducing a new tool into my workflow when just checking all of my dependencies directly into version control works perfectly?

The short answer is that one way is no more correct than the other. Dependency-management tools generally don’t replace the need for version control systems. They are different tools that do different jobs. Nevertheless, using a dedicated tool to manage your dependencies might be preferable for a couple of reasons.

First, a good dependency-management tool will eliminate the requirement to check third-party code into your VCS. This reduces bloat in your repository, making it quicker and easier for new developers to download and clone and to start working on your project.

Secondly, it provides increased visibility into when your dependencies are being upgraded. For example, have you ever made a pull from a repository, only to find 10 minutes later that a particular library has stopped working because another developer upgraded a dependency without telling you? If your dependencies are all checked into source control, then it’s perfectly conceivable that, when pulling the latest updates from your repository, you might not notice that a dependency has been updated. In contrast, a dependency-management tool requires you to execute a specific command to update your dependencies, which will (hopefully) provide clear feedback on which libraries have changed. This makes it harder to miss a change to one of your dependencies, which mitigates the chance of an error.

Nonetheless, remember that just because you’re using a dedicated dependency-management tool doesn’t necessarily mean you should avoid checking your third-party libraries into source control (or, indeed, that you should stop using source control at all). In fact, many developers recommend this approach because it avoids making any one tool a critical point of failure for your application’s deployment process. This is a debate in its own right, so I won’t attempt to cover it in any detail here.

Ultimately, determining whether using a source control system to manage your project’s dependencies works for you is up to you as the developer. I would suggest, though, that you choose the right tool for the job. Leave versioning to Git, and manage and track your dependencies with a tool designed for the task.

Using Composer For Dependency Management

That debate aside, as WordPress developers seeking the benefits of proper dependency management, we can use the PHP tool Composer4.

Most coding languages have a system to manage dependencies — Node.js’ NPM5 and Ruby’s Bundler6 are prime examples. Composer is PHP’s offering, and in recent years it has established itself as the dependency-management tool for PHP.

Composer adopts the concept of “packages,” distinct groups of (mostly) PHP code that can be described by means of a manifest file that contains meta data about each package (including its own dependencies).

As outlined on the official website, Composer allows you to:

  • declare dependent libraries for your project,
  • automate the installation of those dependent libraries.

Luckily, this meets our objectives perfectly, which is great news!

Aside: I am aware of the PEAR library, which has been available for PHP for some time. This article is not suited to a debate on the merits of Composer versus PEAR. For more information, please read “Packages: The Way Forward for PHP7” by Phil Sturgeon8, who also kindly provided an initial technical review of this article.

Defining a Package With Composer

In Composer, every project is a package9. To define a package, simply add a composer.jsonfile to the root of the project’s directory. The full composer.json schema10 is exhaustive, but the key element is the require statement, which details the project’s dependencies, along with a version number or range. For example:

"require": {
    "vendor/package" : "1.3.2", 
    "vendor/package2": "1.*", 
    "vendor/package3": ">=2.0.3"
}

Note that we define each of the packages that we require and provide a range to denote which version of the package this project depends on. For full details on defining Composer packages, please refer to the official documentation11.

Where to Find Packages

By default, Composer will look for your defined packages on Packagist3012, its official online repository. Nonetheless, defining your own custom repositories is possible (which we’ll do later to install our WordPress plugins from the official plugin repository).

Using Composer To Manage WordPress Project Dependencies

Composer has been widely adopted in the PHP community, but until fairly recently it has not gained much traction with mainstream WordPress developers. This may be due in part to a misconception that WordPress is in some way incompatible with Composer’s workflow.

In fact, taking advantage of Composer to manage dependencies in a WordPress project is perfectly possible. We just need to be creative in how we define plugins and themes as packages so that they can be managed with Composer’s tools.

Project: Converting An Existing WordPress Project To Use Composer For Plugins

The remainder of this article will focus on converting a sample WordPress project to use Composer to manage its dependencies.

All of the code for the following steps is available in a GitHub repository13. Be sure to check out the tagged releases14, each of which matches up with the points in the process below.

If you’re ready, let’s get started.

1. Review the Current Project

To kick things off, you might want to clone a copy of the dummy project that I’ve created. For the purpose of this article, I’ll assume you have Git set up and have worked with GitHub before.

To start, clone a copy of the dummy project that I’ve created.15
To start, clone a copy of the dummy project that I’ve created. (Large preview16)

To get started working with a copy of the code, do the following:

  1. Clone the repository.
    git clone­­ --recursive git@github.com:getdave/smashingmag­-wordpress-­composer.git
  2. Check out tag 1.0.0.
    git checkout tags/1.0.0

Be sure to run the initial Git clone using the --recursive flag, which will ensure that all submodules are also cloned.

Now, let’s review the current state of our project. The initial files may also be viewed online in tag 1.0.017.

Our project’s directory.18
Our project’s directory. (Large preview19)

Looking at the code, the first thing that might appear unusual is that I have stored WordPress core as a Git submodule20 in the wp directory. (If you are missing the contents of the wp directory, please run git submodule update ­­init from the root of your project’s directory.) This is to avoid having to check WordPress core into the repository. Achieving this does require some custom configuration, but it’s relatively simple. (If you’re interested in learning more, Antti-Jussi Kovalainen has a good write-up21.)

Other than the aforementioned submodule, however, you can see that we have a fairly typical WordPress set-up. We have a theme22 to provide some styles and a few plugins23 to provide functionality that we might need during the project’s development.

A few points to note:

  • We will assume, for the sake of argument, that several plugins are required for this website to function.
  • The source code for all of the plugins has been directly checked into our Git repository.
  • We have no explicit process to track or manage the versions of our plugin dependencies.

2. Install and Initialize Composer

Now we’re ready to start converting our project to use Composer. If you haven’t already, install Composer.

Install and initialize Composer.24
Install and initialize Composer. (Large preview25)

Installing Composer used to be fairly tricky, but it has improved in recent months. Nonetheless, the installation process varies from platform to platform, so the best advice is to read the installation documentation26 over on the official website. I prefer to install Composer globally27, so that I can run it directly using the composer command, and I’ll assume you will do the same.

Once you’ve installed Composer, cd into your project directory and run the following command:

composer init

Answer all of the prompts as required, but answer “no” when asked whether you’d like to declare any dependencies, because we’ll be doing this manually in the next step.

The init command will, unsurprisingly, initialize a new Composer project in your current working directory. You should see that a new composer.json28 file has been created. This is the manifest file where we will declare information about our project’s dependencies.

You can see the intended file structure in tag 2.0.029 of this article’s GitHub repository.

3. Declare Our Plugin’s Dependencies

Now comes the fun part. Let’s declare our project’s plugin dependencies and get rid of the need to track our plugin’s source files directly into the Git repository.

The first thing to do is tell Composer where to find our packages. As explained earlier, Composer defaults to looking for packages in the official Packagist3012 repository. In spite of this, providing Composer with information about additional repositories that it could consider when searching for packages is possible (more information is available on defining custom repositories)31. This is particularly helpful in our case because WordPress plugins are not tracked into Packagist.

The WordPress Packagist.32
The WordPress Packagist. (Large preview33)

We could create and host our own custom repository34, but luckily Outlandish35 has created the excellent WPackagist36, a custom repository that provides a near real-time mirror of WordPress’ plugin directory37 as a Composer repository. We can tell Composer about this new package source by adding the following entry to our composer.json file:

"repositories" : [ 
  {
    "type" : "composer",
    "url"  : "http://wpackagist.org" 
  }
]

Now that Composer knows about WPackagist, we can simply add our plugins to the require section of the composer.json file, being sure to specify wpackagist as the vendor name. Composer will then request them from WPackagist:

"require" : {
  "wpackagist/advanced­custom­fields" : "4.2.*", 
  "wpackagist/posts­to­posts"         : "1.6.*", 
  "wpackagist/members"                : "0.2.*"
},

The format in which you declare the plugins is critical. One tiny mistake and you’ll be getting errors when you come to install the packages. (Note that tags prior to 5.0.1 contain an error in the wildcard syntax of the package versions. This has been corrected to * in tag 5.0.138. Please refer to the official documentation4039 for more information.)

For each plugin dependency, you should have the following:

  1. Package name
    This must be in the format of wpackagist/[plugin name].
  2. Version constraint
    This refers to the version of the plugin that you wish to install (see the official documentation4039).

For WordPress plugins, here is the best method I’ve found for ensuring that the information is correct:

  1. Look up the plugin you wish to declare in WordPress’ plugin directory.
  2. Copy the plugin’s URL slug from your browser’s address bar, and use this to form the [plugin name] portion of the package name (see above). For example, advanced-custom-fields.
  3. On the plugin’s Web page, click on the “Changelog” tab, and copy the reference to an explicit version that you wish to install. Use this value to populate the version constraint41.

Please note that Composer expects the version constraint to conform to semantic versioning42 for tagged releases. Unfortunately, a few plugins in WordPress’ plugin directory don’t follow this standard; thus, you might get the odd error relating to minimum stability. In this case, the best thing to do is contact the author of the plugin and request that they adopt a semantic versioning policy.

Our composer.json file.43
Our composer.json file. (Large preview44)

The keen-eyed among you will have noticed that we haven’t declared the “Debug Bar” plugin as a dependency. I’ve intentionally left this until last to demonstrate a way to declare plugins that are required only for development of a project and not for production. To do this, we simply add a new section to our composer.json file, as follows:

"require­dev" : { 
  "wpackagist/debug­bar" : "0.8.*",
},

Thus, dev packages will be installed by default, but you can choose to exclude dev packages45 on installation by passing additional flags on the command line.

We’ve now declared all plugin dependencies. You should be able to view the result as tag 3.0.046 in this article’s GitHub repository.

4. Install Our Plugin Dependencies

Now that we’ve declared our dependencies, it’s time to install them. Before doing so, however, we have a bit of housekeeping to do.

First, we need to remove the source code of all of the plugins currently checked into our Git repository. This will prevent collisions when we install the plugins via Composer.

To do this, cd into the plugins directory at /content/plugins/, and use the Git rm command to remove each of the plugins listed. For example, to remove the Posts2Posts plugin’s code, we would run the following command from the /plugins/ directory:

git rm –r posts-­to-­posts

Repeat this for each plugin until all have been removed.

Secondly, Composer needs to know where to install our plugins. By default for all packages of the standard library type, Composer will assume an installation location of vendor/[vendor]/[name]. This isn’t what we want at all. Luckily, WPackagist declares all of its packages as being of the type wordpress--plugin, which alters the installation path to /wp-content/plugins/. This still isn’t quite what we want, but we can now define a custom installation location by adding a line to the composer.json file:

"extra" : { 
  "installer­paths" : {
    "content/plugins/{$name}/" : ["type:wordpress­plugin"] 
  }
}



Now, all of our plugin packages will be installed in the correct location for our directory set-up. For more detailed information on how this is achieved, see the official FAQ entry47.

48
Large preview49

Now that that’s all tidied up, we’re finally ready to install the plugins. All we need to do is run the following command from the root directory of our project.

composer install

Composer will then loop over all of our required plugins, request them from WPackagist, download them and install them in the plugins directory. You should be able to verify this by viewing the contents of the content/plugins directory.

At this point, you will notice that a new file has appeared named composer.lock. This is a file that Composer created to track the exact versions of the dependencies you’ve installed. We need to commit this into source control. When someone else comes to work on your project and runs the composer install command, Composer will download the versions of the packages defined in the composer.lock file, regardless of what is defined in composer.json. This ensures that the other developer has the exact same versions installed as you do. Sound confusing? I urge you to read the official documentation on this feature50, which might clear up a few misunderstandings about updating dependencies.

As a last bit of housekeeping, we can now add the content/plugins directory to our .gitignore file because we no longer need to track the plugins’ source code into our Git repository.

We’ve made great progress! You can see the result in tag 4.0.051 of this article’s GitHub repository.

Success!

If you’ve been following along, you have successfully converted your first WordPress project to Composer-based dependency management. We now have a way to monitor, manage and install our plugin dependencies, and we no longer need to track source code into Git. What’s more, when a colleague wants to work on the project, they can simply clone our repository and run composer install to grab the plugins’ dependencies. Awesome!

But that isn’t the end. You can do so much more with Composer. To dive a little deeper, read on.

WordPress Core As A Composer Dependency

In this section, we’ll learn how to define WordPress core itself as a Composer package. I should say that this technique is a bit cumbersome because WordPress core itself isn’t yet a Composer package52. Nonetheless, there are ways around that, so let’s get started.

First, create a custom repository of the type package53. We’ll use this repository type when the project we want to use does not directly support Composer. The example below defines a package repository for WordPress core.

{
  "type"    : "package", 
  "package" : {
    "name"    : "wordpress", 
    "type"    : "webroot", 
    "version" : "3.7.1", 
    "dist"    : {
      "url"  : "http://wordpress.org/wordpress­3.7.1.zip",
      "type" : "zip" 
    },
    "source" : {
      "url"       : "https://github.com/WordPress/WordPress", 
      "type"      : "git",
      "reference" : "3.7.1"
    },
    "require" : { 
      "fancyguy/webroot­installer" : "1.0.0"
    }
  }
}

As you can see, we’re defining the repository’s type as package and setting a direct download location that points to a ZIP file of the latest version of WordPress.

We’ve also set the package type to be webroot. This is because we’re implementing the required attributes to use the webroot installer package54 to allow us to install WordPress in a custom directory.

Next, we append a couple of new lines to our existing extras object:

"extra" : { 
  "installer­paths" : {
    "content/plugins/{$name}/" : ["type:wordpress­plugin"] 
  },
  "webroot­dir"     : "wp",
  "webroot­package" : "wordpress" 
}

This sets the installation directory of the wordpress package that we defined above to be /wp/, which is the same as what it was when we were using Git submodules.

Lastly, we need to add both webroot-installer and wordpress packages to our require section so that they will be added when we next run composer install. The following lines are required:

"wordpress"                 : "3.7.1", 
"fancyguy/webroot­installer" : "1.0.0"

If we’ve done everything correctly, we should be able to run composer update and then composer install55 to update our dependencies from composer.json and download them to our project. It might take a while to download, but you should see WordPress core installed to the wp directory as it was previously — only now it will be managed via Composer. You can view the final project set-up over in tag 5.0.056 of this article’s GitHub repository.

The big downside to this approach is that for each new version of WordPress, you’ll have to define a new package repository. This method, while simple, does make composer.json a bit bulky once you’ve tracked a few WordPress releases. A better approach might be to host your own package repository57 and pull in your dependencies from there.

Using Private Repositories

Another technique that my team has found to be extremely useful is to use private GitHub repositories as dependencies.

Note that Composer doesn’t require a package to be publicly available via Packagist (or indeed WPackagist) for it to be included as a valid dependency. The VCS repository58 type enables developers to list libraries hosted on GitHub, Bitbucker or elsewhere as valid dependencies.

Taking this a step further, Composer also allows you to include private VCS repositories not meant for public consumption. My team uses this method to include private repositories for our suite of in-house WordPress plugins as dependencies in our client projects.

Achieving the correct set-up to include VCS repositories is relatively simple. The only requirement for private repositories is that you must set up valid SSH keys to allow interaction with the repository in question.

To include a GitHub repository as a dependency, first tell Composer where to find it. This means adding a new item to the repositories section of the composer.json file. It might look like the following:

"repositories" : [ 
  {
    "type" : "composer",
    "url"  : "http://wpackagist.org" 
  },
  {
    "type" : "git",
    "url"  : "git@github.com:my-github-profile/my-example-repo-name.git"
  }
]

If you’ve been following along, you’ll notice that we’ve already had to do something similar to tell Composer where to find the non-default WPackagist repository. However, while the type of WPackagist is composer, for GitHub repositories, we must specify git to instruct Composer that this is a VCS repository of the type Git. Next, we simply provide the URL for the repository in question. In this case, it’s on GitHub, which makes things nice and simple.

With this in place, all we have to do is add a line to the require section to tell Composer that we want to require the GitHub repository to be listed as a dependency:

"require" : {
  "my-github-profile/my-example-repo-name" : "1.0.0"
}

Note that this technique works best when your repository’s tagged releases follow a strict semantic versioning policy, because Composer is pretty picky about this. When used correctly, though, the technique enables you to maintain private plugins as though they were hosted on Packagist, to update them with ease and to completely avoid the slightly laborious process that WordPress provides for uploading custom plugins. Results!

This Is Just The Beginning

This article has only scratched the surface of what’s possible with Composer. There are yet so many possibilities for you to explore!

I strongly encourage you to check out the following resources, which I’ve found to provide some great advice on Composer in general and on using Composer with WordPress specifically:

  • Your Guide to Composer in WordPress59, Andrey “Rarst” Savchenko
    Savchenko is the leading guru on using Composer with WordPress. He has a growing Web resource dedicated entirely to the subject, a must-read for anyone looking to take things a little further.
  • Composer Documentation60
    The official documentation is well written and very digestible. I strongly recommend reading the key sections before diving deep on your own. You’ll thank yourself later!
  • Composer Cheat Sheet for Developers61,” JoliCode
    JoliCode62 has produced an interactive guide to the composer.json schema. It’s an invaluable tool for understanding the composition and scope of a composer.json file.
  • Bedrock63, Roots
    If you’re really looking to take things to the next level, the guys over at Roots have produced Bedrock, a foundation for WordPress projects that has Composer (among other things!) baked in as standard.

Over to you. Go forth and manage your WordPress dependencies the right way with Composer!

(ah, al, il)

Footnotes

  1. 1 http://vip.wordpress.com/clients/
  2. 2 https://github.com/getdave/smashingmag-wordpress-composer/tree/master
  3. 3 https://packagist.org/packages/jenssegers/date
  4. 4 https://getcomposer.org/
  5. 5 https://npmjs.org/
  6. 6 http://bundler.io/
  7. 7 http://philsturgeon.co.uk/blog/2012/03/packages-the-way-forward-for-php
  8. 8 http://philsturgeon.co.uk/
  9. 9 https://getcomposer.org/doc/02-libraries.md#every-project-is-a-package
  10. 10 https://getcomposer.org/doc/04-schema.md
  11. 11 https://getcomposer.org/doc/
  12. 12 https://packagist.org/
  13. 13 https://github.com/getdave/smashingmag-wordpress-composer/
  14. 14 https://github.com/getdave/smashingmag-wordpress-composer/releases
  15. 15 http://www.smashingmagazine.com/wp-content/uploads/2014/03/1-large.png
  16. 16 http://www.smashingmagazine.com/wp-content/uploads/2014/03/1-large.png
  17. 17 https://github.com/getdave/smashingmag-wordpress-composer/tree/1.0.0
  18. 18 http://www.smashingmagazine.com/wp-content/uploads/2014/03/2-large.png
  19. 19 http://www.smashingmagazine.com/wp-content/uploads/2014/03/2-large.png
  20. 20 http://git-scm.com/book/en/Git-Tools-Submodules
  21. 21 http://ajk.fi/2013/wordpress-as-a-submodule/
  22. 22 https://github.com/getdave/smashingmag-wordpress-composer/tree/1.0.0/content/themes
  23. 23 https://github.com/getdave/smashingmag-wordpress-composer/tree/1.0.0/content/plugins
  24. 24 http://www.smashingmagazine.com/wp-content/uploads/2014/03/3-large.jpg
  25. 25 http://www.smashingmagazine.com/wp-content/uploads/2014/03/3-large.jpg
  26. 26 https://getcomposer.org/doc/00-intro.md#installation-nix
  27. 27 https://getcomposer.org/doc/00-intro.md#globally
  28. 28 http://composer.json.jolicode.com/
  29. 29 https://github.com/getdave/smashingmag-wordpress-composer/tree/2.0.0
  30. 30 https://packagist.org/
  31. 31 https://getcomposer.org/doc/05-repositories.md
  32. 32 http://www.smashingmagazine.com/wp-content/uploads/2014/03/4-large.png
  33. 33 http://www.smashingmagazine.com/wp-content/uploads/2014/03/4-large.png
  34. 34 https://getcomposer.org/doc/05-repositories.md#hosting-your-own
  35. 35 http://outlandish.com/
  36. 36 http://wpackagist.org/
  37. 37 http://wordpress.org/plugins/
  38. 38 https://github.com/getdave/smashingmag-wordpress-composer/tree/5.0.1
  39. 39 https://getcomposer.org/doc/01-basic-usage.md#package-versions
  40. 40 https://getcomposer.org/doc/01-basic-usage.md#package-versions
  41. 41 https://getcomposer.org/doc/01-basic-usage.md#package-versions
  42. 42 http://semver.org/
  43. 43 http://www.smashingmagazine.com/wp-content/uploads/2014/03/5-large.jpg
  44. 44 http://www.smashingmagazine.com/wp-content/uploads/2014/03/5-large.jpg
  45. 45 https://getcomposer.org/doc/04-schema.md#require-dev
  46. 46 https://github.com/getdave/smashingmag-wordpress-composer/tree/3.0.0
  47. 47 https://getcomposer.org/doc/faqs/how-do-i-install-a-package-to-a-custom-path-for-my-framework.md
  48. 48 http://www.smashingmagazine.com/wp-content/uploads/2014/03/6-large.png
  49. 49 http://www.smashingmagazine.com/wp-content/uploads/2014/03/6-large.png
  50. 50 https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
  51. 51 https://github.com/getdave/smashingmag-wordpress-composer/tree/4.0.0
  52. 52 https://core.trac.wordpress.org/ticket/23912
  53. 53 https://getcomposer.org/doc/05-repositories.md#package-2
  54. 54 https://github.com/fancyguy/webroot-installer
  55. 55 https://getcomposer.org/doc/03-cli.md#update
  56. 56 https://github.com/getdave/smashingmag-wordpress-composer/tree/5.0.0
  57. 57 https://getcomposer.org/doc/05-repositories.md#hosting-your-own
  58. 58 http://getcomposer.org/doc/05-repositories.md#vcs
  59. 59 http://composer.rarst.net/
  60. 60 http://getcomposer.org/doc/
  61. 61 http://composer.json.jolicode.com/
  62. 62 http://jolicode.com/
  63. 63 https://github.com/roots/bedrock

↑ Back to topShare on Twitter

Dave Smith is a front end developer based near the city of Bath, UK. When he’s not working on the web he can be found playing the trumpet in everything from Big Band jazz groups to Symphony orchestras. You can catch up with Dave on Twitter as @get_dave.

Advertising
  1. 1

    Note that while using WP with webroot installer seems to be quite popular another option is johnpbloch/wordpress package which uses own installer, supports full range of WP versions, and is listed on Packagist.

    Highly recommended over defining core package inline.

    0
    • 2

      Thanks for pointing out that other option Rarst. It looks like a *really* good alternative and I should have mentioned it myself.

      Your input is much appreciated.

      0
  2. 3

    For grunt users, the yeoman-wordpress with yeopress theme is so cool to use.

    0
  3. 4

    Another really interesting project in the WP+Composer space is Composerpress (https://github.com/Tarendai/composerpress), plugin by Tom Nowell that will take your existing setup and generate a starter composer.json file for you based on what you already have installed, what your current setup is, etc.

    0
    • 5

      Hi John,

      Thanks so much for taking the time to suggest this tool. I’ve had a look and it looks really useful. I can see my team and I using this to retroactively update our older WordPress project installs.

      Much appreciated

      0
  4. 6

    This still doesn’t seem any better than SVN, if you know how to use that. Seems like more work than necessary to set it up for every site you work on for the benefits you might get from it. I’m sure there are people that will love it, though.

    0
    • 7

      Hi Tim,

      Thanks for your input. It’s always useful to have another perspective.

      I’m interested in how you envisage SVN being used for dependency management. Perhaps you are referring to committing all your dependencies into source control?

      If that’s the case then my feeling is that really is up to the individual developer to choose their own preference. In the article, I’ve tried to outline my own reasons for preferring a dedicated dependency management tool such as Composer over relying on committing everything into source control. However, I’m conscious that this won’t be everyone’s cup of tea!

      What I will say is that the Composer-based approach has made it much easier for my team here at Burfield to work on larger WordPress projects, especially if/when we’re working remotely. I would urge you to give it a chance even if the initial workload and learning curve is relatively steep.

      I’d be really interested to hear your thoughts.

      Many thanks again for your input.

      0
  5. 8

    I don’t really agree with the two points backing up the benefits of using Composer rather than just source controlling your dependencies.

    In terms of reducing bloat on your repo, that is true. The more dependencies you have the more the file size will increase. However, one of the biggest advantages with Git is that when a developer pulls it only pulls the latest commits from remote, not the entire repo. This means that any new developer will only have to pull the entire repo (including dependencies) once. On top of that, dependencies really aren’t that large. Less than 10MB is very typical and that’s really not not a problem unless you’re on dial up speeds.

    The second point about increased visibility when dependencies are updated I don’t get. If the dependencies are in source control and a dependency gets updated by another developer, it’s that developers responsibility to make sure it doesn’t break any code which is achievable with unit tests. Then when he commits his changes, he commits the updated dependency as well as any changes he had to make to fix existing code.

    At my workplace we use a combination of both. Composer and Bower for managing project dependencies, and then all of that gets picked up in source control. Every now and again we update a decency and if it breaks code we fix it on the spot, and then commit all those changes.

    All of that being said, every developer and their team have their own preferences. If it works for you, you’re obviously doing something right. :)

    0
    • 9

      Note that “typical” cases are very subjective and dangerous to use as argument for merit of lack of merit. I’ve worked on a project with dependencies upwards of 300 (three hundreds) megabytes in size.

      Personally I went through full cycle from excitement to total loss of faith in using version control for dependency management. Wrong tool for the job in my experience.

      0
  6. 10

    Hi Chris,

    Thanks for your input.

    You make some good points regarding repo size but I still feel there is merit to keeping dependencies out of source control in order to enforce a clear separation between project-specific code and code that has been provided by a third party. Perhaps I could have made that clearer in the article.

    As I briefly mentioned, I think this is really part of a wider discussion regarding whether or not you should commit project dependencies into source control, regardless of how those dependencies are ultimately managed. In my opinion it’s a decision that’s down to the preferences and standards of each individual team and as it sounds like your system works really well for you, I wouldn’t be advising you to change this.

    Regarding increased visibility, I take your point which you make very well. I still feel however, that using a dedicated tool does help to promote transparency when it comes to updating dependencies. There is a clear conscious effort required to run Composer which then provides an unambiguous output of which dependencies have been updated. The alternative of simply allowing dependencies to update via a pull from a source control repository is – to me at least – far less clear and thus more prone to error. Nonetheless, as you rightly pointed out, having strong Unit tests in place can help guard against these problems as it allows a developer to quickly test their code before committing. This is something I should have mentioned in the article and I’m glad you’ve raised it here so that others can consider it.

    Having read your comment, it sounds like you’re already using Composer to manage your dependencies but that you’re also checking them into source control. Again, this is a practice that’s down to personal preference and I’m certainly not advocating against it. I simply prefer to keep 3rd party code out of my repositories wherever possible. Perhaps I could have been more objective in my reasoning in the article as I appreciate that I definitely not always right! :)

    Thanks again for taking the time to discuss this and to raise some valid points. It’s much appreciated.

    0
  7. 11

    A side topic also worth mentioning is deployment and/or sharing your database with with other developers.

    The best way to do this is through Capistrano and a gem I created at https://rubygems.org/gems/wordpress-capistrano

    With this gem installed you can do commands like

    Pull the database down from the server AND update all URLs in the database to your local setting
    bundle exec cap production wordpress:db:pull

    Push your local database up to the server AND update the URLs in the database to the proper domain
    bundle exec cap production wordpress:db:pull

    Sync the wp-content/uploads folder with your local and the remote server.
    bundle exec cap production wordpress:content:sync

    The gem homepage (https://github.com/morrislaptop/wordpress-capistrano) also has some recommendations which align with your article :)

    Cheers,
    Craig

    P.S. “requiredev” should be “require-dev” in the article

    0
  8. 12

    wp directory was empty after running
    git clone­­ –recursive git@github.com:getdave/smashingmag­-wordpress-­composer.git

    so I ran git submodule update –­­init
    error: pathspec ‘­­init’ did not match any file(s) known to git.

    Was the submodule updated?

    Thanks.

    0
    • 13

      The correct update command is the init option with two dashes so:
      $ git submodule update –­­init

      @David – Might consider updating this for other users with the same issue. Thx.

      0
  9. 14

    Nice article! Comes exactly at the right time for me.
    I am wondering: With this approach, updating plugins is handled by composer. But how can I prevent me and other team members from accidentally updating plugins from the WordPress admin panel?

    0
  10. 16

    Great article David,

    The more members of the PHP that get to know Composer the better! It can really change the way a developer looks at their applications – encouraging separation of concerns and a more modular approach to code structure.

    I couldn’t help but notice, are hyphens being stripped out from the `code` sections of your article? In particular, snippets of ‘composer.json’

    0
  11. 17

    Hey David… this is *almost* perfect – but what is the purpose of naming your content folder `content` as opposed to `wp-content`? And I don’t see anything here that is going to make the wordpress site runnable: Do you need to symlink the content folder into `wp/wp-content` or something? Otherwise the `wp` directory is literally just the wordpress core files, and doesn’t include any of the plugins that composer has so nicely installed or your theme files or anything.

    What’s the best way to get it to install wp-core *and* put the correct plugins into it’s `wp-content` folder and grab the rest of the committed contents and get it in there? I tried to set “webroot-dir”: “./” to say “put it into the present directory” but that didn’t work. Any ideas?

    0
  12. 19

    Gerald@WPcustoms

    March 25, 2014 2:44 am

    Excellent article. I’m currently working with GRUNT doing less, minify, jslint, live reload and stuff.
    Pretty cool thing but I’m really missing the WP plugin parts. I’ll go through your guide again and will give composer a try.

    0

Leave a Comment

Yay! You've decided to leave a comment. That's fantastic! Please keep in mind that comments are moderated and rel="nofollow" is in use. So, please do not use a spammy keyword or a domain as your name, or else it will be deleted. Let's have a personal and meaningful conversation instead. Thanks for dropping by!

↑ Back to top