Sunday, 29 March 2015

Creating your own drush commands in drupal



If you are a drupal programmer, you might be aware of drush commands which are very easy to interact with drupal database.

We used to clear the cache everytime in drupal. But it is not very easy to go to cache clear from the ui everytime."drush cc all" is the command which every drupal programmer is  executing in the terminal.

For the execution of the drush commands ,you should have

1.A drush installed in your machine. (clone the drush from git)

2. Go through the readme file provided in the drush folder (drush/README.txt) and do the steps.

3.Once the installation is finished, enjoy the drush commands in drupal.


Why we are using drush commands?

The drush commands can be executed from the terminal and it is a script running from backend of the drupal. Instead of dealing with the admin ui for configuration changes, we can easily handle using drush commands.So it is a shell script interface for drupal.

Eg: I want to enable the new module "My new module"

Steps:
Go to admin/modules and enable the module with the name "My new module". 

In terms of drush command, use the drush command drush en my_new_module 

The module name should be the machine name and it was the human readable name in the UI.The other drush commands are disable (dis), pm-uninstall  etc.


Steps for the generation of drush commands

I am going to elaborate the step by step process for the creation of a drush command in drupal with an example.


 I want to create a drush command to change the value of a field for all the contents of the content type "xyz"

Step1

The drush command needs to be written in a drush.inc file.The drush will search for the drupal directory for all the drush.inc files.If you are implementing your drush command in xyz.module, then drush command can be written in xyz.drush.inc


step2

Implement the hook_drush hook to register the drush command.

/**
* Implements hook_drush_command()
*/
function xyz_drush_command() {
  $items['xyz_field_x_change'] = array(
    'description' => 'Custom drush command to change the value of field_x in the content type xyz'
  'aliases' => array('xyz_z'),
  );
return $items;
}
Here i know the field and content type,so need of arguments. But you can make it generic by giving arguments. So the drush command can be used to change the value of any field in a specific content type.But the implementation will become difficult.
The above hook is modified to
function xyz_drush_command() {
  $items['xyz_field_x_change'] = array(
    'description' => 'Custom drush command to change the value of field_x in the content type xyz',
'arguments' => array(
'type' => 'content type',
'field_value' => 'field value'
),
  'aliases' => array('xyz_z'),
  );
return $items;
}
I am putting this point here because of the changes in the requirement day by day.If you want to change the field value of another content type tommorow, then you need to write another command. So try to make the drush commands more generic so that anybody can use it.

step3


Now the command is declared ,but no call back.The call back can be specified in the hook_drush_command or appending drush_ to the drush command.

function drush_xyz_field_x_change($ctype, $field_value) {
//logic goes here.The value should be changed in the database for the field.
}

Use the function "field_attach_update" for changing the value of a field.

If your logic contains more than 1000 entities or more, there is a chance of PHP timeout. Imagine you have 50000 contents of a specific type in your site and you want to modify field value of all. After processing 48000 contents , php timeout happened and what will be your reaction?

So always use batch process if your contents is more.I will cover the batch process basics in a seperate blog.




step4


Now we need to execute our drush command in the terminal.

Run the drush command as 

drush xyx_field_x_change pq pq_field_d

or drush xyz_z pq pq_field_d in the terminal. The script will execute and will do the required changes.


**********************************************************

How to the show the status of the backend process to the user?


Yes , drush command is ready and this will do the job. But how to know whether the process is finished successfully because there is no message printing from our end. So it is a good practise to show the message to the user.

Suppose this is my code at line number 130

L129   : $node->field_x = $new_value;
L130   : field_attach_update($node);
L131   :drush_print("field for". $node->nid. "updated successfully");
L132   : else {
L133   :  drush_print("The updation of field is failed/not happened for ". $node->nid);

$new_value - new field value.
$node - my current processing node
This will print the status for every node and people who is using your drush command will get an idea what s going on.


Simple Example


This example prints the message "Hello User"

/**
* Implements hook_drush_command()
*/
function myname_drush_command() {
  $items['hello_drupal'] = array(
    'description' => 'print Hello',
    'aliases' => array('h_d_m'),
  );
  return $items;
}

function drush_hello_drupal() {
  drush_print('Hello User');
}


No comments:

Post a Comment