How do you pass an argument to a composer script from the command line?
Asked Answered
D

4

30

I'm trying to run a custom composer script via cli like so:

composer custom_script_cli --custom_argument

What happens is composer thinks i'm asking composer if i want to pass that argument to composer instead of the custom script.

Is there a way to do this without forcefully adding it to the custom script itself?

Only thing I found relevant to this topic was a git issue from 2013 which at that time says it's not possible. Not sure if this is still the case 4 years later.

Disney answered 4/7, 2017 at 16:8 Comment(1)
composer custom_script_cli -- --custom_argument perhaps? Note the double dashes (--) in their to separate arguments.Supplicatory
T
32

Any kind of arguments may be passed to custom-composer-scripts simply by appending them on the command-line as usual but after a -- (i.e. the special argument separation operator, which is not passed to the scripts itself).

However, you do not need to use the -- argument separation operator when NONE of the arguments begin with any hyphens (i.e. what are generally called command-line options, like -o or --option) else composer would treat them as an option to composer itself, and not to the script.

If the custom script definition runs multiple commands then the arguments passed will appended to every command. Also you can't use shell programming conventions like $2 to refer to individual arguments.

If the custom script is handled by a callback, it is the script's responsibility to parse options from arguments. From the callback's perspective things like -c and --option=B are arguments.

Example

Given a composer.json with the following contents:

{
    "autoload": { "psr-4": { "MyVendor\\": "./" } },
    "scripts": {
        "pass-args-to-callback": [
            "MyVendor\\MyClass::myCallback"
        ],
        "pass-args-to-commands": [
            "echo one",
            "echo two",
            "@other-command"
        ],
        "other-command": [
            "echo three"
        ]
    }
}

And given a file MyClass.php with the following contents:

<?php
namespace MyVendor;

use Composer\Script\Event;
use Composer\Installer\PackageEvent;

class MyClass {
    public static function myCallback(Event $event) {
        var_dump($event->getArguments());
    }
}

Step 0: Dump Autoloader to recognize MyClass

$ composer dump-autoload
Generating autoload files

Test 1: Show what happens without the argument separation operator

$ composer pass-args-to-callback A --option=B -C


  [Symfony\Component\Console\Exception\RuntimeException]
  The "--option" option does not exist.


pass-args-to-callback [--dev] [--no-dev] [--] [<args>]...

Test 2: Show how arguments and options appear in the callback

$ composer pass-args-to-callback -- A --option=B -C
> MyVendor\MyClass::myCallback
array(3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(10) "--option=B"
  [2]=>
  string(2) "-C"
}

Test 3: Show how arguments and options are appended to commands

$ composer pass-args-to-commands -- A --option=B -C
> echo one 'A' '--option=B' '-C'
one A --option=B -C
> echo two 'A' '--option=B' '-C'
two A --option=B -C
> echo three 'A' '--option=B' '-C'
three A --option=B -C

Reference: https://getcomposer.org/doc/articles/scripts.md

Threat answered 19/9, 2018 at 15:0 Comment(0)
L
10

You may add the double dashes -- to the end of your script entry(s).

This way you can pass additional arguments/options to the underlying script.

{
    "scripts": {
        "test": "phpunit",
        "test-single": "phpunit --"
    }
}

To run the test-single script with a custom phpunit filter:

composer test-single --filter test_function
Louralourdes answered 12/9, 2019 at 8:43 Comment(1)
This seems to not work. I got The "--filter" option does not exist. when running the above example.Essa
T
-1

I'm not sure this is exactly what you are asking for, but I had a similar problem to run PHPUnit with the --filter argument.

I solved this way:

    ...
    "scripts": {
        "test:run": [
            "@php vendor-bin/phpunit/vendor/bin/phpunit --testdox -vvv"
        ],
        "test:run:coverage": [
            "@putenv XDEBUG_MODE=coverage",
            "@test:run --coverage-html ./var/coverage/coverage-html --coverage-clover ./var/coverage/clover.xml --coverage-xml ./var/coverage/coverage-xml --log-junit ./var/coverage/junit.xml"
        ],
        "test:run:coverage:filter": [
            "@test:run:coverage --filter"
        ]
    }
    ...

To launch the coverage only for filtered files/methods:

composer test:run:coverage:filter MyTest
Twila answered 10/5, 2024 at 10:30 Comment(0)
R
-2

You may pass arguments just at the end so:

composer custom_script_cli [--dev] [--no-dev] [--] [<args>]...

Which means something like this

composer custom_script_cli argument1 argument2

And then you may get it in your script like this:

public static function commandcode(Event $event) {
   $event->getArguments(); ...
}

The thing that you refer to is called an option.

Rhondarhondda answered 16/3, 2018 at 12:21 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.