9. Composer – The PHP Workshop

9. Composer

Overview

By the end of this chapter, you will be able to describe the benefits of using a dependency manager in your application; identify high-quality, open source packages to solve common problems; add third-party libraries to your project; set up autoloading in your project so that you don't have to use include statements; and implement the Monolog logging package.

Introduction

In the previous chapter, we covered how to handle error conditions by using PHP's built-in Exception class and how to use the trycatch block to control the flow of your application.

Most modern-day applications are built on top of an amalgamation of other open source libraries. Many problems that are frequently encountered across all applications have already been solved and tested by developers who have made their solutions freely available to include in your project. This may be as small as a library that generates unique identifiers, or as large as full application frameworks that help you to organize your code. Take authentication, for example. Nearly every PHP application is going to include some form of authentication and, the majority of the time, it will be built in exactly the same way each time. We make use of third-party solutions for authentication, so we don't have to write the same authentication code over and over again in each application we write. Other examples of these types of libraries that are needed across multiple applications, known as cross-cutting concerns, are logging, security, and interacting with the filesystem. The list goes on.

With so many dependencies on external libraries, it becomes a necessity to have some tooling for the management of such libraries. In PHP, we are fortunate enough to have a great open source tool for that exact purpose – Composer. On top of that, if you are so inclined, you can leverage Composer to organize your company's frequently implemented features into a library that you use as a jumping-off point for all your applications, preventing the need to write the code over and over, and managing any updates to that library as it evolves.

In this chapter, we will explain what dependency management is and why you should be using a tool to handle it for you. We will walk you through the essential commands you will use to start using it in your projects and explain the configuration file. We will introduce you to PSR-4, one of many recommendations defined by the PHP Framework Interoperability Group (PHP-FIG), which is not exclusive to Composer but is frequently utilized to streamline the inclusion of code in a process called autoloading. We will demonstrate autoloading by setting up a sample project that uses a popular logging framework, Monolog. Finally, we will introduce you to Packagist, a website that functions as a directory listing for packages, and we will give you some tips on navigating the site and evaluating the packages you find to help you choose packages that will not only provide the functionality you need but are backed by a level of support.

Dependency Management

You may be asking yourself why we need the complexity of another tool to manage our external dependencies for us. You could always just grab a copy of the source code and put it directly in your project. The answer is made apparent by one word in the question: external. The dependencies are not your code, and you don't want to be responsible for managing them. This becomes even more apparent as you consider that those packages are likely to also depend on other libraries, which may still have dependencies themselves, and so on. This is further complicated by the fact that each of these libraries needs to be compatible with each other over time as they implement new features, bug fixes, and security maintenance releases.

Composer does all the hard work of determining whether any of the libraries you depend on have upgrades available and determining which versions of those libraries are compatible with each other, and generates a verbose list of packages and their metadata that tells it exactly what to install and where those packages can be located for installation in the project. All you have to do is use a few simple commands or edit a configuration file to give Composer a list of packages you want to include in your project and run a command to install them.

Using Composer

Composer is a tool that you will most frequently interact with from the command line. The next few sections cover the most common operations you will use day to day, with exercises for each. You will need to have Composer installed, the instructions for which are provided in the preface. Composer can be installed at a project level or at a global level on your system. Ensure that you have installed Composer globally.

Exercise 9.1: Getting Started with Composer

In this brief exercise, we will run Composer from the command line for the first time to verify that it is installed correctly, run a command that will give us a list of arguments we can pass to it in order to perform the various functions it has available, and then introduce you to the help command so that you can get summary information on any of the commands Composer has available:

  1. Open your Command Prompt and navigate to the folder where you store your code.
  2. Verify that Composer is functioning properly by checking the version you have installed by running the following command:

    composer –V

    The version number may be different, but if everything is set up correctly, you will see output similar to the following screenshot:

    Figure 9.1: Printing the version number

  3. Next, list out all of the available functions of Composer with a short summary of each using the following command:

    composer list

    You will obtain output similar to the following:

    Figure 9.2: Functions of Composer

    This is an easy way to explore the functionality of Composer and to look up commands you have used before but can't remember the exact names for.

  4. Lastly, the help command takes the name of a command as an argument and explains the usage of that feature. Call the help command, passing the init command as an argument:

    composer help init

    You will obtain output similar to the following:

