cakephp: Command class is missing a dispatchCommand method
This is a
-
feature-discussion (RFC)
-
CakePHP Version: 3.6
-
Platform and Target: N\A
What you did
I was able to dispatch a shell within another shell as
$this->dispatchShell('schema', 'create', 'Blog', '--plugin', 'Blog');
Since the class is deprecated I tried to achieve the same thing with console commands.
What happened
The dispatchCommand method is missing from the Command class.
What you expected to happen
I usually separate commands in granular classes and code a few commands to use them in different aspects according to arguments.
As an example;
class DeployCommand extends Command
{
public function buildOptionParser(ConsoleOptionParser $parser)
{
$parser = parent::buildOptionParser($parser);
$parser
->addOption('type', [
'help' => 'type of deployment',
'required' => true,
'choices' => [
'cms', 'app'
]
]);
return $parser;
}
public function execute(Arguments $args, ConsoleIo $io)
{
if($args->getOption('type') === 'cms') {
// call deploy cms command here
} else {
// call deploy cms here
// call deploy app also here
}
}
}
So it would be useful to have a dispatchCommand method just like dispatchShell method.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 17 (13 by maintainers)
I was thinking a bit more about this, and while sub-processes would cover a few of the scenarios described here, it would not make accepting interactive input easy to work with. The generated sub-processes could attach to the current process’ stdin/stdout easily enough, but testing becomes challenging, as the sub-process would not be controlled by the test suite directly.
Running ‘sub-shells’ in the same PHP process presents some problems around isolation and error handling, but makes testing much simpler. I’ve been working on converting bake commands recently and have made good use of a pattern that looks like:
This pattern allows the calling command to pass in its
ConsoleIoinstance making tests easy, and enables commands to be constructed as needed (either from a DI container, or directly). This pattern could be wrapped into an abstraction that looks like:The
executeCommandmethod would allow other commands, (but not shells) to be called. TheexecuteCommandmethod would:executemethod on the command and return the command’s return code.What do folks think of that API?
I’m sure we could create a way. But why simulate subprocesses if we can use actual sub-processes. Instead of having folks use symfony/process we could provide a method on
Commandthat opens a subprocess with the current process’s ENV data.Would providing wrappers around running other shells/commands as subprocesses work? It would cover the application cron daemon scenario well.
One challenge I have had with invoking other shells is that they run in the same process space and their failure/global state mutation will effect the calling shell.
Instead of dispatching commands from within commands I’d suggest refactoring your code so the reusable logic is not tied to the console anymore.
Dispatching commands from another command doesn’t sound like a good idea and we should avoid that.