Using laminas-cli to Consume Symfony Console Command in Mezzio Application
So, you want to use Symfony Console Command in Mezzio Application? You can! There is laminas-cli
for that. While it still in development, you already can give it a try. First, I assume that you already installed the mezzio application. Next, you can set minimum-stability and prefer-stable config in your composer.json:
➜ composer config minimum-stability dev ➜ composer config prefer-stable true
By above command, you can ensure that you can install the non-stable dependency, while prefer stable version if found. Next, you can require the laminas-cli via command:
➜ composer require laminas/laminas-cli
After installed, let’s create our first command: “HelloWorld command”, like the following:
namespace App\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; use function sprintf; final class HelloWorld extends Command { protected function configure() { $this ->addArgument('message', InputArgument::REQUIRED, 'Greeting Message'); } protected function execute(InputInterface $input, OutputInterface $output) { $message = $input->getArgument('message'); $output->writeln(sprintf('<info>Hello to world: %s<info>! ', $message)); return 0; } }
Greet! Now, time to register it to our App\ConfigProvider
class:
<?php declare(strict_types=1); namespace App; class ConfigProvider { public function __invoke(): array { return [ // ... 'laminas-cli' => $this->getCliConfig(), // ... ]; } public function getCliConfig(): array { return [ 'commands' => [ // ... 'app:hello-world' => Command\HelloWorld::class, // ... ], ]; } public function getDependencies(): array { return [ 'invokables' => [ // ... Command\HelloWorld::class => Command\HelloWorld::class, // ... ], ]; } // ... }
First, in getDependencies()
, we register the command, if the command has dependency, you need to provide factory for it. And then, in __invoke()
method, we register the commands, which you can move the commands definition in separate method. That’s it! Now, you can run the command:
➜ vendor/bin/laminas app:hello-world "Good Morning" Hello to world: Good Morning!
Trying a variation of the above from this reference; https://github.com/laminas/laminas-cli/blob/0.2.x/docs/book/intro.md
The configuration never seems to invoke the CommandFactory despite it being known to the container. This is not using Mezzio but with laminas-mvc only. Have you been able to configure a command factory instead of just an invokable?
Great tutorial. I was able to get it work and in working further with this example, I expanded the execute() function to generate HTML pages that needs to be saved in a file or send out as an email. I’m struggling to get the Url view helper to return the appropriate route links in the view even though I have passed the router stack into the Url view helper. Do you have any tutorials/guide on how to ensure that the Url view helper is generating the appropriate route links in View Models that are instantiated in the CLI mode?
you may need to pull from `ViewHelperManager` service
I’m not sure if i’m doing this right but still having trouble here.
in the HelloWorld factory, i have this:
class HelloWorldFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$entityManager = $container->get(‘doctrine.entitymanager.orm_default’);
$config = $container->get(‘Config’);
$viewRenderer = $container->get(‘ViewRenderer’);
$viewHelperMgr = $container->get(‘ViewHelperManager’);
$router = $container->get(‘router’);
// Instantiate the command and inject dependencies
return new HelloWorld ($viewRenderer, $entityManager, $config, $router, $viewHelperMgr);
}
}
In the HelloWorld Command class constructor:
public function __construct(PhpRenderer $renderer, $entityManager, $config, SimpleRouteStack $router, $viewHelperMgr, string $name = null)
{
$this->renderer = $renderer;
$this->entityManager = $entityManager;
$this->config = $config;
$this->router = $router;
$this->viewHelperManager = $viewHelperMgr;
// Setup plugin Manager
$pluginManager = $this->renderer->getHelperPluginManager();
$pluginManager->setAlias(‘url’,Url::class);
$pluginManager->setService(Url::class, $this->viewHelperManager->get(‘url’));
/** This has been commented out as this was my previous attempt but the url helper is returning blank.
$pluginManager->setService(Url::class, function($name = null, $params = [], $options = [], $reuseMatchedParams = false) {
$url = new Url($name, $params, $options, $reuseMatchedParams);
$url->setRouter($this->router);
});
*/
$pluginManager->setAlias(‘serverUrl’,ServerUrl::class);
$pluginManager->setService(ServerUrl::class, function() {
$urlHelper = new ServerUrl();
$urlHelper->setHost($this->config[‘hostname’]);
return $urlHelper->getHost();
});
$this->renderer->setHelperPluginManager($pluginManager);
parent::__construct($name);
}
I commented out the few lines below the $pluginManager->setService() method as the url helper was printing out blank url in a ViewModel even though I manually injected the SimpleRouteStack in the URL helper.
I tried your suggestion of getting the URL helper from the ViewHelperManager but I’m getting the error message:
PHP Fatal error: Uncaught Error: Call to a member function getRouteMatch() on null in C:\xampp\htdocs\helloworld\vendor\laminas\laminas-mvc-console\src\Service\ConsoleViewHelperManagerDelegatorFactory.php:97
Stack trace:
#0 C:\xampp\htdocs\helloworld\vendor\laminas\laminas-servicemanager\src\ServiceManager.php(765): Laminas\Mvc\Console\Service\ConsoleViewHelperManagerDelegatorFactory->Laminas\Mvc\Console\Service\{closure}(Object(Laminas\ServiceManager\ServiceManager
), ‘Laminas\\View\\He…’, NULL)
#1 C:\xampp\htdocs\helloworld\vendor\laminas\laminas-servicemanager\src\ServiceManager.php(201): Laminas\ServiceManager\ServiceManager->doCreate(‘Laminas\\View\\He…’)
#2 C:\xampp\htdocs\helloworld\vendor\laminas\laminas-servicemanager\src\AbstractPluginManager.php(153): Laminas\ServiceManager\ServiceManager->get(‘Laminas\\View\\He…’)
#3 C:\xampp\htdocs\helloworld\module\Application\src\Command\HelloWorld.php(70): Laminas\ServiceManager\AbstractPluginManager->get(‘Laminas\\View\\He…’)
#4 C:\xampp\htdocs\helloworld\module\Applic in C:\xampp\htdocs\helloworld\vendor\laminas\laminas-mvc-console\src\Service\ConsoleViewHelperManagerDelegatorFactory.php on line 97
Thank you for verify, I will try to take a look when I have a chance. Meanwhile, you may can post a question in forum https://discourse.laminas.dev/ if somebody have a chance to take a look/help 😉