Figure 9.3: Screenshot of the help command

The help command is a useful tool for looking up the specific syntax for any other command if you can't remember it, or even to discover options that may modify its behavior to suit your needs.

Initializing a Project

Now that you've seen how to call Composer on the command line, you can initialize a project with some basic settings. These are stored in a file named composer.json, which should be in your project root directory. This file will include some meta-information about your project as well as definitions of every dependency to be installed in your project. Fortunately, Composer provides a simple command to get us started: init.

Exercise 9.2: Initializing a Project

In this exercise, we will walk through the initial installation of a project using the init command. There are a few options you will be asked to configure, as you will see in the following:

  1. Create a new directory to be the project directory for this example and navigate to it. Here, we will use composer-example.
  2. From this directory, run the command to initialize a project:

    composer init

  3. Type the name you would like to choose for your package and hit Enter:

    mccollum/composer-example

  4. Enter a description and hit Enter.
  5. Hit Enter to accept the default author.
  6. Enter stable as the minimum stability.

    Note

    The minimum stability tells Composer what level of stability is acceptable when selecting which version of a package to install when you require one. The options, from most to least stable, are stable, RC, beta, alpha, and dev. Ordinarily, it's best to select "stable" for projects that will end up in production.

  7. Enter project for the package type and hit Enter.
  8. Hit Enter to skip selecting a license.
  9. Answer no to defining dependencies and dev dependencies interactively.

    The output on your screen should look similar to this:

Figure 9.4: Screenshot after confirmation

You will now have a new composer.json file listed in your project root directory. The contents of the composer.json file are output to the screen as the final step of generating the file. Open it up and take a look at it. All the information you entered during the init command should be listed in the file. You can always make changes to this file directly, but it is easier to interact with it from the command line in most cases.

Requiring Packages

At this stage, all the setup has been completed and you can begin pulling packages into your project. You only need to tell Composer that your project requires the package and Composer will determine the appropriate version of the package to install, alter the composer.json file to add the package as a dependency, and download the files for the project and place them in the vendor directory, which it will create if one does not exist.

The vendor directory is a special directory where Composer keeps all of the files it adds to your project. This is configurable if you need it to be different, but generally, it's best to keep it with the default to keep with convention. Once you require packages, inside the folder, there will be a folder for each project that will contain the source code for that library. It is important not to edit files inside this directory, or you risk your changes being lost as packages are upgraded. In general, it's a good idea to keep your own code separate from the dependencies you are building on top of.

In order to work through an example, we need to choose a package that is available to pull in via Composer. We have chosen Monolog, which happens to be developed and maintained by one of the primary developers of Composer. It is a handy library that serves as an abstraction of the logging functions that are commonly needed across all applications. It allows you to set up any number of processes that will listen for the log function to be called using a common interface and will log to their respective output, which ranges from the filesystem to NoSQL database clients, to a bucket on Amazon Web Services. If there's a place you want to capture your logs, there's a good chance that Monolog supports it and makes it easy to do so.

Exercise 9.3: Adding Dependencies

In this exercise, we will add dependencies to your project using Composer. We have selected a popular logging framework, to begin with, that we will make use of later in the chapter:

  1. In your Command Prompt, navigate to the directory where you initialized your project.
  2. Run the command to install Monolog:

    composer require monolog/monolog

    The output is as follows:

    Figure 9.5: Installing Monolog

  3. Examine the vendor directory:

Figure 9.6: Examining the directory

Inside the vendor directory, you will see the directory for Monolog as well as its dependency, psr. There is also a directory for Composer itself, and an autoload.php file. We will cover the purpose of the autoload file later in this chapter. The composer.json file will also be updated, now including a line in the require section for monolog/monolog and showing you the version of the package it selected:

