2
votes

Standalone command app below works fine on its own when I call: php console.php say:hello MyName

The question is at the bottom.

/var/www/html/local/test-app/composer.json

{
  "name": "my/test-package",
  "description": "......",
  "type": "library",
  "version": "1.0.0",
  "autoload": {
    "psr-0": {"": ""}
  },
  "require": {
    "symfony/console": "2.*"
  },
  "minimum-stability": "stable"
}

/var/www/html/local/test-app/Command/HelloCommand.php

<?php

namespace Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class HelloCommand extends Command
{
    protected function configure()
    {
        $this
            ->setName('say:hello')
            ->setDescription('Say hello to someone')
            ->addArgument(
                'name',
                InputArgument::OPTIONAL,
                'Who do you want to say hello?'
            );
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $name = $input->getArgument('name');
        $hello = $name ? 'Hello '.$name : 'Hello';

        $output->writeln($hello);
    }
}

/var/www/html/local/test-app/console.php

#!/usr/bin/env php
<?php

require __DIR__.'/vendor/autoload.php';

use Command\HelloCommand;
use Symfony\Component\Console\Application;

$application = new Application();
$application->add(new HelloCommand());
$application->run();

QUESTION

When I include standalone package in my main project's composer.json, composer installs everything but when I call php console.php say:hello MyName I get Could not open input file: console.php error. Obviously I have to create a symlink in bin directory like behat, phing, phpspec, doctrine etc. but how?

my main project's composer json

"require": {
    "my/test-package": "dev-master"
},

I've checked:

So on....

3
I think no magic here, you're not in correct directory, or console.php have incorrect permissions.malcolm
This is irrelevant to anything Symfony related - you get that error whenever you invoke php with a non-existant file: $ php DoesNotExist.php outputs Could not open input file: DoesNotExist.php. Otherwise, check to make sure console.php has read permissions.HPierce

3 Answers

1
votes

Composer will install the dependencies in the vendordirectory. You can use the full path to the console.php file:

php vendor/my/test-package/console.php say:hello MyName

It may look surprising to see the full path and not vendor/bin/ only but this is a valid approach, as shown by Wouter J with for PHPUnit. It has one advantage: it will call the right command and not another time (eg. another package already created the vendor/bin/console.php file).

1
votes

If you want to target a specific directory for binaries using composer use

{
    ....
    "config": {
        "bin-dir": "bin"
    },
    ....
}

That lets you have a bin directory at the root of your project for all the binaries in it (since it creates the dynamic links for you automatically).

Don't forget to add this directory (bin) to your .gitignore file.

More info: https://getcomposer.org/doc/articles/vendor-binaries.md#can-vendor-binaries-be-installed-somewhere-other-than-vendor-bin-

1
votes

Solved. I'm giving example in full so that anyone else can benefit from it.

STANDALONE SYMFONY2 CONSOLE COMMAND APP

/var/www/html/local/test-app/composer.json

After creating composer.json file below run composer install.

{
  "name": "my/test-package",
  "description": "Write something here",
  "type": "library",
  "version": "1.0.0",
  "autoload": {
    "psr-0": {
      "Command": "src/"
    }
  },
  "require": {
    "symfony/console": "2.*"
  },
  "minimum-stability": "stable",
  "bin": [
    "bin/console"
  ]
}

/var/www/html/local/test-app/bin/console

Make sure to make it executable so run: chmod +x bin/console first.

#!/usr/bin/env php
<?php

set_time_limit(0);

(@include_once __DIR__ . '/../vendor/autoload.php') || @include_once __DIR__ . '/../../../autoload.php';

use Command\HelloCommand;
use Symfony\Component\Console\Application;

$app = new Application('My CLI Application', '1.0.0');
$app->add(new HelloCommand());
$app->run();

/var/www/html/local/test-app/src/Command/HelloCommand.php

<?php

namespace Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class HelloCommand extends Command
{
    protected function configure()
    {
        $this
            ->setName('say:hello')
            ->setDescription('Say hello to someone')
            ->addArgument(
                'name',
                InputArgument::OPTIONAL,
                'Who do you want to say hello?'
            );
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $name = $input->getArgument('name');
        $hello = $name ? 'Hello '.$name : 'Hello';

        $output->writeln($hello);
    }
}

Test

test-app$ bin/console say:hello MyName
Hello MyName

Standalone console command app is ready now but you also want to use it in your main project so for that, do the following.

YOUR MAIN PROJECT

After including new package in your composer.json file, run composer update my/test-package.

/var/www/html/local/my-main-app/composer.json

{
    "name": "my/main-app",
    "type": "project",
    "description": "Main",
    "autoload": {
        "psr-0": { "": "src/" }
    },
    "repositories": [
        {
          "type": "git",
          "url": "[email protected]:my/test-package.git"
        }
    ],
    "require": {
        .......
        .......
        "my/test-package": "dev-master"
    },
    "minimum-stability": "stable"
}

If you look into your bin directory, you should see file called console so that means you can use the command in your main app.

Test

my-main-app$ bin/console say:hello MyName
Hello MyName