9

I'm working on a Drupal 8 site, and part of the requirement is giving the client a page where they can click a button to do a particular task. I am able to do this using a Drush command from the command line, but I want to do it from a module.

I had seen code using either php_exec() or drush_invoke_process(). How can I use this function?

5
  • I had seen that but there the questioner had added a comment. " drush_invoke_process are undefined. Do i need to include any class or file in my custom drupal 8 module?" I am also getting same error..How can i define drush_invoke_process function?
    – Rifas Ali
    Sep 17, 2018 at 7:41
  • Yes, I got the same error, it is because Drush doesn't not bootstrap Sep 17, 2018 at 8:24
  • when using drush_invoke_process() it is showing me an error that function undefined. If I am using php_exec() my drush commands is not working. Eg:- exec('whoami') is working but exec("/vendor/bin/drush/drush status"); is not working.
    – Rifas Ali
    Sep 17, 2018 at 11:06
  • /vendor/bin/drush/drush seems to be a bit of an odd location for Drush. /vendor in your machine's root, really? I bet you just referenced the wrong location.
    – leymannx
    Sep 21, 2018 at 19:37
  • I think this is probably too opinionated because I wuoldn't try to run drush commands in the UI personally. Instead I would probably abstract the code and make an interface to run via batchable or non-batchable actions.
    – mradcliffe
    Sep 24, 2018 at 0:00

3 Answers 3

7

Just start it from the other side. Imagine that every Drush command executes some PHP code. Then check the code of the Drush command you want to run. And then refactor it into the submit function of your button.

Doing it like suggested in your question doesn't seem to be very sustainable, taking into account that not every host has Drush installed. So you better make that functionality work independently from its environment.


Found one possible way: How to run Drupal console command from code? using Symfony's Process and flagged question as possible duplicate. And regarding drush_invoke_process(), as how I understand it so far, it seems to be callable only from within other Drush commands.


Next thing that came to my attention: In the comments to your question you are saying that you are trying to execute /vendor/bin/drush/drush status which would mean you have the vendor folder at the root of your machine. Which very probably is wrong and you just need to fix that path.

3
  • 1
    when using drush_invoke_process() it is showing me an error that function undefined. If I am using php_exec() my drush commands is not working. Eg:- exec('whoami') is working but exec("/vendor/bin/drush/drush status"); is not working.
    – Rifas Ali
    Sep 17, 2018 at 11:06
  • 2
    @RifasAli – Well, then just don't do it that way. Which command by the way?
    – leymannx
    Sep 17, 2018 at 11:08
  • 1
    Actually I am trying to do drush commands from custom module. Actually the use case is I want to create a file upload section with a button. And while clicking this button I want the migration import command to be done. Write now client is using drush command from CLI to do mi import. We want to provide a ui for the user to achieve this , So as a first step I am trying to run any drush commands using my custom module.Am I missing any includes/ use?
    – Rifas Ali
    Sep 17, 2018 at 11:13
12

From Drush 9 and higher drush commands are symfony services, so you can load them as other services though the services container. example:

if (PHP_SAPI === 'cli') {
  $command = \Drupal::service('migrate_tools.commands');
  $command->import('my_migration', ['update' => TRUE, 'sync' => TRUE]);
}
4
  • 3
    Be careful using this method because drush is assuming the context is CLI so depending on the command it could not work as expected when is run from UI, but you could use the approach for making drush commands calling another commands or other in other CLI contexts like cron execution.
    – Akalam
    Sep 28, 2020 at 9:51
  • 1
    I edited the snippet so the code won't fail if called from UI. It will be valid only if the implementation is aim to be called from CLI (i.e custom drush commands, cron jobs, etc)
    – Akalam
    Mar 2, 2021 at 11:01
  • I would like to add a note how to get result from command execution. Assume we are running next command: $command = \Drupal::service('migrate_tools.commands'); $result = $command->status('migrate_path_alias', ['field' => 'last_imported']);, then to get some field you need iterator_to_array($result)[0]['last_imported'] Jan 28, 2022 at 18:43
  • you have to set $command->setOutput() and $command->setLogger() Mar 20 at 20:12
-1

run updb from other drush command class

    public function updateDB() {
        $updb = new \Drush\Commands\core\UpdateDBCommands();
        $updb->setProcessManager($this->processManager());
        $updb->setConfig($this->getConfig());
        $updb->setLogger($this->logger());
        $updb->setSiteAliasManager($this->siteAliasManager());
        $updb->input()->setOption('yes', true);
        $updb->setOutput($this->output());
        $updb->updatedb(['cache-clear' => true, 'entity-updates' => false, 'post-updates' => true]);

    }
2
  • This doesn't really make much sense to me, perhaps you can elaborate how the OP can apply this to their scenario?
    – Christian
    Jun 5 at 8:06
  • he can apply exaclty the same as on example above: take the class which which implements the command he desires, set the process manager, config, logger channel, i/o stream and data to avoid waiting for user input and run the command class method to do job. In example above $this is a custom drupal service. Jun 7 at 12:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.