Figure 9.7: Printing version

Semantic Versioning

Packages available in Composer conform to a versioning convention known as semantic versioning. This is a standardized format for increasing version identifiers that applies a meaning, on which basis the number in the identifier increases. The official documentation is located at https://semver.org/. The version is formatted so that it has three integers separated by periods. The first integer represents a major version change and indicates that the release may have breaking changes that their clients will need to rework in order to integrate with the library. The second integer indicates minor changes, such as new features, and should be backward compatible. The third number indicates bug fixes or security updates, also known as patches, and should typically be allowed to update automatically.

When a number is increased, the numbers behind it are reset to 0. For example, at the time of writing, when I installed the Monolog package, the current stable release is 1.24.0. This means that there have been 24 minor releases since the project was deemed stable and ready for production. If a bug were found in the software and they released that individually, the next version number would be 1.24.1. After that, the next release of minor features would bring the version number to 1.25.0. If they ever need to change the library in a way that breaks the consumer interface, the version would bump up to 2.0.0. This is a very useful format, and I recommend using it for your own projects within your version control system.

Applying Version Constraints

When you require a package, you may optionally specify version constraints that limit the available versions of that package that Composer may select to install. You will want to ensure that when you upgrade the packages installed by Composer, it does not automatically upgrade to a version that will be incompatible with your code base. The most common use case for this is that you only want to apply patch-level updates automatically and wait until you can test minor and major versions before releasing them alongside your code. Another example from my personal experience was a scenario when we converted a large legacy application to use Composer, which made use of a library several major versions behind the current one. It was not cost-effective to update the library, so I needed to lock it into the same version that was installed prior to being managed by Composer.

Composer offers a number of modifiers you can add to the version definition that will allow it to dynamically select a version according to your specifications. You can find a full description of the modifiers at https://packt.live/2MJNAur. The two most common of these are the next-significant-release operators: one identified by a tilde character, as in ~1.24.3, and the other a caret, as in ^1.24.0.

The tilde operator will limit upgrades to the next major or minor version, depending on whether the patch number is specified. For example, ~1.24.3 would accept any version prior to 1.25.0, while ~1.24 would accept any version prior to 2.0.0. The caret operator is similar but assumes that any non-breaking change as specified by semantic versioning would be acceptable. If ^1.24.3 were specified, this would allow any upgrade prior to 2.0.0.

Exercise 9.4: Applying Version Constraints

In this exercise, we will introduce the show command and give an example of applying version constraints to a dependency. You will also see that when you require a package, you can add the version you would like installed to the end of the command and it will target that constraint:

  1. From the Command Prompt, run the command to view the currently installed packages:

    composer show

  2. Update your requirement to the 1.0.0 version of Monolog:

    composer require monolog/monolog:1.0.0

    If you run Composer again, you will see that Monolog has been downgraded to 1.0.0:

    Figure 9.8: Screenshot of Composer

  3. Now, update the require command to accept version 1.23 or higher, but less than 2.0. Note that it will install the highest version that is less than 2.0.0:

    composer require monolog/monolog:~1.23

    Composer will again show that it has been brought back up to the current version (1.24.0 at the time of writing).

Using these constraints, you can be confident that as time passes and new versions are released by vendors, your code will be unaffected until you are ready to implement their changes. You may also notice that the version of psr/log does not change with the version of Monolog being upgraded/downgraded, as 1.1.0 satisfies both versions.

The Lock File

At this stage, if you examine the files in your project directory, you will see the composer.json file you generated with the init command, the vendor directory that was created when you required a package, and lastly, a composer.lock file. The composer.lock file is a counterpart to the composer.json file and is regenerated every time you make a modification to the required packages. If you view the contents of the file, you will see a few sections, such as _readme and a content hash, but the primary one is the packages section, which details the packages you have installed and some metadata about each that allows Composer to reliably reinstall the packages in the same configuration they have at this point in time. Each package has the name listed, the version installed, the version control type, and the URL where it can be found, as well as any required dependencies, among other things.

