欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

Drupal:如何创建自己的Drush命令 自定义drush命令 custom drupal command ( commands ) 有大用 有大大用 有大大大用

例子在   附件  里面 

Drush是一个命令行工具,用于帮助您从终端使用Drupal。它默认带有一堆有用的命令,例如下载,启用甚至更新模块。但模块可以定义自己的命令,让Drush使用其代码执行操作。

在本文中,我们将讨论为虚构模块创建一个Drush命令,该模块实际上没有做任何事情。目的是说明您需要在Drush方面做什么,而不必担心定义命令的模块的实际功能。如果你想跟随,我假设你已经设置了自己的自定义模块。它无关紧要。

我们编写的所有代码都可以在此存储库中找到,因此如果您想要跟进或甚至跳过,您可以查看它。每个提交代表我们在教程中采取的不同步骤。

我们的模块

demo_drush我们想要向Drush公开模块功能将非常简单。这是一个设置Hello world!消息的函数

function demo_drush_print_statement() {
  drupal_set_message(t('Hello world!'));
}

它并不多,但它将帮助我们了解如何使用Drush将此语句打印到终端屏幕,并在此过程中,如何配置命令以执行各种强大的操作。我们将在本教程中调整它以演示各种可能性。

Drush命令文件

我们需要做的第一件事是将新文件添加到我们模块的文件夹中,其名称以.drush.inc结尾Drush将扫描代码库并根据此名称选择它以加载我们在其中声明的函数。

最佳做法是在放置模块后命名此文件。对于我们的情况,这将是demo_drush.drush.inc(我的模块的名称是demo_drush)。而就目前而言,只需<?php在顶部打开php标签()并保存文件即可。

命令钩子和回调

Drush命令体系结构中有两个主要组件:我们定义命令及其配置的钩子实现,以及由命令触发的回调函数。当然还有其他函数在进程中被调用(例如验证或前/后回调),但我们不会在本教程中介绍它们。

首先,让我们实现hook_drush_command()并定义一个drush-demo-command使用别名调用的简单命令ddc

/**
 * Implements hook_drush_command().
 */
function drush_demo_drush_command() {

  $items['drush-demo-command'] = array(
    'description' => 'Demonstrate how Drush commands work.',
    'aliases' => array('ddc'),
  );

  return $items;
}

使用这个钩子实现(以下称为the hook),我们在数组中返回一个新的键,它将是完整的命令名。在这个数组中,我们配置它。目前,我们为命令指定了一个简单的描述和别名。因此,如果我们运行drush help ddc,我们会在终端上打印描述和命令的别名。

Drush命令架构的第二部分是回调函数。就像现在一样,Drush期望声明一个函数被调用drush_drush_demo_command()此默认命名结构以后drush跟所有与下划线连接的命令的名称开头。所以让我们快速声明并使用它来调用demo_drush_print_statement()我们之前写函数:

/**
 * Callback for the drush-demo-command command
 */
function drush_drush_demo_command() {
  demo_drush_print_statement();
}

现在,如果你清除drush cache(drush cc drush),你可以运行drush ddc命令,你应该看到Hello world!打印到屏幕上。恭喜,您最基本的Drush命令有效。

虽然对于本教程的其余部分,我们将继续使用此默认命名约定,但您不一定限于此。如果要为回调函数指定其他名称,可以在hook指定名称时添加新密钥

...

'callback' => 'drush_demo_test'

...

现在您可以声明一个被调用的函数drush_demo_test(),这是该命令自动调用的函数但就目前而言,我们将坚持使用我们的drush_drush_demo_command()名字。


论点和选项

