Overview
Batching processing allows large amount of data to be processed without putting stress on your server. Also, there is a timeout limit per page load on your browser. Therefore, processing data that requires a lot of time in 1 go will not work.
In Drupal 8, the Batch API allows you to process in batches. What you need are:
$operationns
: Breakdown your data into smaller chunks to be processed for each batch(operation).batch_set($batch)
: Define and setup your batch.batchDelete()
: Implement the operation callback method. Define how to process the batch data.batchFinished()
: Implement the finish callback method. Define what to do after batch processing is complete.
In the tutorial below, I will show how to delete Article nodes in batches using node ID ranges.
Create routing to your batch delete form page
Create an URL for your batch delete form page by adding the following routing information in ./modules/tradesteps/tradesteps.routing.yml
.
tradesteps.batch_delete_form: path: '/batch_delete_form' defaults: _form: 'Drupal\tradesteps\Form\BatchDeleteForm' _title: 'Batch delete nodes form' requirements: _permission: 'access content'
Implement your batch delete form class
In the code below, focus on
submitForm()
: It is inside this function that you create and setup your batch processing usingbatch_set($batch);
. The only required array element of$batch
is the attribute$operations
. It is an array of operations that your batch will process. The list of operations are in the form of an array containing two components. The first component is the function to call and the second is an array of parameters to pass to that function.batchDelete()
: The operation callback function. It will delete nodes listed in$smaller_batch_data
parameter.batchFinished()
: The finish callback function. It will display success or error message after batch processing is complete.
<?php namespace Drupal\tradesteps\Form; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; class BatchDeleteForm extends FormBase { public function buildForm(array $form, FormStateInterface $form_state) { $form['from_nid'] = [ '#type' => 'textfield', '#title' => $this->t('From node ID'), '#required' => TRUE, ]; $form['to_nid'] = [ '#type' => 'textfield', '#title' => $this->t('To node ID'), '#required' => TRUE, ]; // Add a submit button that handles the submission of the form. $form['actions']['submit'] = [ '#type' => 'submit', '#value' => $this->t('Delete nodes in batches'), ]; return $form; } public function submitForm(array &$form, FormStateInterface $form_state) { // Get all data to be processed. $from_nid = $form_state->getValue('from_nid'); $to_nid = $form_state->getValue('to_nid'); $all_nids = \Drupal::entityQuery('node') ->condition('type', 'article') ->condition('nid', $from_nid, '>=') ->condition('nid', $to_nid, '<=') ->execute(); // Breakdown your process into small batches(operations). // Delete 50 nodes per batch. $operations = []; foreach (array_chunk($all_nids, 50) as $smaller_batch_data) { $operations[] = ['\Drupal\tradesteps\Form\BatchDeleteForm::batchDelete' , [$smaller_batch_data]]; } // Setup and define batch informations. $batch = array( 'title' => t('Deleting nodes in batch...'), 'operations' => $operations, 'finished' => '\Drupal\tradesteps\Form\BatchDeleteForm::batchFinished', ); batch_set($batch); } // Implement the operation method. public static function batchDelete($smaller_batch_data, &$context) { // Deleting nodes. $storage_handler = \Drupal::entityTypeManager()->getStorage('node'); $entities = $storage_handler->loadMultiple($smaller_batch_data); $storage_handler->delete($entities); // Display data while running batch. $batch_size=sizeof($smaller_batch_data); $batch_number=sizeof($context['results'])+1; $context['message'] = sprintf("Deleting %s nodes per batch. Batch #%s" , $batch_size, $batch_number); $context['results'][] = sizeof($smaller_batch_data); } // What to do after batch completed. Display success or error message. public static function batchFinished($success, $results, $operations) { if ($success) $message = count($results). ' batches processed.'; else $message = 'Finished with an error.'; drupal_set_message($message); } public function getFormId() { return 'tradesteps_batch_delete_form'; } }
Test batch nodes delete form
- Clear your cache.
- Open http://your-domain.com/batch_delete_form
- Type in the node ID ranges and then run the batch.
Batch Delete Form
Batch running: batchDelete()
Batch finished: batchFinished()
Note
If you are using Batch API outside of form API, then you have to explicitly call batch_process('/node');
after batch_set($batch);
to run the batch operation. Otherwise, batch operation will not run.
Github
- https://github.com/xuanngo2001/drupal-batch-delete-nodes.git