Introduction to Composer [all about repositories]

Coding (Php 7.x)

Nov 5, 2020

A repository is a package source. A list of packages. Composer examines the repositories to find the packages a project requires
 
/img/blog/introduction-to-composer-repositories-packages.jpg

Introduction

 

In the previous episodes of the series, we have discovered what Composer is and why you need to know about it.

 

It is fundamentally important whether you want to advance in your career or you just want to become a better developer.

 

Composer allows you to save plenty of time and retrieve features for your project made and tested by potentially thousands of web developers all around the world.

 

In this article, we are going to focus on the repositories.

 

Repositories in Composer are like folders but with some superpower, 

 

Repositories, in fact, have extra abilities such as remember every version of every file included into it, they also retain the metadata of the files, so they can sprinkle the information for every file when needed.

 

The simple way for you to see that you are dealing with repos is by looking for the .git folder inside the directory.

 

The job of this .git folder is to memorize the history of every change you and other collaborators make on the files

 

Below you are going to find out about the three different types of repository and how to host your own repo.

 

 

 

 

About this series

 

This article is part of the series Introduction to Composer,

 

If you haven't read the previous part already head to

  1. Installation and components
  2. Command-line interface
  3. Command-line interface part 2
  4. Destructuring composer.json
  5. Repositories

 

 

Concepts

 

Before starting learning about repositories (Repo for short) we need to do a clarification of two main concepts of Composer.

 

What are Composer packages?

 

The role of Composer is to install packages into your local project.

 

a package is a directory of files that contain some PHP code,

 

It also has a name and an identified version so web developers can recognize each package.

 

Versions are fundamentally important because Composer counts every version as a different package.

 

Another important information that packages contain is the metadata, this is a collection of information that describes the content of the package.

 

You also need to consider the two different options of package data points.

 

They can be: 

 

  • Dist which is a version of the package data, often this is a released and stable version and 
  • Source this is instead used during the development process, if you want to modify the package this is the option you would go for.

 

Packages can provide one or both of these options.

 

What are Composer repositories?

 

Repositories are package source,

 

They have the format of lists of packages/versions.

 

Composer’s job is to examine the repository and find the packages that are required by the project.

 

When you start the only repo registered in Composer is Packagist.org, 

 

If you need to add more repositories to your project you need to declare them in the composer.json file.

 

We have a complete article on how to use composer.json.

 

 

Types

 

Composer

 

The most common type of repository is the composer repository.

 

It uses a single package.json file that includes all the metadata needed.

 

Composer is the repository type used by packagist.

 

There is only one required field and it is packages

 


 

{
    {
        "repositories": [
            {
                "type": "composer",
                "url": "https://example.org"
            }
        ]
    },
    "packages": {
        "nameVendor/namePackage": {
            "dev-master": {
               "name": "smarty/smarty",
                "version": "3.1.7",
                "dist": {
                    "url": "https://www.smarty.net/files/Smarty-3.1.7.zip",
                    "type": "zip"
                }
            },
            "1.0.x-dev": {
                "name": "smarty/smarty",
                "version": "1.0",
                "dist": {
                    "url": "https://www.smarty.net/files/Smarty-1.0.zip",
                    "type": "zip"
                }
            },
            "0.0.1": {
                "name": "smarty/smarty",
                "version": "0.0.1",
                "dist": {
                    "url": "https://www.smarty.net/files/Smarty-0.0.1.zip"
                    "type": "zip"
                }
            },
            "1.0.0": {
                "name": "smarty/smarty",
                "version": "1.0.0",
                "dist": {
                    "url": "https://www.smarty.net/files/Smarty-1.0.0.zip",
                    "type": "zip"
                }
            }
        },
        {
            "notify-batch": "example.com/downloads/"
        },
        {
            "downloads": [
                {
                    "name": "monolog/monolog", "version": "1.2.1.0"
                }
            ]
        },
        {
            "provider-includes": {
                "nameProvidersOne.json": {
                    "sha256": "f5b4bc0b354108ef08614e569c1ed01a2782e67641744864a74e788982886f4c"
                },
                "nameProvidersTwo.json": {
                    "sha256": "b38372163fac0573053536f5b8ef11b86f804ea8b016d239e706191203f6efac"
                }
            },
            "providers-url": "/p/%package%$%hash%.json"
        }
    }
}

 