This is important because it allows you to consistently reproduce the installation of your entire list of dependencies using the known versions you have used during development. Imagine a scenario in which you are brought onto a team to work on a project and acme/awesome-package was required in version 1.0.0. However, by the time you join the project, version 2.0.0 has been released. Without the .lock file, you would be getting a version of the library that may be incompatible with the code base. Using the install command will make use of the .lock file to determine which versions of the packages to install, while the update command will ignore the current lock file and generate a new one with the most current versions that are compatible with all required packages. The .lock file specifies the exact versions of the packages that are installed each time you make an update to your dependencies. For this reason, both the composer.json and composer.lock files are typically committed to version control. By specifying the exact version that is installed, you can have confidence that the version you get will be compatible with your code until the point at which you explicitly update packages.

Exercise 9.5: Re-Installing Vendor Files

To show you how the composer.lock file works, we will delete the vendor directory entirely and restore the required packages with the install command:

  1. From the Command Prompt, delete the entire vendor directory:

    OSX or Linux: rm –rf vendor

    Windows: rmdir vendor

  2. View the contents of your project directory to see that the vendor directory has disappeared. You should still have both your composer.json and composer.lock files, which will allow you to reinstall your required packages by running the install command.
  3. Run the command to install the dependencies:

    composer install

    The output is as follows:

Figure 9.9: Installing dependencies

Voilà! The vendor directory is restored, with all the files and folders from your dependencies back in their usual places.

Dev Dependencies

Many of the packages your project depends on will be production code, but some of them will be libraries you use for development purposes only. A couple of examples of these would be testing frameworks and command-line utilities. Composer provides the capability to specify packages as dev dependencies, so that when you run the install command on a non-dev environment, you can pass the --no-dev flag and it will omit any development-only packages.

Exercise 9.6: Installing Development Dependencies

In this exercise, we will add the popular unit testing framework PHPUnit as a development dependency only:

  1. Install the PHPUnit testing framework:

    composer require --dev phpunit/phpunit

  2. Now, if you view the contents of the composer.json file, you will see the phpunit/phpunit package listed under the require-dev section:

Figure 9.10: Contents of composer.json

Requiring packages as dev dependencies is a way to maintain a nice separation between the code you intend to go out to production and the code that is really only meant for development purposes.

Packagist

Composer has a companion site at https://packagist.org that serves as the primary listing of all the packages available to be pulled into your project. When you are adding features to your application, you should first ask yourself whether other developers have likely solved this problem before you, and then you should check Packagist to see whether there's a package that can simplify the development of your feature. This will make you much more efficient as a developer, as you will not be spending time writing code that's been written time and time again by other developers and can focus on the code that makes your project deliver value. The cost of developing software is more than just writing code; you have to test the code and maintain it. Making a habit of using open source solutions can save you countless hours of development time in the long run. Simply search according to the keyword of the functionality you are looking for, or by the name of the package if you know it.

An important concept to understand when you are browsing packages on Packagist is that they are prefixed with a vendor namespace, followed by a slash and the name of the actual package. For example, there is a group of developers who call themselves The League of Extraordinary Packages because they produce a variety of open source libraries that are well-tested and use modern coding practices.

One of their popular packages is flysystem, a library that functions as an abstraction layer for interacting with the filesystem. The vendor name that they operate under is "league," so the name of the package is league/flysystem.

Having both the vendor name and package name combined helps by allowing projects to have the same base name, while still being able to distinguish between two different packages. In some cases, a project that has the same name but two different vendor prefixes may be a project that was abandoned by one vendor and picked up by another under the new vendor name. That's one of the great things about open source. Projects are always available to be copied and used as a starting point for extension.

Exercise 9.7: Discovering Packages on Packagist.org