使用Drush命令可以执行的基本操作之一是传递参数和选项。两者之间的关键区别在于前者是强制性的,而后者则不是。另一个区别在于值传递给回调函数的方式。参数作为函数参数(按顺序)传递,而使用特殊辅助函数(drush_get_option在回调中检索选项

所以在我们命令的钩子里面,让我们添加参数和选项信息:

...

'arguments' => array(
  'type' => 'The type of statement (error or success).',
),
'options' => array(
  'repeat' => 'The number of statement repeats.',
),

...

我们声明了1个参数(称为type)和一个名为的选项repeat这些值应该解释它们的用途,但它们的使用方式可能不那么明显。该参数type将是在终端(drush drush-demo-commanddrush ddc)中的命令名之后写入的第一个字符串该选项将是一个整数值,该值将分配给--repeat命令中标志。

例:

drush ddc error --repeat=10

此命令应使打印的语句出错,并将其打印10次到终端屏幕。现在让我们调整我们的代码来实现这一目标。

首先,让我们修改一下这个demo_drush_print_statement()函数:

function demo_drush_print_statement($type = NULL) {
  drupal_set_message(t('Hello world!'), $type);
}   

现在打印的语句类型是动态的。其次,让我们修改命令回调函数并将其更改为:

function drush_drush_demo_command($type = FALSE) {

  // Check for correct argument
  $correct_args = array('error', 'success');
  if (!in_array($type, $correct_args)) {
    return drush_set_error(dt('"@type" is not a valid statement type. Please choose between "success" and "error".', array('@type' => $type)));
  }

  // Option
  $repeat = drush_get_option('repeat', 1);
  if ($repeat > 1 && is_numeric($repeat)) {
    for ($i=0; $i < $repeat; $i++) { 
      demo_drush_print_statement($type);
    }
  }
  else {
    demo_drush_print_statement($type);
  }

}

首先,我们检查参数pass($type)是否是2种可接受的类型之一。如果没有,我们返回Drush错误。如果它被接受,我们继续并检查repeat选项是否已通过以及它是否包含高于1的数值。如果没有,我们称之为demo_drush_print_statement()一次,但如果确实如此,我们会多次调用repeat值。无论如何,我们还将$type参数作为参数传递给函数。

现在您可以继续从终端运行命令并测试参数和选项的工作方式。

用户输入

运行此命令时您会注意到的一件事是,如果我们传递的不是两个接受的参数值,它会返回正确的错误。但是,如果我们根本没有通过任何东西呢?它返回一个通用的Drush错误,它抱怨缺少的参数。

让我们这样做,如果用户没有传递参数,我们会询问他们想要传递什么参数并使用他们交互式提供的值。有一个方便的Drush功能,但整个实现可能如下所示:

// Check for existence of argument
if (!$type) {
  $options = array(
    'success' => dt('Success'),
    'error' => dt('Error'),
  );
  $type = drush_choice($options, dt('What kind of message you\'d like to print?'));
}

...

在检查是否传递了正确的参数之前,这将进入命令回调函数的顶部。但是我们在这做什么呢?

首先,只有当用户没有传递参数时,一切都会发生。其次,我们创建了一组键值对,它们代表了我们为用户提供的选择。数组键表示选择的计算机名称,而值表示人类可读的名称。第三,我们将这个数组沿着一个问题字符串传递给drush_choice()将返回用户选择的机器名函数。这就成了我们的新$type变量(论证)。

所以现在我们可以尝试一下。运行不带参数的命令,系统将要求您输入与两个可用选项之一对应的数字。执行此操作后,您应该看到相应的声明。

例子

正如我之前提到的,为我们自己的命令(drush help ddc运行Drush help命令将列出有关此命令的一些有用信息(参数,选项,描述,别名等)。让我们回到我们的钩子并在命令中添加更多信息:

...

'examples' => array(
  'drush ddc error' => 'Prints the statement once with the error flag.',
  'drush ddc success --repeat=10' => 'Prints the statement 10 times with the success flag.',
 ),

 ...

我们有代表示例命令用法的键,以及描述在运行命令时将发生什么的值。现在,如果我们运行drush help ddc,我们可以看到这些命令如何使用的有用示例。

结论

这是结束本教程的好地方,因为我们介绍了定义我们自己的Drush命令的许多基本但重要的方面。我们使用了一个简单的示例,但允许我们说明此过程的许多功能:如何定义命令信息以及如何在回调中使用其中的一些信息。我们查看了参数,选项,甚至看到了如何从终端获取用户输入。

当然还有很多方面我们无法在这里讨论。它们用于更高级的用法,但非常重要,必须牢记它们的存在。例如,您可以指定Drush需要具有的Drupal引导级别才能运行。您还可以为命令指定模块依赖关系,甚至指定运行所需的核心版本。因此,请在Drush API站点文档中查看这些内容以获取更多信息。


来自  https://www.sitepoint.com/drupal-create-drush-command/


Drush is a command line tool built to assist you in working with Drupal from the terminal. It comes by default with a bunch of useful commands, such as downloading, enabling or even updating modules. But modules can define their own commands to have Drush perform operations using their code.

In this article we are going to look at creating a Drush command for a fictitious module that really doesn’t do anything. The purpose is to illustrate what you need to do on the Drush side of things and not have to worry about the actual functionality of the module that defines the command. If you want to follow along, I assume that you already have your own custom module set up. Doesn’t matter what it does.

All the code we write is available in this repository so if you want to follow along or even skip ahead, you can check it out. Each commit represents a different step we take in the tutorial.

Our module

The demo_drush module functionality we want to expose to Drush will be super simple. It’s a function that sets the Hello world! message:

function demo_drush_print_statement() {
  drupal_set_message(t('Hello world!'));
}

It’s not much but it will help us understand how to use Drush to print this statement to the terminal screen, and in doing so, how to configure the command to perform all sorts of powerful operations. We’ll be adjusting it in the course of this tutorial to demonstrate various possibilities.

The Drush command file

The first thing we need to do is add a new file to our module’s folder with the name ending in .drush.inc. Drush will scan the codebase and pick it up based on this name to load the functions we declare inside.

It is also best practice to name this file after the module you place it in. For our case, this would be demo_drush.drush.inc (my module’s name is demo_drush). And for now, just open php tags (<?php) at the top and save the file.

Command hook and callback

There are 2 main components in the Drush command architecture: the hook implementation where we define the commands and their configurations, and the callback functions that get triggered by the command. There are of course other functions that get called in the process (such as validation or pre/post callbacks), but we will not cover them in this tutorial.

First, let’s implement hook_drush_command() and define a simple command called drush-demo-command with an alias of ddc:

/**
 * Implements hook_drush_command().
 */
function drush_demo_drush_command() {

  $items['drush-demo-command'] = array(
    'description' => 'Demonstrate how Drush commands work.',
    'aliases' => array('ddc'),
  );

  return $items;
}

With this hook implementation (henceforth referred to as the hook) we return a new key in the array that will be the full command name. Inside this array, we configure it. For now, we specified a simple description and an alias for the command. So if we run drush help ddc, we get printed to our terminal the description and the alias of the command.

The second part of the Drush command architecture is the callback function. As it is now, Drush expects a function to be declared called drush_drush_demo_command(). This default naming structure starts with drushfollowed by the name of the command all connected with underscores. So let’s quickly declare it and use it to call the demo_drush_print_statement() function we wrote earlier:

/**
 * Callback for the drush-demo-command command
 */
function drush_drush_demo_command() {
  demo_drush_print_statement();
}

Now if you clear the drush cache (drush cc drush), you can run the drush ddccommand and you should see Hello world! printed to the screen. Congratulations, your most basic Drush command works.

Although for the rest of the tutorial we will continue with this default naming convention, you are not necessarily restricted to it. If you want to give the callback function another name, you can add a new key to the hook specifying the name:

...

'callback' => 'drush_demo_test'

...

Now you can declare a function called drush_demo_test() and this is the one to get called automatically by this command. For now though, we will stick with our drush_drush_demo_command() name.


Arguments and options

One of the basic things you can do with Drush commands is pass them arguments and options. The key difference between the two is that the former are mandatory whereas the latter are not. Another distinction is in the way the values are passed to the callback function. Arguments are passed as function parameters (in order) while options are retrieved in the callback using a special helper function (drush_get_option).

So inside the hook for our command, let’s add both the arguments and options information:

...

'arguments' => array(
  'type' => 'The type of statement (error or success).',
),
'options' => array(
  'repeat' => 'The number of statement repeats.',
),

...

We declared 1 argument (called type) and one option called repeat. The values should explain their purpose but how they are used is maybe not so obvious. The argument type will be the first string that gets written after the command name in the terminal (drush drush-demo-command or drush ddc). The option will be an integer value that gets assigned to the --repeat flag in the command.

Example:

drush ddc error --repeat=10

This command should make the printed statement an error and have it print 10 times to the terminal screen. Now let’s adjust our code to make this happen.

First, let’s modify the demo_drush_print_statement() function:

function demo_drush_print_statement($type = NULL) {
  drupal_set_message(t('Hello world!'), $type);
}   

Now the type of statement printed is dynamic. Second, let’s modify the command callback function and change it to this:

function drush_drush_demo_command($type = FALSE) {

  // Check for correct argument
  $correct_args = array('error', 'success');
  if (!in_array($type, $correct_args)) {
    return drush_set_error(dt('"@type" is not a valid statement type. Please choose between "success" and "error".', array('@type' => $type)));
  }

  // Option
  $repeat = drush_get_option('repeat', 1);
  if ($repeat > 1 && is_numeric($repeat)) {
    for ($i=0; $i < $repeat; $i++) { 
      demo_drush_print_statement($type);
    }
  }
  else {
    demo_drush_print_statement($type);
  }

}

First, we check whether the argument passed ($type) is one of the 2 accepted types. If not, we return a Drush error. If it is accepted, we continue and check if the repeat option has been passed and if it contains a numeric value higher than 1. If it doesn’t, we call our demo_drush_print_statement() once, but if it does, we do so as many times as the repeat value. In any case, we also pass the $type argument to the function as a parameter.

Now you can go ahead and run the command from the terminal and test out how the argument and option work.

User input

One thing you’ll notice when running this command is that if we pass something else than the two accepted argument values, it returns the good error. But what if we don’t pass anything at all? It returns a generic Drush error that complains about the missing argument.

Let’s make it so that if a user doesn’t pass an argument, we ask them what argument they’d like to pass and use the value they provide interactively. There is a handy Drush function for this, but the whole implementation could look like this:

// Check for existence of argument
if (!$type) {
  $options = array(
    'success' => dt('Success'),
    'error' => dt('Error'),
  );
  $type = drush_choice($options, dt('What kind of message you\'d like to print?'));
}

...

This goes to the top of the command callback function before checking whether the correct argument was passed. But what are we doing here?

First, everything happens only if the user has not passed an argument. Second, we create an array of key-value pairs that will represent the choices we give the user. The array keys represent the machine name of the choice while the values, the human readable name. Third, we pass this array along side a question string to the drush_choice() function that will return the machine name of the choice the user makes. And that becomes our new $type variable (the argument).

So now we can try it out. Run the command with no argument and you will be asked to type in a number that corresponds to one of the two available choices. Upon doing that, you should see the statement printed accordingly.

Examples

As I mentioned before, running the Drush help command for our own command (drush help ddc) will list some useful information about this command (arguments, options, description, aliases, etc). Let’s go back to our hook and add some more information to our command:

...

'examples' => array(
  'drush ddc error' => 'Prints the statement once with the error flag.',
  'drush ddc success --repeat=10' => 'Prints the statement 10 times with the success flag.',
 ),

 ...

We have the keys that represent the example command usage, and the value which describes what will happen if the command was run. Now if we run drush help ddc, we can see these helpful examples of how this command can be used.

Conclusion

Here is a good place to end this tutorial since we covered a lot of the basic but important aspects of defining our own Drush command. We used a simple example but one that allowed us to illustrate many features of this process: how to define the command information and how to make use of some of that inside of a callback. We looked at arguments, options and even saw how we can get user input from the terminal.

There are of course many more aspects that we could not cover here. They are for more advanced usages but very important and must keep in mind that they exist. For example, you can specify what Drupal bootstrap level Drush needs to have in order to run. You can also specify a module dependency for the command or even what version of core it needs to run. So do check up on these things as well on the Drush API site and in the docs for more information.


来自  https://www.sitepoint.com/drupal-create-drush-command/

附件大小
文件 drush_demo.rar1.06 KB
普通分类: