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
Name | Short version | Version Range |
---|---|---|
Exact Version | 1.0.2 | 1.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 Range | 1.0 – 2.0 | >=1.0.0 <2.1 |
1.0.0 – 2.1.0 | >=1.0.0 <=2.1.0 | |
Wildcard Version Range | 1.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:
- “cweagans/composer-patches” needs to be required
- 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/