Score:0

Batch Error: Using $this when not in object context, so Can I call batch method in non static way?

sy flag

The existing code

when a form is submitted I execute this batch :

/**
 * {@inheritdoc}
 */
public function submitForm(array &$form, FormStateInterface $form_state) {

  $node_titles = ['node1', 'node2', 'node3', 'node4', 'node5'];

  $batch_builder = (new BatchBuilder())
    ->setTitle(t('Processing Batch'))
    ->setInitMessage('Batch is starting')
    ->setProgressMessage('Processed @current out of @total.')
    ->setErrorMessage('Batch has encountered an error');

  $batch_builder->addOperation(['Drupal\drupolo_batch\Controller\NodeUpdate','run'], $node_titles);

  batch_set($batch_builder->toArray());
}

The batch_set() method always calls a static method, and this works as expected:

public static function run($title, $etm, &$context) {
  $node_storage =  \Drupal::entityTypeManager()->getStorage('node');

  $values = [
    'type' => 'article',
    'title' => $title,
  ];
  $node = $node_storage->create($values);
  $node->save();
  $context['results'][] = '';
}

Problem

I want to access the injected service: $this->entityTypeManager, so I have tried to use a non-static method to access the injected entityTypeManager service.

When I try this:

<?php
namespace Drupal\drupolo_batch\Controller;

use Drupal\Core\Entity\EntityTypeManagerInterface;

class NodeUpdate {
  public $entityManager;

  public function __construct(EntityTypeManagerInterface $entityManager) {
    $this->entityTypeManager = $entityManager;
  }
   ....
  public  function run($title,$etm,  &$context) {
    kint($this->entityTypeManager); die();
  }
}

I get this error :

ResponseText: Error: Using $this when not in object context in Drupal\drupolo_batch\Controller\ NodeUpdate::run() (line 15 of NodeUpdate.php).

!! the method call is still static ::run()

Solution that doesn't work for me

  1. I have declared my class as a service with the proper dependencies:
services:
  drupolo_batch.node_update:
    class:  Drupal\drupolo_batch\Controller\NodeUpdate
    arguments: ['@entity_type.manager']
  1. In addOperation method I have passed my service
$service = \Drupal::service('drupolo_batch.node_update');
$batch_builder->addOperation([ $service ,'run'], $node_titles);
  1. This is called in a non-static way but I get this error :

The website encountered an unexpected error. Please try again later. AssertionError: The container was serialized. in assert() (line 28 of core/lib/Drupal/Core/DependencyInjection/Container.php). assert(, 'The container was serialized.') (Line: 28) Drupal\Core\DependencyInjection\Container->__sleep() serialize(Array) (Line: 89) Drupal\Core\Queue\DatabaseQueue->doCreateItem(Array) (Line: 56) Drupal\Core\Queue\DatabaseQueue->createItem(Array) (Line: 993) _batch_populate_queue(Array, 0) (Line: 899) batch_process() (Line: 63) Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 593) Drupal\Core\Form\FormBuilder->processForm('codimth_batch_form', Array, Object) (Line: 321) Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 91) Drupal\Core\Controller\FormController->getContentResult(Object, Object) call_user_func_array(Array, Array) (Line: 123) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}() (Line: 573) Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}() (Line: 151) Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68) Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57) Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47) Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106) Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85) Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47) Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 38) Drupal\webprofiler\StackMiddleware\WebprofilerMiddleware->handle(Object, 1, 1) (Line: 52) Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23) Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708) Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Question

  1. Is there any way to call the batch method non statically to access the injected services?
  2. What is the cause of the previous error and how can I fix it?
  3. Should I pass the services as parameters instead of injecting them into my service?
cn flag
Why not use `\Drupal::service` in the static method itself? Otherwise the `drupolo_batch.node_update` service needs to be made serialisable so it can be stored in the database with the batch op.
Jaypan avatar
de flag
I think error number for #3 is a result of having entityTypeManager be public. Try changing it to protected.
Marwen Amri avatar
sy flag
@Clive I prefer to inject the services for easy unit testing and also bc this service will be used by other services so thank you I will try to serialize the service,
Jaypan avatar
de flag
You don't have to serialize the service yourself, you just need to make sure that it's serializable. As I said in my earlier comment, I believe that setting the entity type manager as public can cause your problem, as I believe it causes serialization errors.
Marwen Amri avatar
sy flag
@Jaypan I have already make the entityTypeManager prop protected but that doesn't work, stil have the same error, anywhy thank you but I will juste use the satic method .
Jaypan avatar
de flag
In that case, Clive's suggestion of using a static call from your static method is how you will need to proceed.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.