BentCoder
BentCoder

Reputation: 12740

Including Symfony2 standalone console components packages in main app to access commands

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....

Upvotes: 2

Views: 848

Answers (3)

BentCoder
BentCoder

Reputation: 12740

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

Upvotes: 1

vpassapera
vpassapera

Reputation: 362

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-

Upvotes: 1

A.L
A.L

Reputation: 10503

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).

Upvotes: 1

Related Questions