0

Following is the code where I'm willing to update the description of the field_meta_tags of all my products using the batch process.

It's getting executed & working as expected, but only for the first batch.

function mymodule_update_8001($sandbox) {
  if (!isset($sandbox['total'])) {
    $products = \Drupal::entityQuery('commerce_product')
      ->condition('type', 'default')
      ->execute();
    $sandbox['total'] = count($products);
    $sandbox['current'] = 0;
  }

  $products_per_batch = 25;

  $products = \Drupal::entityQuery('commerce_product')
    ->condition('type', 'default')
    ->range($sandbox['current'], $sandbox['current'] + $products_per_batch)
    ->execute();

  foreach ($products as $product_id) {
    $product = Drupal\commerce_product\Entity\Product::load($product_id);
    $product->set('field_meta_tags', serialize(['description' => '']));
    $product->save();
    $sandbox['current']++;
  }

  \Drupal::messenger()
    ->addMessage($sandbox['current'] . ' products processed.');

  $sandbox['#finished'] = empty($sandbox['total']) ? 1 : ($sandbox['current'] / $sandbox['total']);
}

Once the above hook_update_n($sandbox) is executed, getting the following output at the terminal:

 --------------- ----------- --------------- ------------- 
  Module          Update ID   Type            Description  
 --------------- ----------- --------------- ------------- 
  mymodule        8001        hook_update_n   Updates.     
 --------------- ----------- --------------- ------------- 

 // Do you wish to run the specified pending updates?: yes.                                                             

>  [notice] Update started: mymodule_update_8001
>  [notice] Update completed: mymodule_update_8001
>  [notice] Message: 25 products processed.
> 
 [success] Finished performing updates.

Not sure how $sandbox['#finished'] is getting the value as 1, since that's how I remember we ask the batch to stop processing.

  • "Not sure how $sandbox['#finished'] is getting the value as 1, since that's how I remember we ask the batch to stop processing." hook_update_N() is only run a single time. You seem to be mixing up batch processing and hook_update_N(). Nothing will tell hook_update_N() to run multiple times, it's only ever supposed to run a single time. – Jaypan May 18 at 15:11
  • 1
    @Jaypan hook_update_N implementations can act as batch callbacks (and thus invoked multiple times in the same update script). There's a note on it in the docs – Clive May 18 at 16:11
  • No kidding. I stand corrected. Thanks for the link Clive! – Jaypan May 18 at 16:31
  • The declaration should be function mymodule_update_8001(&$sandbox), as arrays have weird pass by value/reference rules in PHP. So, I highly suspect in the UpdateManager(?), this isn't actually being called as a batch. – mpdonadio May 18 at 23:44
0

There is no need for batches if you intend to run all entries in one process.

This is something we had use to update around 30.000 entries i quickly adapted from your example :

/**
 * Query all commerce_product of type default
 *
 * *
 * @param array $sandbox
 *
 * @return string
 *  Number of updated rows
 */
function mymodule_post_update_0801(array $sandbox) {
  /** @var $connection Drupal\Core\Database\Connection */
  $connection = \Drupal::service('database');
  $query = $connection->select('commerce_product', 'p');
  $query->fields('p', ['id'])
    ->condition('type', 'default');
  $toUpdate = $query->execute()->fetchAll();

  $result = array_map( 'update_description_value', $toUpdate);

  return sprintf('Number of row updated: %s', count($result));
}

/**
 * Update a product description
 *
 * @param stdClass $defaultProduct
 *  ->id
 *
 * @return string
 *  product id
 */
function update_description_value($productQueried) {
  /** @var $connection Drupal\Core\Database\Connection */
  $connection = \Drupal::service('database');

  $updated = $connection->update('commerce_product')
    ->fields(['field_meta_tags' => serialize(['description' => ''])])
    ->condition('id', $productQueried->id, '=')
    ->execute();

  return $productQueried->id;
}

Let me know if there is typo somewhere.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.