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!
Functional Test Symfony 4 with Kahlan 4
Yes, there is a bundle for it, but currently not fully work well with kahlan 4 yet. However, we can still use kahlan 4 for it. The simplest way is define Symfony 4 skeleton bootstrap in kahlan config, and use its property at specs, for example, we configure config at kahlan-config.php
as follows:
<?php // kahlan-config.php use App\Kernel; use Kahlan\Filter\Filters; use Symfony\Component\Debug\Debug; use Symfony\Component\HttpFoundation\Request; Filters::apply($this, 'bootstrap', function($next) { require __DIR__.'/config/bootstrap.php'; umask(0000); Debug::enable(); $root = $this->suite()->root(); $root->beforeAll(function () { $this->request = Request::createFromGlobals(); $this->kernel = new Kernel('test', false); }); return $next(); });
Above settings are minimal, if you need more setup, you can define there. If you didn’t require kahlan/kahlan:^4.0
, you can require via composer:
$ composer require --dev kahlan/kahlan:^4.0
Give a try
Let’s try testing a famous /lucky/number
from LuckyController
. We have the following controller:
<?php // src/Controller/LuckyController.php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Routing\Annotation\Route; class LuckyController extends Controller { /** * @Route("/lucky/number", name="lucky_number") */ public function number() { $number = mt_rand(0, 100); return $this->render('lucky/number.html.twig', [ 'number' => $number, ]); } }
And our twig file is:
{# templates/lucky/number.html.twig #} <h1>Your lucky number is {{ number }}</h1>
We can place test under spec
directory at root directory, for its test, we can create a spec/Controller
directory:
kahlan.config.php ├── spec │ └── Controller
Now, we can create the test as follows with make request to the ‘/lucky/number’ page and get its response. We can use toMatchEcho
matcher provided with regex to get match random number of mt_rand(0, 100)
that printed inside a response html content:
<?php // spec/Controller/LuckyControllerSpec.php namespace App\Spec\Controller; describe('LuckyController', function () { describe('/lucky/number', function () { it('shows lucky number', function () { $request = $this->request->create('/lucky/number', 'GET'); $response = $this->kernel->handle($request); expect(function () use ($response) { $response->send(); })->toMatchEcho( "#Your lucky number is ([0-9]|[1-8][0-9]|9[0-9]|100)#" ); }); }); });
Time to run it with command:
$ vendor/bin/kahlan
We will get the success output:
That’s it 😉
5 comments