This is my composer.json file:
"require": {
"php": ">=5.4",
"zendframework/zendframework": "2.*",
"doctrine/doctrine-module": "dev-master",
"doctrine/doctrine-orm-module": "0.*",
"gedmo/doctrine-extensions": "dev-master"
},
"require-dev": {
"phpunit/phpunit": "3.7.*"
},
"scripts": {
"post-update-cmd": [
"rm -rf vendor/Behat",
"git clone git://github.com/Behat/Behat.git",
"cp composer.phar Behat/composer.phar",
"cd Behat && git submodule update --init",
"cd Behat && php composer.phar install",
"cd Behat && php composer.phar require guzzle/guzzle:3.0.*",
"mv Behat vendor/Behat",
"ln -sf ../Behat/bin/behat vendor/bin/"
]
}
How can I make it so the scripts are only run in the dev environment?
Basically I want the scripts to run only when I call:
php composer.phar update --dev
To do the non-development environment update without triggering any scripts, use the --no-scripts command line switch for the update command:
php composer.phar update --no-scripts
^^^^^^^^^^^^
By default, Composer scripts are only executed1 in the base package2. So you could have one package for development and in the live environment make it a dependency of the live system.
Apart from that, I do not see any way to differentiate scripts automatically.
This answer is back from 2012, the additional options in order of appearance can now safely be listed. As the list is composer-only and the original question smells to fall for x/y, the general answer is to use a build manager.
But turns out this could be done already at the day of asking, as in this composer-json example:
{
"scripts": {
"post-update-cmd": "composer::dev-post-update-cmd",
"dev-post-update-cmd": [
"rm -rf vendor/Behat",
": ... ",
"ln -sf ../Behat/bin/behat vendor/bin/"
]
}
}
1.0.0-alpha6 (2012-10-23): dispatch dev-only scripts with PHP script class and __callStatic, e.g. composer::dev-post-update-cmd. if in_array('--dev', $_SERVER['argv']) then $eventDispatcher->dispatchCommandEvent($name).
1.0.0-alpha7 (2013-05-04): --dev is now default and henceforth optional, --no-dev required for not --dev script dispatching. this effectively changes the command-line in question from: composer update --dev running only to: not running on composer update --no-dev. $event->isDevMode() now available, also required for new second parameter on dispatching the script on the event dispatcher. Compare with answer by Christian Koch.
1.0.0-alpha9 (2014-12-07): autoload-dev now allows to not have the script class in --no-dev automatically by removing it from autoload. this works b/c non-existing classes fall-through w/o error.
1.3.0-RC (2016-12-11): --dev is deprecated. COMPOSER_DEV_MODE environment parameter now available in update/install/dumpautoload scripts. no inherit need any longer for the PHP script class, unless enviroment parameters do not work in your setup, then use a PHP class script for a workaround. Compare with answer by Veda.
3 (future): --dev will needlessly make composer fatal, at least this is announced. this closes the circle to pre-1.0.0-alpha7 which also failed on the opposite, --no-dev. the command-line library in use then and yet in the future is not able to cope with -[-not]-args symmetrically, and if the pair is divided and one must go, then it can only throw.
References
See "Note:" in What is a script? - Scripts - Composer Docs
Base package is commonly referred to as root package in the Composer documentation.
Introduction
Some of the answers are a bit brief and don't go into detail about the context in which this is done. I'd like to share some knowledge with whoever is still puzzled after reading the previous answers.
Determine the right option for you
First, take a moment to realise that you're effectively creating a different flow, specific for a certain environment (i.e. your development server/container). This is against any best practices, as it is generally prone to errors. Having said that, you can achieve what you want in several ways;
Not triggering any scripts (docs)
If on some environment you do not want to trigger any scripts, you can prevent this using the --no-scripts flag.
Documentation reads: --no-scripts: Skips execution of scripts defined in composer.json.
composer upgrade --no-scripts
This is especially useful when upgrading packages while your code is currently not working. It would also work if your only scripts are development and test-related.
Running one script separately (docs)
Simply run the specific command as needed:
composer run-script [--dev] [--no-dev] script
This is useful when you want to run a script only on specific occasions.
For example, on build systems that have to perform a certain script before running any tests; build systems offer configuration options to call custom scripts like the above.
Defining a condition in the command (docs)
Documentation reads: During a composer install or update process, a variable named COMPOSER_DEV_MODE will be added to the environment. If the command was run with the --no-dev flag, this variable will be set to 0, otherwise it will be set to 1.
An example could look like
"scripts": {
"post-install-cmd": [
"[ $COMPOSER_DEV_MODE -eq 0 ] || <your command>"
]
}
Personally i would say this is the recommended way if you are using containers.
Note: this does not work on windows, since it would need %COMPOSER_DEV_MODE%.
There are also packages (like scriptsdev by neronmoon) that help you achieve the same goal without having to type the above in all commands, using a dev-scripts section in the extra section in composer.json
Defining a condition in your PHP script (docs)
Call a PHP method, that checks your environment based on how your application already does this. You can even reuse this condition by combining it with the method above; "Defining a condition in the command".
"scripts": {
"post-update-cmd": [
"AppNameSpaceName\\YourClassName::methodName"
]
}
You can then go ahead and create the class, like so:
<?php
namespace AppNameSpaceName;
class YourClassName
{
methodName() {
// do stuff
}
}
In many modern frameworks there is already a mechanism present to determine the runtime environment of the application (Symfony way, Laravel way).
Yarn run (docs)
Since most PHP applications nowadays also transpile their javascript files, either NPM or Yarn would be installed. You can use the scripts section to run this part only on development machines/containers. For example:
yarn run dev-only-script
having a section in package.json
"scripts": {
"dev-only-script": "rm some/folder && ln -s path/to/your/folder some/"
}
The point of this is would be to your composer.json clean. In yarn you could have scripts for dev-server, test and build.
It's not possible to choose different script for default install and the --dev option but you can use the method isDevMode() in Composer\Script\Event to run command only in a development enviroment. http://getcomposer.org/apidoc/master/Composer/Script/Event.html
You can use the COMPOSER_DEV_MODE environment variable (new in version 1.3.0-RC - 2016-12-11):
"scripts": {
"post-install-cmd": [
"[ $COMPOSER_DEV_MODE -eq 0 ] || echo devmode only"
]
},
You can achieve the same effect by setting up a custom script for the dev pathway, instead of using the post-update-cmd hook.
"scripts": {
"update-behat": [
"rm -rf vendor/Behat",
"git clone git://github.com/Behat/Behat.git",
"cp composer.phar Behat/composer.phar",
"cd Behat && git submodule update --init",
"cd Behat && php composer.phar install",
"cd Behat && php composer.phar require guzzle/guzzle:3.0.*",
"mv Behat vendor/Behat",
"ln -sf ../Behat/bin/behat vendor/bin/"
],
"dev-update": [
"#composer update --dev",
"#update-behat"
]
}
Then simply run php composer.phar dev-update
Run the following command.
composer update --no-scripts
Here is the small package, that you may use to do that
https://github.com/neronmoon/scriptsdev
It adds ability to define only-dev scripts.
usage
...
"extra": {
"scripts-dev": {
"post-install-cmd": [
"npm install --dev"
],
"post-update-cmd": "php ./someCoolCommand.php"
},
}
...
You can run either one and check,
composer update --no-scripts
or
composer dump-autoload
Related
From the documentation if I want to run a Composer script manually I need to type
composer run-script [--dev] [--no-dev] script-name
But if I write
composer script-name
The script will be executed just the same.
I was setting up scripts to run unit and integration tests, and I really see no difference between these two approaches (with or without run-script part).
Is there any, and what is it? Or is it just something that was needed in the earlier versions of the Composer? The documentation isn't giving much details on this.
You need to use run-script for running standard scripts for events, for example you need it to run post-update-cmd script manually:
"scripts": {
"post-update-cmd": "echo My script"
},
Not working:
$ composer post-update-cmd
[Symfony\Component\Console\Exception\CommandNotFoundException]
Command "post-update-cmd" is not defined.
Working:
$ composer run-script post-update-cmd
> echo My script
My script
AFAIK there is no difference between between these to approach when you want to run custom command.
However with run-script you're able to run script with the same name as composer built-in command:
"scripts": {
"install": "echo My script"
},
Run composer install command:
$ composer install
A script named install would override a Composer command and has been skipped
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files
Run install script:
$ composer run-script install
A script named install would override a Composer command and has been skipped
> echo My script
My script
However in such case you will get warning about conflicting script name and I would not rely on it. It does not make much sense anyway.
I have a customized symfony-project and a custom vendor. In the composer.json of the project the type is set to "project". To update my vendor I use composer update. So far, so good.
But how do I update my project itself? It's installed by composer's create-project, but I know that such as update-project does not exist for composer. What is the best strategy to keep my "skeleton" up-to-date? Using git would require to init git repository and checkout the right branch/tag. So that's not my favourite solution for end-users and release-management. What other methodologies can be used to tackle this scenario?
There is no better alternative, as the skeleton is completely free. You can use Symfony by just adding a symfony/symfony dependency and creating your own directory structure.
This means that while most projects start with the skeleton, projects can tweak it to fit their needs. Also, some bundles included by the skeleton may be removed from the project or a project uses different settings than the skeleton.
Each time a new skeleton version is released, you can check the diff (e.g. https://github.com/symfony/symfony-standard/compare/v2.7.2...v2.7.3 ) and check the changes and apply the changes to your project whenever they're needed in your project.
I'm testing another approach at the moment. I've created a bash-script which is included in the composer.json at the post-install- and post-update-part. I know that has to be exists, but with this, the enduser only have to do a composer update
composer.json
[...]
"scripts": {
"post-install-cmd": [
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::removeSymfonyStandardFiles",
"chmod +x init_update_app && ./init_update_app"
],
"post-update-cmd": [
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::removeSymfonyStandardFiles",
"chmod +x update_app && ./update_app"
]
},
[...]
Post-Install:
#!/bin/bash
if ! git ls-remote origin > /dev/null; then
git init
git remote add origin https://github.com/xxx/xxx.git
fi
git fetch --tags
latestTag=$(git describe --tags `git rev-list --tags --max-count=1`)
git checkout $latestTag
Post-Update:
#!/bin/bash
git fetch --tags
latestTag=$(git describe --tags `git rev-list --tags --max-count=1`)
git checkout $latestTag
Any disadvantages with this approach? I know that git have to be installed but that is not the problem. The scripts could be improved by checking the existing tag to prevent checking out the same tag again or to check if git is installed...
I'm deploying a PHP app to Heroku using Composer. Currently I'm using Gulp to compress CSS/JS and commit it to the Git repository. I was wondering if it makes more sense to run the Gulp tasks using Composer's post-install-cmd. What is the best practice for that?
You use the so-called "multi-buildpack" to perform both a Node.js (to install Gulp) and PHP build upon deploy.
Here's an example I built a while ago that uses Bower to install Bootstrap in a Composer post-install-cmd, but the principle is going to be the same:
http://heroku-multipack-nodejs-php-ex.herokuapp.com
Sources with README that explains the process: https://github.com/dzuelke/heroku-multipack-nodejs-php-example
You can also use the composer compile step if you prefer the Gulp install not to run on each composer install: https://devcenter.heroku.com/articles/php-support#custom-compile-step
Think of Gulp as an all-purpose task-runner, rather than using Composer's post-install-cmd (or similar) to bolt on additional tasks. A PHP package manager shouldn't be responsible for fetching or compressing front-end assets, that's not its job. Gulp isn't just for front-end-related tasks.
To me, using gulp-composer makes the most sense.
gulp provides flexible tools for command tasks, so perhaps, the best practice is to use gulp for update or install composer dependencies?
Take a look at this gulp-composer package
Example:
composer = require('gulp-composer');
gulp.task('composer', function () {
composer({ cwd: './php-stuff', bin: 'composer' });
});
I'd recommend using Symfony's Process Component for that inside some script handler and then run that as post-install-cmd as you said.
scripts/composer/ScriptHandler.php
use Composer\Script\Event;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
class ScriptHandler {
public static function gulpBuild(Event $event) {
$process = new Process('cd /path/to/my/theme && gulp build');
$process->run();
// executes after the command finishes
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
$event->getIO()->write($process->getOutput());
}
else {
$event->getIO()->write("Recompiled and compressed CSS/JS");
}
}
}
composer.json
"autoload": {
"classmap": [
"scripts/composer/ScriptHandler.php"
]
},
"scripts": {
"post-update-cmd": [
"DrupalProject\\composer\\ScriptHandler::gulpBuild"
]
},
Check Composer template for Drupal projects for some more inspiration. (For example getting the path to your theme dynamically to have that command run successfully in every environment.)
In my symfony project i would like to trigger the
php app/console doctrine:migration:migrate
on every
composer install --no-dev
I have read that it should be possible to place such a command in the post-install-cmd Section of my composer file but can not figure out how to use it properly.
You have to create a Composer Script:
A script, in Composer's terms, can either be a PHP callback (defined as a static method) or any command-line executable command.
Just like they do in the example:
{
"scripts": {
"post-install-cmd": ["phpunit -c app/"],
}
}
I have project on Symfony 2 and i would like use PHPUNIT on Windows 7.
On githut phpunit is:
Composer
Simply add a dependency on phpunit/phpunit to your project's composer.json file if you use Composer to manage the dependencies of your project. Here is a minimal example of a composer.json file that just defines a development-time dependency on PHPUnit 3.7:
{
"require-dev": {
"phpunit/phpunit": "3.7.*"
}
}
For a system-wide installation via Composer, you can run:
composer global require 'phpunit/phpunit=3.7.*'
Make sure you have ~/.composer/vendor/bin/ in your path.
First i use system-wide installation but i dont know when this installed.
Next i add to my composer.json require-dev.
This installed phpunit in C:/wamp/www/myproject/vendor/symfony. Next i try commands:
composer install --dev
And i can't use phpunit. In cmd.exe i enter "phpunit" and i have error:
'phpunit' is not recognized as an internal or external command operable program or batch file
How can i use phpunit? I have Windows 7, Wamp server and php 5.4.12.
When you install PHP-Unit in windows via composer, the global installation will create files in
C:\Users\YOUR_USERNAME\AppData\Roaming\Composer
To execute phpunit easily via command line you need to add path of phpunit.bat file in windows Environment Variables. For this:
Right click My Computer
Go to Properties -> Advance system settings and
Click Environment variables from the Advance tab.
Now add C:\Users\YOUR_USERNAME\AppData\Roaming\Composer\vendor\bin to the windows PATH.
You can now run the phpunit from command. Note that you may need to restart your command prompt for the changes to take effect.
The bin file of packages are put in the configured bin directory. By default, this is vendor/bin and when you use the symfony standard edition, this is the bin folder.
To execute this bin file, run ./bin/phpunit (or ./vendor/bin/phpunit when not using the Symfony Standard Edition)
Windows users have to put this in double quotes: "bin/phpunit" (or "vendor/bin/phpunit")
composer require --dev phpunit/phpunit ^7
The above example assumes, composer is already on your $PATH variable.
You composer.json should look similar to;
{
"name": "vendor_name/package_name",
"description": "This project is for practicing writing php unit tests",
"minimum-stability": "stable",
"license": "proprietary",
"authors": [
{
"name": "Umair Anwar",
"email": "umair.anwar#gmail.com"
}
],
"autoload": {
"classmap": [
"src/"
]
},
"require-dev": {
"phpunit/phpunit": "^7",
"phpunit/dbunit": "^4.0"
}
}
Easiest way to install phpunit via composer is to run from project root.
$ composer require phpunit/phpunit
What this would do is, it will create a phpunit folder inside vendor/bin
and you can run unit tests like this..
$ ./vendor/bin/phpunit
Too simple operation on Windows with composer and works for me following way:
Install composer
https://getcomposer.org/doc/00-intro.md#installation-windows Go to
your symphony folder e.g C:\wamp64\www\symfony\UserManagement where is
composer.json and run this command.
Should be register with global to not have issue $phpunit bash: phpunit: command not found
//old version is 5.7 new 6.4 or put newest version.
composer global require --dev phpunit/phpunit ^5.7
I remember futzing around with the composer dependency stuff for phpunit and never could get it to work.
Instead, from your git bash shell:
mkdir ~/bin
cd ~/bin
curl https://phar.phpunit.de/phpunit.phar > phpunit
chmod +x phpunit
exit out of bash and then start a new bash session.
And you should be good to go. You can echo $PATH to verify you have a path to ~/bin but one seems to added by default.
https://phar.phpunit.de/phpunit.phar
I also came across the same issue and find out the solution by following steps
To run PHPUnit in Windows 7 under WAMP installation
Composer Install
{
"require-dev": {
"phpunit/phpunit": "3.7.*"
}
}
Simply Set Environment Variable
The php unit will be install in a vendor dir in vendor/bin
Path : C:\wamp\www\myproject\vendor\bin;
Open a new Command Prompt
C:\Users\guny >phpunit --version
PHPUnit 3.7.30 by Sebastain Bergmann