The package manager for PHP
Manages dependencies of your project
Generates optimized autoloaders
Can fetch packages from diverse, de-centralized sources
Together with PHP-FIG initiative, has changed the PHP landscape
Centralized control over project lifecycle
Provides separate production and development paths
Makes projects self-contained
$ git clone mycompany/project
$ cd project
$ composer install
Two mechanisms for enhancing default Composer functionality
Use same hooks
( i.e. "post-install-cmd"
<=> ScriptEvents::POST_INSTALL_CMD
)
Overlap in multiple areas
Stored in project's composer.json
file
Run on root package only
Intended for project automation
Stored in external package of type composer-plugin
Run on all included packages
Intended for Composer extension
{
"name": "mycompany/package",
"require-dev": {
"phpunit/phpunit": "~6"
},
"scripts": {
"post-update-cmd": "@clearCache",
"test": [
"@clearCache",
"phpunit"
],
"clearCache": "rm -rf cache/*"
}
}
{
"name": "mycompany/composer-plugin",
"type": "composer-plugin"
"require": {
"composer-plugin-api": "~1"
},
"autoload": {
"psr-4": {
"MyCompany\\ComposerPlugin\\": "src/"
}
},
"extra": {
"class": "MyCompany\\ComposerPlugin\\Plugin"
}
}
<?php namespace MyCompany\ComposerPlugin;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Plugin\PluginInterface;
use Composer\Script\Event;
class Plugin implements PluginInterface,
EventSubscriberInterface
{
// Hook your code up to Composer events.
public static function getSubscribedEvents()
{
return array(
ScriptEvents::POST_INSTALL_CMD => 'doSomething',
ScriptEvents::POST_UPDATE_CMD => 'doSomething',
);
}
// Actually do something when triggered.
public static function doSomething(Event $event) {}
}
Needs upstream sync after every commit
Branch alias needed, but causes issues
Automatic upstream updates
Errors when it needs attention
Provides means for documentation
https://github.com/cweagans/composer-patches
Tip: Get patches from GitHub by appending .diff
to any commit URL
Composer can only handle conflicts if it controls the entire project, starting from the root
In legacy systems like WordPress, individual plugins might want to use Composer, even though the Core does not use it
Prefixing allows multiple, potentially conflicting versions of a same library to co-exist in a project
Treat external data as a managed dependency
Changes can be (version-)controlled
Makes data part of project's deployment flow
No need to remember manual updates
Example project: https://github.com/brightnucleus/geolite2-country
Treated as a development dependency
Immediately active after a composer install
Logic can be coded in PHP
Multiple, prioritisable scripts on same hook
{
"name": "mycompany/custom-hook",
"type": "php-composter-action"
"require": {
"php-composter/php-composter": "*"
},
"autoload": {
"psr-4": {
"MyCompany\\CustomHook\\": "src/"
}
},
"extra": {
"php-composter-hooks": {
"20.pre-commit":
"MyCompany\\CustomHook\\MyAction::preCommit"
}
}
}
<?php namespace MyCompany\CustomHook;
use PHPComposter\PHPComposter\BaseAction;
class MyAction implements BaseAction
{
/**
* Example pre-commit action method.
*/
public function preCommit()
{
echo sprintf(
'Example Pre-Commit Hook %s @ %s' . PHP_EOL,
$this->hook,
$this->root,
);
}
}
Use create-project
for scaffolding:
composer create-project <package> <dir>
Provide logic in PHP, hooked into Autoloader
Provide configuration in "extra"
keys
Hook into post-create-project-cmd
hook to trigger logic and to clean up
after generation
{
"name": "mycompany/boilerplate",
"autoload": {
"psr-4": {
"Awesome\\Boilerplate\\Scripts\\": "_scripts/"
}
},
"extra": {
"mycompany-boilerplate": {
"config-file": "_config/defaults.php",
}
},
"scripts": {
"post-create-project-cmd": [
"MyCompany\\Boilerplate\\Scripts\\Setup::run",
"rm -rf _scripts",
"composer update --ansi",
"phpunit --color=always"
]
}
}
Example project: https://github.com/brightnucleus/boilerplate
Provides access to all supported sources
Built-in event dispatching
Flexible scripting/plugin system still usable
I'm Alain Schlesser.
Follow me on Twitter:
@schlesseraOr visit my Personal Blog:
www.alainschlesser.com