In the following exercise, we will walk through an example of the way you might use the Packagist site to seek out a package and some criteria you can use as guidance for evaluating different packages so that you can choose the one that's right for your specific situation. We will search for a widely used package to handle logging functionality in our application:

  1. Open a browser window and navigate to https://packt.live/2MlwgNv:

    Figure 9.11: Packagist window

  2. In the main search bar, enter logging:

    Figure 9.12: Searching packages

    Note

    Packagist lists the number of downloads and stars a package has in the search results. It is a good idea to select packages that have as many downloads and stars as possible, as those are more likely to be quality packages and to maintain support in the long term.

  3. Click the link to view the details pertaining to the monolog/monolog package, which should be one of the first listings. At the time of writing, it has over 132 million downloads and in excess of 14,000 stars:

Figure 9.13: Details of Monolog

Note

In the panel on the right-hand side, you will see links to the repository on GitHub and to the home page for the package. These will frequently provide important instructions on how to use the package. You can review the source code of the package on GitHub. This is useful for evaluating the quality of the package.

There is a lot of information that you can glean from the details page of a package on Packagist that will help you to determine whether it is a good idea to include it in your own project. Here are some things you may want to consider: is the package in widespread use by other developers? A good indication of this is the number of stars, installs, and other packages that list it as a suggestion.

The more people that use the package, the more likely it is to be well maintained long into the future. If the project does not have as many stars and downloads as some of the other very popular projects, is it because it only applies to a narrower set of use cases, and yet is still very much in demand with this smaller group? Are there many open issues on the GitHub page for the project? Have they responded to them? How long have they been open? Are there many that have been resolved? When was the last update made to the project? Finding answers to these questions should give you a sense of whether or not the project is being maintained well.

Because the projects are open source, we will see forks and pull requests. A fork is when a developer creates a copy of the project under their own vendor name so that they can make updates to the project and most likely submit them back to the main project maintainer in a pull request. It's called a pull request because the developer that made the update is making a request to pull the update back into the main project repository. You can see on GitHub how many pull requests have been merged, and it's a really good indicator that the project will be updated as time goes on, and even allow you the opportunity to contribute back to the project if you discover a useful feature or a bug that needs to be fixed.

In the center pane of the details page, you will see two lists of other packages: one listing packages that the selected package has as its own dependencies, while the other has suggested packages. If you plan on installing a package, it's a good idea to evaluate each of the package's dependencies just as you would the original package, as they will all end up being code that your application could potentially execute. You may not be able to read every line of source code, but you should be able to get a reasonable idea of whether or not the package is respectable. The suggested packages are packages that will work with the selected package, but would not be applicable to every project that installs the package and were not therefore worth including in the main package. For example, the flysystem package we mentioned earlier has many suggestions for extensions that integrate with systems including Amazon Web Services, Azure, and Dropbox. It makes the most sense to only include the base and let users pick which extensions apply to themselves.

It is also important to take a moment to note that these packages are being made freely available over the internet, and you should also evaluate them from a security perspective and ensure that you are receiving the code you expect when you install them.

These are the important pieces of information you should consider when selecting third-party software to include in your project. If you prefer not to interface directly with Packagist, the makers of Composer provide solutions to be used in the Enterprise, Toran Proxy and Satis. These solutions function as proxies to both Packagist and GitHub and can be used to host your own company's packages, but keep them private to your own organization. Toran Proxy provider has been phased out, and Private Packagist (https://packt.live/2Beq5Ez) is recommended These days, open source software has solved many of our common problems and, with a little effort, you will often find a package to do exactly what you are looking for and you are only left to implement it.

Namespaces

Before we go on to actually using a package we have installed with Composer, let's take a brief moment to review what we learned about namespaces in Chapter 5, ObjectOriented Programming. This is a similar concept to the namespaces we just referenced on the Packagist site. However, these are built into the PHP language. Namespaces have been part of PHP since version 5.3 and most, if not all, of the libraries you come across will use namespaces. Namespaces allow multiple pieces of code that would otherwise have a name collision to exist side by side. Prior to namespaces, vendors would inconveniently have to create extraordinarily long class names that were prefixed with their vendor name and usually separated by underscores to avoid naming collisions. It is highly recommended that you use namespaces in your own code to help keep things well organized and simplify references between files.

