Рейтинг:0

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

флаг sy

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
Почему бы не использовать `\Drupal::service` в самом статическом методе? В противном случае сервис `drupolo_batch.node_update` необходимо сделать сериализуемым, чтобы его можно было хранить в базе данных с пакетной операцией.
Jaypan avatar
флаг de
Я думаю, что номер ошибки для № 3 является результатом того, что entityTypeManager является общедоступным. Попробуйте изменить его на защищенный.
Marwen Amri avatar
флаг sy
@Clive Я предпочитаю внедрять сервисы для простого модульного тестирования, а также потому, что этот сервис будет использоваться другими сервисами, поэтому спасибо, я попытаюсь сериализовать сервис,
Jaypan avatar
флаг de
Вам не нужно сериализовать службу самостоятельно, вам просто нужно убедиться, что она сериализуема. Как я сказал в своем предыдущем комментарии, я считаю, что установка менеджера типов объектов как общедоступного может вызвать вашу проблему, поскольку я считаю, что это вызывает ошибки сериализации.
Marwen Amri avatar
флаг sy
@Jaypan Я уже сделал защиту entityTypeManager, но это не работает, все еще есть та же ошибка, в любом случае, спасибо, но я просто использую метод satic.
Jaypan avatar
флаг de
В этом случае Клайв предлагает использовать статический вызов из вашего статического метода.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.