📜 ⬆️ ⬇️

Batch operations as it is done in Drupal

When developing projects, it is more complicated than a business card site, it is often necessary to process large amounts of data. Quite often, customers want integration with 1C, import of existing prices, upload to Yandex Market, migration from anywhere. Obviously, creating a thousand nodes in one run will not work, and if so, then aka Batch operations come to the rescue.
Start over.

Module creation

example / example.info
name = example description = "example batch" core = 7.x version = "7.x-0.1" 


example / example.module
 <?php function example_menu() { $items["example"] = array( "title" => "Example", "type" => MENU_NORMAL_ITEM, "page callback" => "drupal_get_form", // ,        "page arguments" => array('example_form'), //    'access arguments' => array('administer site configuration'), ); return $items; } //     ,    example_form function example_form($form, &$form_state) { $form["submit"] = array( '#type' => 'submit', '#value' => t('Submit') ); $form["#action"] = url("example"); return $form; } 

')
Here we have an elementary module that registers a menu item in the system, by clicking on which we will see a form with a button. This item is available only to users with the right to configure the site, that is, Drupal will not even show anyone who has a link or a page.

Form processing and batch operation registration

example / example.module
 //          function example_form_submit() { $batch = array( 'title' => t('import'), 'operations' => array( array('example_batch_0', array($_SERVER['REQUEST_TIME'])), // array('example_batch_1', array($_SERVER['REQUEST_TIME'])), // ... ,   ), 'finished' => 'example_batch_finished', ); batch_set($batch);// batch_process();//     } 


Perform batch operation

example / example.module

 //     ,   ,  ,  &$context function example_batch_0($time, &$context) { if (empty($context['sandbox'])) { //  , example_batch_0    $context['sandbox']['progress'] = 0; $context['sandbox']['max'] = 100500; //  ,   } //  - // ,  -  $context["result"] $context['message'] = $context['sandbox']['progress']. "/" . $context['sandbox']['max'] ." - ". ($_SERVER['REQUEST_TIME'] - $time) . " sec"; $context['sandbox']['progress']++; if ($context['sandbox']['progress'] < $context['sandbox']['max']) { $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max']; } } 


$ context ['sandbox'] - our sandbox, the part of the data that belongs only to this function from the package,
when (if) it comes to example_batch_1, the sandbox will be clean again, this allows us to find out at which step of the current operation we are

$ context ['result'] - the part of the data that is available to all functions of the package as they are executed

$ context ['message'] - the string that will be sent to the browser, in our case, you can see the time spent and the overall progress of the current operation

$ context ['finished'] - this value allows the system to understand whether the current operation is completed, 1 or no result means that everything has already been done, a value from 0 to 1 is used to show the progress of the entire batch operation

Complete batch operation

 function example_batch_finished($success, $results, $operations) { if ($success) { drupal_set_message('yep'); } else { drupal_set_message('nope', 'error'); } } 


$ success - means that the package is completed without errors.

$ results - our results

$ operations - our operations, because the same finish can be used for different packages

At last

Do not pass large data structures as arguments, do not store them in the sandbox, or output them to the result. Drupal is able to glue operations together in a single launch, but between launches these structures will be stored in a database. Large volume in the database simply will not be transferred.

About where you can store intermediate data, next time.

Source: https://habr.com/ru/post/144424/


All Articles