To define a namespace in a file, it must be declared at the top of a file before any other code. Just use the namespace keyword, followed by the namespace you want to define, and complete the line with a semicolon. You can prefix a namespace in a directory structure-like manner by inserting a backslash character between the prefix and the namespace. You can use multiple levels of prefixes if you so desire. You will see an example of this in the next exercise. To reference a namespace, you can either reference a full namespace by providing an absolute path to the namespace, or you can make use of the use keyword, which will make the namespace available throughout the rest of the scope. This will also be demonstrated in the example.

Autoloading

There is one more subject we need to touch on before writing code to use one of the dependencies we installed, and that is autoloading. Autoloading is a term that refers to programmatically automating the inclusion of classes and functions external to the file you are working in. Without it, our code would be littered with include or require statements. PHP offers a function, spl_autoload_register, that accepts a function to do your autoloading for you, but Composer makes it even easier than that.

When Composer creates the vendor directory, it places an autoload.php file in it. With a little configuration in the composer.json file, if you require this one file (ideally in a central file as part of bootstrapping the rest of your application) and follow the convention for naming your files and directories, Composer will automatically include everything for you, saving you the hassle.

Using Composer Packages

Let's now walk through using a library pulled in by Composer. You can use this example of Monolog as a solid base to use for your logging in any PHP application you build. First, we will create a simple script to work as our example, and then we will wire our script up to Composer so that the classes in our dependencies will be autoloaded. This way, our own code can be kept clean and not be cluttered by needless require or include statements.

Composer can also autoload your own classes for you. You can configure this in the composer.json file. PHP has a standard way of structuring your files and directories so that you don't need to specify them. It is part of a series of standards maintained by the PHP-FIG. The autoloading standard is named PSR-4. You can see the full documentation at https://packt.live/314fBCj. To follow this standard, you should place your classes in a directory structure that matches the namespace structure of your class. For example, if you wrote a dummy class with the namespace Acme/Helper, the path to it would be Acme/Helper/Dummy.php. Often, this path exists inside another directory inside your project root to keep your application code separate, such as an src directory.

Exercise 9.8: Using PSR-4 to Load Classes

In this exercise, we will write a basic PHP class and use a filename and directory structure that conforms to the PSR-4 convention. Then, we will use Composer to autoload that class, omitting the need to require the class file ourselves:

  1. Inside the directory that contains the composer.json file, create a new directory named src. Inside that directory, create a directory named Packt:

    mkdir src

    cd src

    mkdir Packt

  2. Inside the Packt directory, create a file named Example.php with the following contents:

    <?php

    namespace Packt;

    class Example

    {

        public function doSomething()

        {

            echo "PHP is great!" . PHP_EOL;

        }

    }

  3. Back at the root of your project, open the composer.json file and add the autoload section below the require-dev section:

    composer.json

    15 "require-dev": {

    16       "phpunit/phpunit": "^8.0"

    17 },

    18 "autoload": {

    19       "psr-4": {

    20             "Packt\\":"src/Packt/"

    21 }

    22 }

  4. Create an index.php file:

    <?php

    require 'vendor/autoload.php';

    use Packt\Example;

    $e = new Example();

    $e->doSomething();

  5. Run the index.php file. You can see the output in the following screenshot:

Figure 9.14: Output of the index

You can see that by configuring Composer and following the PSR-4 format, your class will be loaded up into memory on demand as you call it, without the need to explicitly require the file. Next, let's extend our example with a very basic Monolog implementation.

Exercise 9.9: Implementing Monolog

