命令执行drupal
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.
Drush是一个命令行工具,旨在帮助您从终端上使用Drupal。 默认情况下,它带有一堆有用的命令,例如下载,启用甚至更新模块。 但是模块可以定义自己的命令,以使Drush使用其代码执行操作。
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.
在本文中,我们将研究为一个虚构的模块创建一个Drush命令,该命令实际上什么也没做。 目的是为了说明您需要在Drush方面执行的操作,而不必担心定义命令的模块的实际功能。 如果您想继续,我假设您已经设置了自己的自定义模块。 没关系,它做什么。
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.
我们编写的所有代码都可以在该存储库中找到,因此,如果您想继续学习甚至跳过,可以将其签出。 每个提交代表我们在教程中采取的不同步骤。
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:
我们要向Drush公开的demo_drush
模块功能将非常简单。 这是设置Hello world!
的功能Hello world!
信息:
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.
数量不多,但是它将帮助我们了解如何使用Drush将此语句打印到终端屏幕上,以及在执行此操作时如何配置命令以执行各种强大的操作。 在本教程中,我们将对其进行调整以演示各种可能性。
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.
我们需要做的第一件事是将一个新文件添加到模块文件夹中,名称以.drush.inc
结尾。 Drush将扫描代码库,并根据此名称进行选择,以加载我们在其中声明的功能。
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.
最好的做法是在放置该文件的模块后命名该文件。对于我们来说,这将是demo_drush.drush.inc
(我的模块名为demo_drush
)。 现在,只需打开顶部的php标签( <?php
)并保存文件即可。
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.
Drush命令体系结构中有2个主要组件:钩子实现(在其中我们定义命令及其配置)以及由命令触发的回调函数。 当然,在此过程中还会调用其他函数(例如验证或前/后回调),但是在本教程中我们将不介绍它们。
First, let’s implement hook_drush_command() and define a simple command called drush-demo-command
with an alias of ddc
:
首先,让我们实现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;
}
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 hook
),我们在数组中返回一个新的键,该键将是完整的命令名。 在此阵列内,我们对其进行配置。 现在,我们为命令指定了简单的描述和别名。 因此,如果我们运行drush help ddc
, drush help ddc
在终端上打印命令的描述和别名。
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 drush
followed 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:
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();
}
Now if you clear the drush cache (drush cc drush
), you can run the drush ddc
command and you should see Hello world!
printed to the screen. Congratulations, your most basic Drush command works.
现在,如果您清除drush缓存( drush cc drush
),则可以运行drush ddc
命令,您应该会看到Hello world!
打印到屏幕上。 恭喜,您最基本的Drush命令有效。
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:
尽管在本教程的其余部分中,我们将继续使用此默认命名约定,但不一定要局限于此。 如果您想给回调函数起另一个名字,则可以在hook
添加一个新的密钥来指定名字:
...
'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.
现在,您可以声明一个名为drush_demo_test()
的函数,这是此命令自动调用的函数。 不过现在,我们将继续使用drush_drush_demo_command()
名称。
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).
您可以使用Drush命令执行的基本操作之一是向它们传递参数和选项。 两者之间的主要区别在于,前者是强制性的,而后者不是强制性的。 另一个区别是将值传递给回调函数的方式。 参数是作为函数参数传递的(按顺序),而选项是使用特殊的辅助函数( 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.
我们声明了1个参数(称为type
)和一个选项称为repeat
。 这些值应该说明它们的用途,但是如何使用它们可能并不那么明显。 参数type
将是在终端中的命令名称( drush drush-demo-command
或drush ddc
)之后写入的第一个字符串。 该选项将是一个整数值,该整数值将分配给命令中的--repeat
标志。
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.
此命令应使打印的语句出错,并在终端屏幕上打印10次。 现在,让我们调整代码以实现此目标。
First, let’s modify the demo_drush_print_statement()
function:
首先,让我们修改demo_drush_print_statement()
函数:
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.
首先,我们检查传递的参数( $type
)是否为两种可接受的类型之一。 如果不是,则返回Drush错误。 如果被接受,我们继续检查是否通过了repeat
选项,并且它是否包含大于1的数值。如果不包含,我们将调用demo_drush_print_statement()
一次,但是如果这样做,则执行以下操作:多次作为repeat
值。 无论如何,我们还将$type
参数作为参数传递给函数。
Now you can go ahead and run the command from the terminal and test out how the argument and option work.
现在,您可以继续从终端运行命令,并测试参数和选项的工作方式。
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.
运行此命令时,您会注意到的一件事是,如果我们传递的不是两个可接受的参数值,它会返回正确的错误。 但是,如果我们什么都不通过怎么办? 它返回一个通用的Drush错误,抱怨缺少参数。
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:
让我们做到这一点,以便如果用户不传递参数,我们问他们想要传递什么参数并交互使用他们提供的值。 有一个方便的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?'));
}
...
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).
首先,只有在用户未传递参数的情况下,一切都会发生。 其次,我们创建键-值对数组,以表示我们为用户提供的选择。 阵列键代表选择的机器名称,而值代表人类可读的名称。 第三,我们将此数组与问题字符串一起传递给drush_choice()
函数,该函数将返回用户做出选择的机器名称。 这将成为我们新的$type
变量(参数)。
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.
所以现在我们可以尝试一下。 运行不带参数的命令,系统将要求您键入一个数字,该数字与两个可用选项之一相对应。 完成此操作后,您将看到相应打印的声明。
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:
如前所述,为我们自己的命令( 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.',
),
...
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.
我们有代表示例命令用法的键,以及描述命令运行时将发生的值。 现在,如果运行drush help ddc
,我们将看到这些有关如何使用此命令的有用示例。
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.
这是结束本教程的好地方,因为我们介绍了定义自己的Drush命令的许多基本但重要的方面。 我们使用了一个简单的示例,但其中一个示例使我们能够说明此过程的许多功能:如何定义命令信息以及如何在回调内部使用某些信息。 我们研究了参数,选项,甚至看到了如何从终端获得用户输入。
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.
当然,这里还有许多我们无法涵盖的方面。 它们是用于更高级的用法,但非常重要,必须记住它们的存在。 例如,您可以指定Dupal引导级别Drush需要具有什么才能运行。 您还可以为命令指定模块依赖性,甚至可以指定它需要运行的内核版本。 因此,请在Drush API网站和文档中检查这些内容,以获取更多信息。
命令执行drupal