Composer – PHP Package Manager

The PHP Composer is a Package-Management Tool similar to NPM or Yarn which you can find in the JavaScript world of NodeJS.

Why do I need Dependency-Management?

There is already so much functional code present out there for e.g. User management inkl. roles, media management, login etc.

Therefore it wouldn’t be bad if you could just “import” these modules into your project and just use them, or not?

But as always in software development there are incompatibilities with specific versions.

And thats why we have composer.

Composer nows through the composer.json and composer.lock which modules need to be installed in which version and which modules are dependent on other modules.

Installation

https://getcomposer.org/download/

With there 4 lines of PHP you will get a composer.phar in the current directory.

Therefore you can execute composer with the following command:

php composer.phar list

But usually you have composer installed “globally”. This can only be done with admin/sudo privileges:

sudo mv composer.phar /usr/local/bin/composer

Due to the fact that every Linux and MacOS has the path /usr/local/bin/ in the $PATH variable you can now execute composer via:

composer list

Usage

Here are some essential composer commands explained:

composer list

Shows all available composer commands

composer create-project <boilerplate-name>

Creates a composer project with a defined “boilerplate” and creates a composer.json in the current directory.

composer require <modulenmae>

Adds the desired module to the composer.json and executes a composer update.

composer remove <modulenmae>

Removes the desired module from the composer.json and from the file system.

composer update

Updates all currently installed modules with the newest version (dependent on the version string defined in the composer.json)
The currently active version is saved in the composer.lock.

composer install

If a composer.lock is present all the modules are installed in the defined version.
If no composer.lock is present the given modules in the composer.json are installed in the newest version (according to composer.json) and a composer.lock is created.

composer self-update

Updates the composer version

composer outdated --direct

Shows all modules, which can be updated.
The –direct changes the output so only module updates are being displayed, which are defined in the composer.json and not the dependencies behind these modules.

Structure of the composer.json

The simplest composer.json can be created via the command composer init:

{
    "name": "devguide/myapp",
    "authors": [
        {
            "name": "Kevin Pfeifer",
            "email": "info@devguide.at"
        }
    ],
    "require": {}
}

Basically only the name of the module devguide/myapp, the author and the dependencies are being displayed here.

require vs. require-dev

As usual in software development there is a separation between the production and the development environment.

To exclude modules from the production environment you have to add these modules in the require-dev area. Modules, which are always required, should be in the require area.

composer install --no-dev

With this command the require-dev modules are not being installed.

Version strings for the composer.json

NameShort versionVersion Range
Exact Version1.0.21.0.2
Version Range>=1.0 <2.0>=1.0 <2.0
>=1.0 <1.1 || >=1.2>=1.0 <1.1 || >=1.2
Hyphenated Version Range1.0 – 2.0>=1.0.0 <2.1
1.0.0 – 2.1.0>=1.0.0 <=2.1.0
Wildcard Version Range1.0.*>=1.0 <1.1
Tile Version Range~1.2>=1.2 <2.0
~1.2.3>=1.2.3 <1.3.0
Caret Version Range^1.2.3>=1.2.3 <2.0.0

Composer Patches

As always in software development the current “stable” version doesn’t always work 100% as desired.

Before the Composer Module developer publishes a new version of the module you usually have access to patches.

These patch files are normal .patch files, which can be created via GIT.

Example: https://www.drupal.org/files/issues/2019-02-07/3030251—​entity-owner-trait—​11.patch

diff --git a/consumers.install b/consumers.install
index 3ca8e25..22287bc 100644
--- a/consumers.install
+++ b/consumers.install
@@ -8,7 +8,7 @@
 use Drupal\consumers\Entity\Consumer;
 use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
-
+use Drupal\user\Entity\User;
 /**
  * Implements hook_install().
  */
@@ -161,3 +161,20 @@ function consumers_update_8105() {
     'is_default' => TRUE,
   ])->save();
 }
+
+/**
+ * 'owner_id' field should be not null.
+ */
+function consumers_update_8106() {
+  // Set owner_id to AnonymousUser id when null.
+  $anonymous_user = User::getAnonymousUser();
+
+  \Drupal::database()->update('consumer_field_data')
+    ->fields(['owner_id' => $anonymous_user->id()])
+    ->isNull('owner_id')
+    ->execute();
+
+  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
+  $field_definition = $entity_definition_update_manager->getFieldStorageDefinition('owner_id', 'consumer');
+  $entity_definition_update_manager->updateFieldStorageDefinition($field_definition);
+}

Requirements

To automatically apply composer patches you need to do have the following done:

  1. “cweagans/composer-patches” needs to be required
  2. Enable patching via an option in the “extra” area
{
  "require": {
      "cweagans/composer-patches": "^1.6.0"
  },
  "extra": {
      "enable-patching": true
  }
}

Add patch to composer.jso

"patches": {
    "drupal/<module_or_theme>": {
        "<Description>": "<URL-to-patch>"
    }
},

Therefore

"patches": {
    "drupal/recaptcha": {
        "CAPTCHA validation error: unknown CAPTCHA session ID (issues/3035883)": "https://www.drupal.org/files/issues/2019-11-15/3035883-29-workaround.patch"
    }
},

In this example the module drupal/recaptcha will be patched.

If you execute a composer install or a composer update the path should show up in the output:

Problems with patching

In this example the given patch cant be downloaded because the URL is not available. Just check if the given URL is 100% correct.

In this example you can see that the patch can’t be applied.

There are several reasons why that can happen, but most of the time this happens, because a newer version of the module has already been installed which already includes the patch.

In that case check the changelog of the module if the given patch has already been applied and a new version has been published. If so just remove the patch from the composer.json

Problems while updating

Permission problems

PHP Memory Limit problems

The problem with the Memory Limit can be solved via the php.ini. First check where your php.ini is located:

php -i | grep 'Loaded Configuration File'

On MacOS this outputs (for me):

Loaded Configuration File => /etc/php.ini

On Linux

Loaded Configuration File => /etc/php/7.3/cli/php.ini

For Drupal 8 projects you should adjust the following value to at least 3G:

memory_limit = 3G

Permission problems always need to be checked dependent on the current environment.

While the update is running the web-site is NOT accessible and/or will output errors. If possible enable a maintenance mode of your web-site or stop the web server while updating is in progress.

Installed modules don’t match up with composer.json and/or composer.lock

Sometimes it can happen, that composer doesn’t download modules correctly or misses something.

The easiest solution is to delete all generated files/folders and just tell composer to install everything again.

rm -rf vendor/*
composer install

For Drupal 8 projects

rm -rf vendor/* docroot/modules/contrib/*
composer install

Where can I find composer modules?

All available composer modules can be found here: https://packagist.org/

Share this post

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.