In this exercise, we will give an example implementation of integrating with the Monolog library we installed earlier in this chapter. This example assumes you have worked through the previous examples and are at a Command Prompt in the main project directory:

  1. From the command line, create a logs directory. This directory will be where our logs will be written:

    mkdir logs

  2. Edit the index.php file to include use statements for Monolog, set up a handler, and pass it to our Example class:

    <?php

    require 'vendor/autoload.php';

    use Monolog\Logger;

    use Monolog\Handler\StreamHandler;

    use Packt\Example;

    $logger = new Logger('application_log');

    $logger->pushHandler(new StreamHandler('./logs/app.log', Logger::INFO));

    $e = new Example($logger);

    $e->doSomething();

  3. Edit the src/Example.php file to add the use statements for Monolog, add a constructor to accept the logger, and call the logger:

    Example.php

    1  <?php

    2  namespace Packt;

    3  use Monolog\Logger;

    4  class Example

    5  {

    6      protected $logger;

    7      public function __construct(Logger $logger)

    8      {

    9          $this->logger = $logger;

    10     }

  4. Run the index.php script again:

    php index.php

  5. Now, view the app.log file in the ./logs directory:

Figure 9.15: Printing the log

You will see three lines written to it for the three log levels in the doSomething method.

Working through this example has not only shown you how to use libraries you have included in your project with Composer, but also gives you a very basic example of setting up Monolog that you can apply the same principles to in order to set up advanced logging in your application.

Before starting the next activity, there are a few concepts you should be familiar with in order to make it useful in the real world. You will modify the example application we just wrote to generate a universally unique identifier, known as a UUID for short. A UUID is a 128-bit number used to uniquely identify data in computer systems. They look like long alphanumeric strings with sections separated by dashes. They can have many use cases, but one of the most common is to generate unique IDs for data in your system that you may store in a database. It is generally considered poor practice nowadays to use ascending integers as unique identifiers for your publicly accessible objects as you may not want the user to be able to guess the next one in the sequence. The package we have selected for the activity makes this task trivial.

Activity 9.1: Implementing a Package to Generate a UUID

In this activity, you have an opportunity to apply what you have learned in this chapter. You will need to have completed the previous exercises in this chapter and use them as a starting point. There is a Composer package for generating UUIDs named ramsey/uuid:

  1. Add the UUID package to your project dependencies and ensure that it is installed in the vendor directory.
  2. Add a method to your Example.php script to call the library to generate a UUID and echo the result. There are multiple methods provided for generating one; uuid1() will be sufficient. Include a concatenated new line, PHP_EOL, at the end of your echo statement.
  3. Call the new method you created in Example.php from your index.php file after your previous output.
  4. Run the index.php script and confirm that you see the UUID generated.

The output should be similar to the following:

Figure 9.16: Expected Outcome

Note

The solution for this activity can be found via this link.

Summary

In this chapter, you were introduced to the concept of dependency management and Composer, the primary tool for bringing external dependencies into your projects in PHP. Dependency management is important to keep your own application code separate from third-party libraries that need to be kept up to date and compatible with one another.

We covered Packagist, Composer's companion site that catalogs packages available for inclusion in projects. You can identify reputable packages by noting the rating, the number of downloads, and other such criteria. The site links to the source code of each of its listings, so you can review the code yourself if you need a better understanding of its inner workings or if you want to confirm the quality of the code.

We provided an overview of setting up your project to use Composer and how to use the essential features you will need to integrate with other libraries. Libraries are required in the command line or by editing the composer.json file directly. They can have version constraints placed on them so that Composer will only install versions from a specified range. Each time a package is required, a lock file is generated to keep track of the exact versions of the current set of installed libraries. Packages can also be specified as only for development purposes, and therefore can be omitted when passing a flag to the install script to omit development dependencies.

Finally, we set up a sample implementation of Monolog to demonstrate using a package installed by Composer. We can use Composer to autoload our own code as long as we follow the PSR-4 standard and take advantage of namespaces. In the next chapter, we will look at the basics of concepts of web services and connecting your application with them using Guzzle, a popular PHP open-source library for making HTTP requests.

In the next chapter, we will present an overview of web services and take a look at some examples of interacting with them.