Inside the versions node, there will be the content of the composer.json from that package version.

 

The content on this node is mainly the name, the version and the source.

 

This part of the file can include other info that is explained in detail in the schema page of the official documentation.

 

Another common field is the notify-batch.

 

This field indicates a URL that will be called when a user installs the package.

 

The URL can be

 

  • Absolute
  • Fully qualified

 

Even though the field above is quite common this is not a required field of the file.

 

You can also list a set of files that list packages name supplied by the repository,

 

You do this by inserting the provider-includes field.

 

The hash of the items should be a sha256.

 

You need to indicate how these files are found on the server,

 

To do so you have to include the absolute path from the repository root.

 

The field must contain placeholders %package% and %hash%.

 

Those files contain packages’ names and hashes to verify the file integrity.

 

Here is a snippet:


 

{
    "providers": {
        "acme/foo": {
            "sha256": "38968de1305c2e17f4de33aea164515bc787c42c7e2d6e25948539a14268bb82"
        },
        "acme/bar": {
            "sha256": "4dd24c930bd6e1103251306d6336ac813b563a220d9ca14f4743c032fb047233"
        }
    }
}

 

This snippet states that the two providers can be found in the repository,

 

By replacing the package and the hash placeholder in the providers-url field, the indicated file will be loaded.

 

These fields are optional as well.

 

I also need to mention that the package.json file is loaded by using a PHP stream.

 

You can change the stream by modifying the options parameter.

 

PHP has several Context options and parameters you can choose from.

 

 

VCS

 

Another type of repository is VCS

 

VCS is an acronym and it stands for Version Control System,

 

Version control is a system that is responsible for managing updates to the software.

 

This software can be applications, documents, websites, etc.

 

VCS includes systems like git, fossil hg and svn. 

 

Composer has a repository type for installing packages from these systems.

 

The main reason you want to use a VCS repository is when you need to use a modified version of a specific package.

 

Let’s see an example:

 

Given you want to use a package, but you need to update it according to your needs, what you would usually do is to fork and maintain your own version of the package,

 

(If you are not sure about what I am talking about it is time to check GIT for PHP developers). 

 

The reason for this is that when you’d use the package in your code you’d want to use your forked package, the one with your patches on it.

 

In this case, you can simply update your composer, JSON by adding your fork as a repository and add the new updated version.

 

It is also common practice to prefix your custom branch with ‘dev-’, 

 

You can find more info on this on the official libraries documentation.

 

For clarification purposes let’s see this on an actual snippet of code.


 

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/anastasionico/Faker"
        }
    ],
    "require": {
        "fzaninotto/Faker": "dev-foodAddition"
    }
}



In this case,

 

During the updating of Composer, you should get your own version rather than the one from packagist.

 

Also notice that I haven’t changed the name of the package, in fact, both are called Faker,

 

This is because Composer will pick my updated package.

 

It is advisable to change the name only in case you want to move further from the original package’s code.

 

Also when you rename the package you should do it in the master branch, not in a feature one.

 

Git is not the only version control system supported by the VCS repository.

 

If you have alternative clients installed you can get packages from other systems.

 

For example:

 

  • Subversion: subversion.apache.org
  • Mercurial: mercurial-scm.org
  • Fossil: fossil-scm.org

 

The issue with this is that you may not want to install another version control system.

 

For that GitHub and BitBucket have developed APIs.

 

 

These APIs allow you to fetch the packages without having to install anything.

 

The VCS repository provides dists for them that fetch the packages as zips.

 

They can be used automatically based on the URL,

 

In case you have to specify the one you can use one among the list below.

 

  • git-bitbucket, 
  • hg-bitbucket, 
  • github, 
  • gitlab, 
  • perforce, 
  • fossil, 
  • git, 
  • svn
  • hg

 

Package

 

Lastly, the other type is the Package one.

 

This is to be used if you do not want to use any of the previous options.

 

The way it works is that you simply specify the required information that is inside the composer repository’s packages.json.

 

The fields you need to specify are name, version and one between dist and source.

 

Here is an example


 

{
    "repositories": [
        {
            "type": "package",
            "package": {
                "name": "smarty/smarty",
                "version": "3.1.7",
                "dist": {
                    "url": "https://www.smarty.net/files/Smarty-3.1.7.zip",
                    "type": "zip"
                },
                "autoload": {
                    "classmap": ["libs/"]
                }
            }
        }
    ],
    "require": {
        "smarty/smarty": "3.1.*"
    }
}



This type of repo is the less common because of the few constraints it has,

 

In fact, Composer only updates the package if the version field has changed.

 

Also, if you use master as a reference you must delete the package to force an update.

 

This means you will have an unstable lock file and you need to manage it.

 

Note that you can define different versions of a package by indicating them as arrays under the package node.


 

{
    "repositories": [
        {
            "type": "package",
            "package": [
                {
                    "name": "vendor/project",
                    "version": "1.0.0",
                    ...
                },
                {
                    "name": "vendor/project",
                    "version": "2.0.0",
                    ...
                }
            ]
        }
    ]
}



 

Your own package

 

The vast majority of the time you are going to use packagist for your packages, but there are a few times in which you do not need it or you may want to do otherwise.

 

Let’s say you work in a company that uses Composer for their internal packages, there are high chances that you need to keep these packages private.

 

Another case is when your package is very specific for a unique case if it won’t benefit the PHP community there is no need for it to be published on packagist.

 

If you want to host your own package it is advisable to use the composer type as it gives the best performance.

 

There are a few tools that allow you to host your own package.

 

The first one is the private feature of Packagist.

 

It mirrors open-source and third-party dependencies and monitors security vulnerabilities

 

Artifact

 

Another tool is Artifact,

 

As the one before even this is mainly used when you are working on private packages,

 

To use it you have to use a repository of type artifact with a folder that contains a zip or a tar archive of the private packages.

 

Each zip artifact is an archive that contains a composer.json in the root.

 

In case two archives are containing different versions they are both imported.

 

When you run composer update the version will be imported as well and Composer will update to the latest version.

 

Here is some the composer.json code


 

{
    "repositories": [
        {
            "type": "artifact",
            "url": "path/to/directory/with/zips/"
        }
    ],
    "require": {
        "private-vendor-one/core": "15.6.2",
        "private-vendor-two/connectivity": "*",
        "acme-corp/parser": "10.3.5"
    }
}

 

Path

 

We can also use the path repository if we want.

 

It permits us to depend on the local directory using both absolute or relative paths.

 

We want to opt for this type when we deal with monolithic repositories.

 

Usually, the version should be defined in the composer.json file if the version is not specified Composer supposes that it has to take dev-master.

 

In case it is not possible to get to the version we should use the branch-version item of the extra node.

 

The package will either be symlinked or copied.

 

You can also force the fallback strategy by using true or false in the symlink key.

 

Here is an example of this part of the code


 

{
    "repositories": [
        {
            "type": "path",
            "url": "../../packages/my-package",
            "options": {
                "symlink": false
            },
            "extra": {
                "branch-version": "4.2-dev"
            }
        }
    ],
    "require": {
        "my/package": "*"
    }
}

 

Satis

 

Think of Satis as a generator of repositories.

 

It is a lightweight, file-based version of Packagist.

 

The way it works is by giving a composer.json that contains the repositories (VCS and package repository), and it will fetch all the packages that are required.

 

Have a look at the Satis on GitHub.

 

 

How to disable Packagist.org

 

Using Packagist for your project is not mandatory!

 

You can disable it by simply update the composer.json in your folder.


 

{
    "repositories": [
        {
            "packagist.org": false
        }
    ]
}

 

Or you can do so globally by updating the config of Composer

 

composer config -g repo.packagist false

 

 

Become a Patron!

 

 

Conclusion

 

In this episode of the series, we have seen how there are different ways you can use packages and repositories.

 

For the vast majority of cases, you will often use packagist as the main tool but it is good to know that, depending on your needs, there are other methods available.

 

Composer will remain a PHP developer’s essential for many years to come.

 

The way it works and the help it provides to us and our application are just required in nowadays development.

 

Especially with the new version of PHP about to arrive on our machines

 

If you haven’t read about it already I have created a series that describes all the new features of PHP 8.

 

In case you are looking for something more advanced have a look at the Observer pattern instead.

 
 
If you like this content and you are hungry for some more join the Facebook's community in which we share info and news just like this one!

Other posts that might interest you

Coding (Php 7.x) Sep 19, 2020

Introduction to Composer [ the json scheme]

See details
Get my free books' review to improve your skill now!
I don't want to improve