Drupal 8 batch process: why and when you should use it
For one of our Drupal 8 projects, we had to use a Batch process. We will use this opportunity to talk a bit about Batch processes on Drupal 8, how and when these should be used.
WHAT IS A BATCH PROCESS
A batch process means executing a series of functions without any external (end-user) interference. It implies the execution of a series of programs each on "batch" (set) of inputs. Thus the name of batch processes.
WHY USE A BATCH PROCESS
The batch process job comes in handy when we’re handling large amounts of data that in normal circumstances would cause a PHP timeout.
EXAMPLE OF USING A BATCH PROCESS
Let's say you have a view that filters all the article content types that have the field_boring
set as TRUE and you want to delete all of them (because they’re sooo boring). It wouldn't be such a big deal but, your view has 500+ results. What can you do? To delete them manually would take a lot of time and would prove more than inefficient.
To start deleting the required information, you will need:
- a controller: we will call ours Delete.php
- info file: module.info.yml
- routing: module.routing.yml
We start with creating the .info file
, just to let Drupal know that you have something worth running.
module.info.yml: name: Delete description: Delete articles core: 8.x type: module package: Custom
Then, we create the routing. So Drupal knows when your code should be run, we will set it to run when we access the path /delete-boring-articles
.
module.routing.yml: module.delete: path: '/delete-boring-articles' defaults: _controller: '\Drupal\module\Controller\module::delete' _title: 'Deletes boring article' requirements: _permission: 'administer node'
Last but not least, we create the php file in which it all the deleting magic happens. We start off with defining the batch function:
$batch = [ 'title' => t('Deleting'), 'operations' => $operations, 'finished' => finished_callback(), ]; batch_set($batch);
Then we define the $operations
variable, this needs to contain an array with the functions that need to be run.
Since we do not know the number of times we need to run the function or on which nodes to run it, I've called it inside a foreach and passed the node id to it (see Delete.php below).
After that, we just need to tell it what to do once the process is finished.
function finished_callback() { $path = '/wherever/you/want/to/go; return new RedirectResponse($path); }
You could simply add another function or a redirect here, however it's not really necessary, you could just leave this empty.
The actual Delete.php:
<?php /** * @file * Contains \Drupal\module\Controller\Delete. */ namespace Drupal\module\Controller; use Drupal\Core\Controller\ControllerBase; use Drupal\node\Entity\Node; use Symfony\Component\HttpFoundation\RedirectResponse; /** * Initialize class. */ class Delete extends ControllerBase { /** * @return \Symfony\Component\HttpFoundation\RedirectResponse */ public function delete() { $view_results = views_get_view_result('boring_articles', 'page_1'); $operations = []; foreach ($view_results as $key => $value) { $operations[] = [ [ $this->batchFunction($value->_entity->id()), [], ], ]; } $batch = [ 'title' => t('Deleting'), 'operations' => $operations, 'finished' => $this->finished_callback(), ]; batch_set($batch); } function batchFunction($id) { $video = Node::load($id); $video->delete(); } function finished_callback() { $path = '/wherever/you/want/to/go'; return new RedirectResponse($path); } }
Now, you got rid of all those boring articles that were bugging you...no pun intended.
Hope this helps. If you have problems with the code or some questions, you will find a comment section below, so feel free to use it.