有时程序在处理大量数据时,运行的时间比较长,这样很容易发生超时现象。这时候就可以使用批处理来解决这个问题。
1.定义表单路由
d9_base.form.test_batch:
path: '/test/batch'
defaults:
_form: 'Drupal\d9_base\Form\TestBatchForm'
_title: 'Test Batch Form'
requirements:
_permission: 'access content'
2.创建表单
<?php
namespace Drupal\d9_base\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class TestBatchForm extends FormBase
{
/**
* Returns a unique string identifying the form.
*
* The returned ID should be a unique string that can be a valid PHP function
* name, since it's used in hook implementation names such as
* hook_form_FORM_ID_alter().
*
* @return string
* The unique string identifying the form.
*/
public function getFormId()
{
return 'test_batch_form';
}
/**
* @inheritDoc
*/
public function buildForm(array $form, FormStateInterface $form_state)
{
$form['update_node_title'] = [
'#type' => 'submit',
'#value' => $this->t('Update All Node Title'),
];
return $form;
}
/**
* @inheritDoc
*/
public function submitForm(array &$form, FormStateInterface $form_state)
{
$nids = \Drupal::entityQuery('node')->execute();
$operations = [
['test_batch_progress', [$nids, 'products']],//进程1
['test_batch_multi_progress', []],//进程2
];
$batch = [
'title' => $this->t('Updating Node ...'),
'operations' => $operations,
'finished' => 'test_batch_finished',//结束时调用
];
batch_set($batch);
}
}
3.在.module文件中分别实现test_batch_progress
、test_batch_multi_progress
和 test_batch_finished
三个方法
function test_batch_progress($nids, $type, &$context) {
$context['message'] = 'Update Node title ...';
$nodes = \Drupal\node\Entity\Node::loadMultiple($nids);
foreach ($nodes as $node) {
if ($node->getType() != $type)//这里只是为了演示传递两个参数$nids和$type的方法,实践中不会有这么2的操作
continue;
$title = $node->getTitle();
$node->setTitle($title . '111');
$node->save();
$results[] = $node->id();
}
$context['results'] = $results;
}
function test_batch_multi_progress(&$context) {
if (empty($context['sandbox'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['current_id'] = 0;
$context['sandbox']['max'] = \Drupal::database()
->query('SELECT COUNT(DISTINCT [nid]) FROM {node}')
->fetchField();
}
$limit = 2;//每次两条记录
$result = \Drupal::database()
->select('node', 'n')
->fields('n', ['nid'])
->condition('n.nid', $context['sandbox']['current_id'], '>')
->orderBy('n.nid')
->range(0, 2)
->execute();
$nids = $result->fetchCol();
$nodes = \Drupal\node\Entity\Node::loadMultiple($nids);
foreach ($nodes as $node) {
$title = $node->getTitle();
$node->setTitle($title . '2222');
$node->save();
$results[] = $node->id();
$context['sandbox']['progress']++;
$context['sandbox']['current_id'] = $node->id();
$context['message'] = \Drupal\Component\Utility\Html::escape($node->getTitle());
}
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
function test_batch_finished($success, $results, $operations) {
if ($success) {
$message = \Drupal::translation()->formatPlural(
count($results),
'One post processed.', '@count posts processed.'
);
} else {
$message = t('Finished with an error.');
}
\Drupal::messenger()->addStatus($message);
}
网友评论