Please note that this article acts as an introduction to Composer to be included with my upcoming title 'Code Bright' for Laravel. However, it could just as easily represent a guide to composer for newcomers without the intention of using the Laravel framework. Enjoy!
Composer is something special in the world of PHP. It has changed the way we handle application dependencies, and quelled the tears of many PHP developers.
You see, in the olden days, when you wanted to build an application that relied on third party dependencies you would have to install them with PEAR or PECL. These two dependency managers both have a very limited set of outdated dependencies and have been a thorn in the side of PHP developers for a long time.
When a package is finally available you could download a specific version and it would be installed on your system. However, the dependency is linked to PHP rather than your application itself. This means that if you had two applications that required different versions of the same dependencies... well. You’re gonna have a bad time.
Enter composer, king of the package managers. First let’s think about packages, what are they?
First of all, let’s forget the concept of ‘applications’ and ‘projects’ for now. The tool that you are building is called a package. Imagine a little box containing everything needed to run your application, and to describe it.
This box requires only one piece of paper (file) inside for it to be registered as a package.
Configuration
You learned JSON in the last chapter right? So you are ready for this now! Remember that I told you JSON was used for data transfer between web applications? Well I lied. It’s not that I’m nasty. It just made it easier to teach the topic with a smaller scope of its ability. I do this a lot, expect many lies!
Do you remember how JSON represents a complex piece of data? Well, for that reason, why can’t we use it within flat files to provide configuration? That’s exactly what the composer
guys thought. Who are we to argue with them?
JSON files use the .json
extension. Composer expects its configuration to live at the root of your package along with the filename composer.json
. Remember this! Laravel will use this file often.
Let’s open it up and start entering some information about our package.
{
"name": "marvel/xmen",
"description": "Mutants saving the world for people who hate them.",
"keywords": ["mutant", "superhero", "bald", "guy"],
"homepage": "http://marvel.com/xmen",
"time": "1963-09-01",
"license": "MIT",
"authors": [
{
"name": "Stan Lee",
"email": "stan@marvel.com",
"homepage": "http://marvel.com",
"role": "Genius"
}
]
}
Right, here we have a composer.json
file at the root of a package for the X-Men. Why the X-Men? They are awesome, that’s why.
Truth be told all of the options (keys) in this file are optional. Normally you would provide the above information if you intended to redistribute the package or release it into the wild.
To be quite honest with you, I normally go ahead and fill in this information anyway. It doesn’t do any harm. The configuration above is used to identify the package. I have omitted a few keys that I felt where reserved for special circumstances. If you are curious about any additional config I would recommend checking out the composer website which contains a wealth of information and documentation.
I also found this handy cheat sheet online, which may be useful for newcomers to composer when creating new packages. Mouse over each line to discover more about the configuration items.
Anyway, let’s have a closer look at the configuration we have created for the X-Men package.
"name": "marvel/xmen",
This is the package name. If you have used Github then the name format will be familiar to you, but I’m going to explain it anyway.
The package name consists of two words separated by a forward slash (/
). The part before the forward slash represents the owner of the package. In most circumstances developers tend to use their Github username as the owner, and I fully agree with this notion. You can, however, use whatever name you like. However, be sure to keep it consistent across all packages that belong to you.
The second part of the name string is the package name. Keep it simple and descriptive. Once again, many developers choose to use the repository name for the package when hosted on Github, and once again I fully agree with this system.
"description": "Mutants saving the world for people who hate them.",
Provide a brief description of the functionality of the package. Remember, keep it simple. If the package is intended for open source then you can go into detail within the README
file for your repository. If you want to keep some personal documentation then this isn’t the place for it. Maybe get it tattooed on your back, and keep a mirror handy? That makes the most sense to me. Sticky notes will also work well though.
"keywords": ["mutant", "superhero", "bald", "guy"],
These keywords are an array of strings used to represent your package. They are similar to tags within a blogging platform, and essentially serve the same purpose. The tags will provide useful search metadata for when your package is listed within a repository.
"homepage": "http://marvel.com/xmen",
The homepage configuration is useful for packages due to be open sourced. You could use the homepage for the project, or maybe the Github repository URL? Whatever you feel is more informative.
Once again I must remind you that all of these configuration options are optional. Feel free to omit them if they don’t make sense for your package.
"time": "1963-09-01",
This is one of those options that I don’t see very often. According to the cheat sheet, it represents the release date of your application or library. I’d imagine that it’s not required in most circumstances because of the fact that most packages are hosted on Github, or some other version control site. These sites normally date each commit, each tag, and other useful events.
Formats accepted for the time configuration are YYYY-MM-DD
and YYYY-MM-DD HH:MM:SS
. Go ahead and provide these values if you feel like it!
"license": "MIT",
If your package is due to be redistributed then you will want to provide a license with it. Without a license, many developers will not be able to use the package at all due to legal restrictions. Choose a license that suits your requirements, but isn’t too restrictive to those hoping to use your code. The Laravel project uses the MIT license which offers a great deal of freedom.
Most licenses require you to keep a copy of the license within the source repository, but if you also provide this configuration entry within the composer.json
, then the package repository will be able to list the package by its license.
The authors section of the configuration provides information about the package authors, and can be useful for package users wishing to make contact.
Note that the authors section will allow an array of authors for collaborative packages. Let’s have a look at the options given.
"authors": [
{
"name": "Stan Lee",
"email": "stan@marvel.com",
"homepage": "http://marvel.com",
"role": "Genius"
}
]
Use an object to represent each individual author. Our example only has one author. Let’s take a look at Stan Lee. Not only does he have a cameo in every Marvel movie, but he’s also managed to make it into my book. What a cheeky old sausage!
"name": "Stan Lee",
I don’t really know how to simplify this line. If you are having trouble understanding it then you might want to consider closing this book, and instead pursue a career in sock puppetry.
"email": "stan@marvel.com",
Be sure to provide a valid email address so that you can be contacted if the package is broken.
"homepage": "http://marvel.com",
This time a personal homepage can be provided, go ahead and leech some hits!
"role": "Genius"
The role option defines the authors role within the project. For example, developer, designer, or even sock puppetry artist. If you can’t think of something accurate then put something funny.
That’s all you need to describe your package, now let’s look at something more interesting. Dependency management!
Dependency Management
You have a box that will contain the X-Men. Only.. there aren’t a lot of mutants in that box yet. To build a great superhero team (application) you will need to enlist the support of other mutants (3rd party dependencies). Let’s have a look at how composer will help us accomplish this.
{
"name": "marvel/xmen",
"description": "Mutants saving the world for people who hate them."
"keywords": ["mutant", "superhero", "bald", "guy"],
"homepage": "http://marvel.com/xmen",
"time": "1963-09-01",
"license": "MIT",
"authors": [
{
"name": "Stan Lee",
"email": "stan@marvel.com",
"homepage": "http://marvel.com",
"role": "Genius"
}
],
"require": {
}
}
We now have a new section within our composer.json
called require. This will be used to list our dependenc... mutants. From now on I’ll be omitting the rest of the configuration, and just showing the require block to shorten the examples. Make sure you know where it really lives though!
We know that the X-Men will depend on:
- Wolverine.
- Cyclops.
- Storm.
- Gambit.
There are loads of others, but these guys are pretty cool. We will stick with them for now. You see, we could copy the source files for these guys into our application directly, but then we would have to update them ourselves with any changes. That could get really boring. Let’s add them to the require
section so that composer
will manage them for us.
"require": {
"xmen/wolverine": "1.0.0",
"xmen/cyclops": "1.0.1",
"xmen/storm": "1.2.0",
"xmen/gambit": "1.0.0"
}
Here we are listing the packages for our mutant dependencies, and the versions that we would like to use. In this example, they all belong to the same owner as the X-Men package, but they could just as easily belong to another person.
Most redistributable packages are hosted on a version control website such as Github or Bitbucket. Version control repositories often have a tagging system where we can define stable versions of our application. For example with git we can use the command:
git tag -a 1.0.0 -m 'First version.'
With this we have created version 1.0.0
of our application. This is a stable release which people can depend on.
Let’s have a closer look at the Gambit dependency.
"xmen/gambit": "1.0.0"
You should know by now that composer
package names consist of an owner and a package nickname separated by a forward slash (/
) character. With this information we know that this is the gambit
package written by the xmen
user.
Within the require
section, the key for each item is the package name, and the value represents the required version.
In the case of Gambit, the version number matches up to the tag available on Github where the code is versioned. Do you see how the versions of dependencies are now specific to our application, and not the whole system?
You can add as many dependencies as you like to your project. Go ahead, add a billion! Prove me wrong.
Listen, do you want to know a secret? Do you promise not to tell? Woah, oh oh. Closer, let me whisper in your ear. Say the words you long to hear..
Your dependencies can have their own dependencies.
That’s right! Your dependencies are also composer packages. They have their own composer.json
files. This means that they have their own require
section with a list of dependencies, and those dependencies might even have more dependencies.
Even better news, is that composer will manage and install these nested dependencies for you. How fantastic is that? Wolverine might need tools/claws
, tools/yellow-mask
, and power/regeneration
but you don’t have to worry about that. As long as you require
the xmen/wolverine
package then composer will take care of the rest.
As for dependency versions, they can assume a number of different forms. For example, you might not care about minor updates to a component. In which case, you could use a wildcard within the version, like this:
"xmen/gambit": "1.0.*"
Now composer
will install the latest version that starts with 1.0
. For example, if Gambit had versions 1.0.0
and 1.0.1
, then 1.0.1
would be installed.
Your package might also have a minimum or maximum boundary for package versions. This can be defined using the greater-than
and and less-than
operators.
"xmen/gambit": ">1.0.0"
The above example would be satisfied by any versions of the xmen/gambit
package that have a greater version number than 1.0.0
.
"xmen/gambit": "<1.0.0"
Similarly, the less-than
operator is satisfiable by packages less than the version 1.0.0
. Allowing your package to specify a maximum version dependency.
"xmen/gambit": "=>1.0.0"
"xmen/gambit": "=<1.0.0"
Including an equals sign =
along with a comparison operator will result in the comparative version being added to the list of versions which satisfy the version constraint.
Occasionally, you may wish to enter more than one version, or provide a range value for a package version. More than one version constraint can be added by separating each constraint with a comma (,
). For example:
"xmen/gambit": ">1.0.0,<1.0.2"
The above example would be satisfied by the 1.0.1
version.
If you don’t want to install stable dependencies, for example, you might be the type that enjoys bungee jumping or sky diving, then you might want to use bleeding edge versions. Composer is able to target branches
of a repository using the following syntax.
"xmen/gambit": "dev-branchname"
For example, if you wanted to use the current codebase from the develop branch of the Gambit project on Github, then you would use the dev-develop
version constraint.
"xmen/gambit": "dev-develop"
These development version constraints will not work unless you have a correct minimum stability setting for your package. By default composer uses the stable
minimum compatibility flag, which will restrict its dependency versions to stable, tagged releases.
If you would like to override this option, simply change the the minimum-stability
configuration option within your composer.json
file.
"require": {
"xmen/gambit": "dev-master"
},
"minimum-stability": "dev"
There are other values available for the minimum stability setting, but explaining those would involve delving into the depths of version stability tags. I don’t want to overcomplicate this chapter by looking at those. I might come back to this chapter later and tackle that topic, but for now I’d suggest looking at the composer documentation for package versions to find additional information on the topic.
Sometimes, you may find yourself needing to use dependencies that only relate to the development of your application. These dependencies might not be required for the day-to-day use of your application in a production environment.
Composer has got your back covered in this sithation thanks to it’s require-dev
section. Let’s imagine for a moment that our application will require the Codeception testing framework to provide acceptance tests. These tests won’t be any use in our production environment, so let’s add them to the require-dev
section of our composer.json
.
"require": {
"xmen/gambit": "dev-master"
},
"require-dev": {
"codeception/codeception": "1.6.0.3"
}
The codeception/codeception
package will now only be installed if we use the --dev
switch with composer. There will be more on this topic in the installation and usage section.
As you can see above, the require-dev
section uses exactly the same format as the require
section. In fact, there are other sections which use the same format. Let’s have a quick look at what’s available.
"conflict": {
"marvel/spiderman": "1.0.0"
}
The conflict
section contains a list of packages that would not work happily alongside our package. Composer will not let you install these packages side by side.
"replace": {
"xmen/gambit": "1.0.0"
}
The replace section informs you that this package can be used as a replacement for another package. This is useful for packages that have been forked from another, but provide the same functionality.
"provide": {
"xmen/gambit": "1.0.0"
}
This section indicates packages that have been provided within the codebase of your package. If the Gambit packages source was included within our main package then it would be of little use to install it again. Use this section to let composer know which packages have been embedded within your primary package. Remember, you need not list your package dependencies here. Anything found in require
doesn’t count.
"suggest": {
"xmen/gambit": "1.0.0"
}
Your package might have a number of extra packages that enhance its functionality, but aren’t strictly required. Why not add them to the suggest
section? Composer will mention any packages in this section as suggestions to install when running the composer install command.
Well that’s all I have on dependencies. Let’s take a look at the next piece of composer magic. Autoloading!
Auto Loading
By now we have the knowledge to enable composer
to retrieve our package dependencies for us, but how do we go about using them? We could require()
the source files ourselves within PHP, but that requires knowing exactly where they live.
Ain’t nobody got time for dat. Composer will handle this for us. If we tell composer where our classes are located, and what method can be used to load them then it will generate its own autoload, which can be used by your application to load class definitions.
Actions speak louder than words, so let’s dive right in with an example.
"autoload": {
}
This is the section in which all of our autoloading configurations will be contained. Simple right? Great! No sock puppetry for you.
Let’s have a look at the simplest of loading mechanisms, the files
method.
"autoload": {
"files": [
"path/to/my/firstfile.php",
"path/to/my/secondfile.php"
]
}
The files
loading mechanism provides an array of files which will be loaded when the composer
autoloader component is loaded within your application. The file paths are considered relative to your projects root folder. This loading method is effective, but not very convenient. You won’t want to add every single file manually for a large project. Let’s take a look at some better methods of loading larger amounts of files.
"autoload": {
"classmap": [
"src/Models",
"src/Controllers"
]
}
The classmap
is another loading mechanism which accepts an array. This time the array consists of a number of directories which are relative to the root of the project.
When generating its autoloader code, composer will iterate through the directories looking for files which contain PHP classes. These files will be added to a collection which maps a file path to a class name. When an application is using the composer autoloader and attempts to instantiate a class that doesn’t exist, composer will step in and load the required class definition using the information stored in its map.
There is, however, a downside to using this loading mechanism. You will need to use the composer dump-autoload
command to rebuild the class map every time you add a new file. Fortunately there is a final loading mechanism, and the best of all, which is intelligent enough to not require a map. Let’s first learn about PSR-0 class loading.
PSR-0 class loading was first described in the PSR-0 PHP standard, and provides a simple way of mapping PHP name-spaced classes to the files that they are contained in.
Now this isn’t a PHP book so I won’t describe namespaces in detail, but know that if you add a namespace
declaration to a file containing your class, like this:
<?php
namespace Xmen;
class Wolverine
{
// ...
}
Then the class becomes Xmen\Wolverine
and as far as PHP is concerned it is an entirely different animal to the Wolverine
class.
Using PSR-0
autoloading, the Xmen\Wolverine
class would be located in the file Xmen/Wolverine.php
.
See how the namespace matches up with the directory that the class is contained within? The Xmen
name-spaced Wolverine
class is located within the Xmen
directory.
You should also note that the filename matches the class name, including the uppercase character. Having the filename match the class name is essential for PSR-0
autoloading to function correctly.
Namespaces may have several levels, for example, consider the following class.
<?php
namespace Super\Happy\Fun;
class Time
{
// ...
}
The Time
class is located within the Super\Happy\Fun
namespace. So PHP will recognise it as Super\Happy\Fun\Time
and not Time
.
This class would be located at the following file path.
Super/Happy/Fun/Time.php
Once again, see how the directory structure matches the namespace? Also you will notice that the file is named exactly the same as the class.
That’s all there is to PSR-0
autoloading. It’s quite simple really! Let’s have a look at how it can be used with composer
to simplify our class loading.
"autoload": {
"psr-0": {
"Super\\Happy\\Fun\\Time": "src/"
}
}
This time, our psr-0
autoloading block is an object rather than an array. This is because it requires both a key and a value.
The key for each value in the object represents a namespace. Don’t worry about the double forward slashes. They are used because a single slash would represent an escape character within JSON. Remember this when mapping namespaces in JSON files!
The second value is the directory in which the namespace is mapped. I have found that you don’t actually need the trailing slash, but many examples like to use it to denote a directory.
This next bit is very important, and is a serious ‘Gotcha’ for a lot of people. Please read it carefully.
The second parameter is not the directory in which classes for that namespace are located. Instead, it is the directory which begins the namespace to directory mapping. Let’s take a look at the previous example to illustrate this.
Remember the super happy fun time class? Let’s have another look at it.
<?php
namespace Super\Happy\Fun;
class Time
{
// ...
}
Well, we now know that this class would be located in the Super/Happy/Fun/Time.php
file. With that in mind, consider the following autoload snippet.
"autoload": {
"psr-0": {
"Super\\Happy\\Fun\\Time": "src/"
}
}
You might expect composer to look in src/Time.php
for the class. This would be *incorrect, and the class would not be found.
Instead, the directory structure should exist in the following format.
src/Super/Happy/Fun/Time.php
This is something that catches so many people out when first using composer. I can’t stress enough how important this fact is to remember.
If we were to run an installation of composer now, and later add a new class Life.php
to the same namespace, then we would not have to regenerate the autoloader. Composer knows exactly where classes with that namespace exist, and how to load them. Great!
You might wonder why I put my namespaces files in a src
folder? This is a common convention when writing composer based libraries. In fact, here is a common directory/file structure for a composer package.
src/ (Classes.)
tests/ (Unit/Acceptance tests.)
docs/ (Documentation.)
composer.json
Feel free to keep to this standard, or do whatever makes you happy. Laravel provides its own locations for classes which we will describe in a later chapter.
Now that you have learned how to define your autoload mechanisms, it’s time that we looked at how to install and use composer, so that you can start taking advantage of its autoloader.
Installation
Now you might be wondering why I chose to cover installation and usage at the end of this chapter? I feel that having a good knowledge of the configuration will help you understand what Composer is doing behind the scenes as we are using it. Let me know!
The following installation methods will be specifically for unix based development environments such as Linux or Mac OSX. I’m hoping that Taylor might be able to edit this chapter and provide information on installing Composer in a Windows environment, since I avoid that particular operating system like the plague.
Composer is a PHP based application, so you should have the CLI client for PHP installed before attempting to use it. Double check this by running the following command.
php -v
If PHP has been installed correctly, you will see something similar to..
$ php -v
PHP 5.4.4 (cli) (built: Jul 4 2012 17:28:56)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies
with XCache v2.0.0, Copyright (c) 2005-2012, by mOo
If the output states that you are using anything less than PHP version 5.3.2, then you aren’t going to be able to use Composer until you upgrade you PHP version. In fact, if you are using anything less than PHP 5.3 then you won’t be able to use Laravel at all.
You can use CURL
to download composer. Mac OSX comes with it by default. Many Linux distributions will have CURL within their software repositories, if it has not already been installed as standard. Let’s use CURL to download Composer’s executable.
curl -sS https://getcomposer.org/installer | php
Experienced linux users may be concerned that CURL is piping the installation script into PHP. This is a fair concern, but the composer installation has been used by thousands of developers and has been proven to be secure. Don’t let it put you off using this lovely piece of software!
Assuming the installation process was completed successfully (it will tell you), then you will now have a composer.phar
file in your application directory. This is the executable that can be used to launch composer, for example:
php composer.phar
Will show you a list of commands that are available to you.
Now, you could continue to use composer this way, but I would suggest installing it globally. That way it can be used across all of your Composer projects, and will have a shorter command to execute it.
To install composer globally, simply move it to a location within your PATH
environmental variable. You can see these locations by using the following command.
echo $PATH
However, /usr/local/bin
is an acceptable location for most systems. When we move the file, we will also rename it to composer
to make it much easier to launch. Here is the command we need:
sudo mv composer.phar /usr/local/bin/composer
Having installed composer globally, we can now use the following shorter syntax to see the same list of commands. This command is also executable from any location on the system.
composer
Hey, that’s a lot cleaner isn’t it? Let’s start using this thing.
Usage
Let’s assume that we have created the following composer.json
file in our package directory.
{
"name": "marvel/xmen",
"description": "Mutants saving the world for people who hate them."
"keywords": ["mutant", "superhero", "bald", "guy"],
"homepage": "http://marvel.com/xmen",
"time": "1963-09-01",
"license": "MIT",
"authors": [
{
"name": "Stan Lee",
"email": "stan@marvel.com",
"homepage": "http://marvel.com",
"role": "Genius"
}
],
"require": {
"xmen/wolverine": "1.0.0",
"xmen/cyclops": "1.0.1",
"xmen/storm": "1.2.0",
"xmen/gambit": "1.0.0"
},
"autoload": {
"classmap": [
"src/Xmen"
]
}
}
Let’s go ahead and use the install
command to install all of our package dependencies, and setup our autoloader.
composer install
The output we get from composer will be similar to:
Loading composer repositories with package information
Installing dependencies
- Installing tools/claws (1.1.0)
Cloning bc0e1f0cc285127a38c232132132121a2fd53e94
- Installing tools/yellow-mask (1.1.0)
Cloning bc0e1f0cc285127a38c6c12312325dba2fd53e95
- Installing power/regeneration (1.0.0)
Cloning bc0e1f0cc2851213313128ea88bc5dba2fd53e94
- Installing xmen/wolverine (1.0.0)
Cloning bc0e1f0cc285127a38c6c8ea88bc523523523535
- Installing xmen/cyclops (1.0.1)
Cloning bc0e1f0cc2851272343248ea88bc5dba2fd54353
- Installing xmen/storm (1.2.0)
Cloning bc0e1f0cc285127a38c6c8ea88bc5dba2fd53343
- Installing xmen/gambit (1.0.0)
Cloning bc0e1f0cc285127a38c6c8ea88bc5dba2fd56642
Writing lock file
Generating autoload files
Remember that these are fake packages used as an example. Downloading them won’t work! They are however more fun, since they are X-men! Yey!
So why are there seven packages installed when I only listed four? Well you are forgetting that Composer automatically manages the dependencies of dependencies. The three extra packages are dependencies of the xmen/wolverine
package.
I’d imagine you are probably wondering where these packages have been installed to? Composer creates a vendor
directory in the root of your project to contain your package’s source files.
The package xmen/wolverine
can be found at vendor/xmen/wolverine
, where you will find its source files along with its own composer.json
.
Composer also stores some of its own files relating to the autoload system in the vendor/composer
directory. Don’t worry about it. You will never have to edit it directly.
So how do we take advantage of the awesome autoloading abilities? Well the answer to that is even simpler than setting up the autoloading itself. Simply require()
or include()
the vendor/autoload.php
file within your application. For example:
<?php
require 'vendor/autoload.php';
// Your awesome application bootstrap here!
Great! Now you can instantiate a class belonging to one of your dependencies, for example..
$gambit = new \Xmen\Gambit;
Composer will do all the magic and autoload the class definition for you. How fantastic is that? No more littering your source files with thousands of include()
statements.
If you have added a file in a class-mapped directory, you will need to run a command before Composer is able to load it.
composer dump-autoload
The above command will rebuild all mappings and create a new autoload.php
for you.
What if we want to add another dependency to our project? Let’s add xmen/beast
to our composer.json
file.
{
"name": "marvel/xmen",
"description": "Mutants saving the world for people who hate them.",
"keywords": ["mutant", "superhero", "bald", "guy"],
"homepage": "http://marvel.com/xmen",
"time": "1963-09-01",
"license": "MIT",
"authors": [
{
"name": "Stan Lee",
"email": "stan@marvel.com",
"homepage": "http://marvel.com",
"role": "Genius"
}
],
"require": {
"xmen/wolverine": "1.0.0",
"xmen/cyclops": "1.0.1",
"xmen/storm": "1.2.0",
"xmen/gambit": "1.0.0",
"xmen/beast": "1.0.0"
},
"autoload": {
"classmap": [
"src/Xmen"
]
}
}
Now we need to run composer install
again so that composer can install our newly added package.
Loading composer repositories with package information
Installing dependencies
- Installing xmen/beast (1.1.0)
Cloning bc0e1f0c34343347a38c232132132121a2fd53e94
Writing lock file
Generating autoload files
Now xmen/beast
has been installed and we can use it right away. Smashing!
You may have noticed the following line in the output from the composer install
command.
Writing lock file
You might also have noticed that composer has created a file called composer.lock
at the root of your application. What’s that for I hear you cry?
The composer.lock
file contains the information about your package at the time that the last composer install
or composer update
was performed. It also contains a list of the *exact version of each dependency that has been installed.
Why is that? It’s simple. Whenever you use composer install
when a composer.lock
file is present in the directory, it will use the versions contained within the file instead of pulling down fresh versions of each dependency.
This means that if you version your composer.lock
file along with your application source (and I highly recommend this), when you deploy to your production environment it will be using the exact same versions of dependencies that have been tried and tested in your local development environment. This means you can be sure that composer won’t install any dependency versions that might break your application.
Note that you should never edit the composer.lock
file manually.
While we are on the topic of dependency versions, why not find out about updating them? For example if we had the following requirement in our composer.json
file.
"xmen/gambit": "1.0.*"
Composer might install version 1.0.0
for us. However, what if the package was updated to 1.0.1
a few days later?
Well, we can use the composer update
command to update all of our dependencies to their latest versions. Let’s have a look at the output.
$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing xmen/gambit (1.0.1)
Cloning bc0e1f0cc285127a38c6c8ea88bc5dba2fd56642
Generating autoload files
Great! The xmen/gambit
package has been updated to its latest version, and our composer.lock
file has been updated.
If we wanted to update only that one dependency rather than all of them, we could specify the package name when using the update
command. For example:
composer update xmen/gambit
Wait, what’s that (including require-dev)
bit mean? Well you must remember the require-dev
section in the composer.json
file where we list our development only dependencies? Well composer expects the update command to be only ran in a safe development or testing environment. For this reason, it assumes that you will want your development dependencies, and downloads them for you.
If you don’t want it to install development dependencies then you can use the following switch.
composer update --no-dev
Also, if you would like to install dependencies when using the install
command, simply using the following switch.
composer install --dev
The last thing you should know, is that you can use the composer self-update
command to update the composer binary itself. Be sure to use sudo
if you have installed it globally.
sudo composer self-update
Well, that just about covers all the Composer knowledge we will need when working with Laravel. It has been a lot of information to take in, and a long chapter for these weary fingers, but I hope you have gained something from it.
If you feel that a particular topic needs expanding, be sure to let me know!