0

I am trying to create a module in Drupal 8 (8.9.11) and this module uses the function hook_entity_presave in order to update a node / entity programmatically. I've tried the answers from hook_entity_presave() doesn't work, I was able to add those in my code.

sno.routing.yml

sno.content:
  path: /node/add/issuances
  defaults:
    _controller: Drupal\sno\Controller\SnoController::sno_entity_presave
  requirements:
    _permission: 'access content'

src/Controller/SnoController.php

namespace Drupal\sno\Controller;

use Drupal\Core\Entity\EntityInterface; use Drupal\node\NodeInterface;

class SnoController {

  public function sno_entity_presave(\Drupal\Core\Entity\EntityInterface $entity) {
    if ($entity->getEntityType()->id() == 'issuances') {
      $entity->set('field_s', ', s. ');
    }   
  }

}

When I got into adding a content of content type issuance (/node/add/issuances), I am getting the following error.

The website encountered an unexpected error. Please try again later.

RuntimeException: Controller "Drupal\sno\Controller\SnoController::sno_entity_presave()" requires that you provide a value for the "$entity" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one. in Symfony\Component\HttpKernel\Controller\ArgumentResolver->getArguments() (line 78 of /var/www/senate-library/vendor/symfony/http-kernel/Controller/ArgumentResolver.php).

1

The exception you get (Controller "Drupal\sno\Controller\SnoController::sno_entity_presave()" requires that you provide a value for the "$entity" argument) is caused from the fact the controller's method associated to the sno.content route you define doesn't get any $entity argument, which is instead listed as its parameters.

That is a route, anyway, not a hook. If you want to implement hook_entity_presave(), you don't need to define a route for that. If the module isn't defining other routes, the sno.routing,yml file isn't even necessary.

As Jaypan already said, hooks aren't methods implemented in a class. They are plain PHP functions with a specific name.
In your case, it should be the following function. I corrected the function code because:

  • In a path like /node/add/issuances, issuances is the content type, or node bundle, not the entity type. As the code should act on a node whose bundle is issuances, the code needs to check the value returned from $entity->bundle().
  • Since hook_entity_presave() is invoked for every entity Drupal saves, it's necessary to check which entity is being saved, by checking the value returned from $entity->getEntityTypeId(), not just its bundle. This handles the case where two different entities have a bundle with the same name.

I took the module machine name from the namespace used in the question code and from the name of the routing file. If those are correct, also the module machine name should be correct.

// Put the following line on the top of the sno.module file.
use \Drupal\Core\Entity\EntityInterface;

/**
 * Implements hook_entity_presave().
 */
function sno_entity_presave(EntityInterface $entity) {
  if ($entity->getEntityTypeId() == 'node' && $entity->bundle() == 'issuances') {
     $entity->set('field_s', '<value to assign to the field>');
  }
}

Alternatively, if the module only has code for a single entity type, hook_ENTITY_TYPE_presave() can be instead used. In this case, it's not necessary to check the entity type, as the hook is only invoked for a single entity type. (In this case, the entity type is Node.)

// Put the following line on the top of the sno.module file.
use \Drupal\Core\Entity\EntityInterface;

/**
 * Implements hook_ENTITY_TYPE_presave().
 */
function sno_node_presave(EntityInterface $entity) {
  if ($entity->bundle() == 'issuances') {
     $entity->set('field_s', '<value to assign to the field>');
  }
}

As for the field, it's usually field_s for a field added via UI. If it's defined from code, the field is simply s. You need to verify the correct way to reference that field, as that isn't clear from the code shown in the code.

As side note, if you edit the code of a module that is installed, you need to install or uninstall a module, to make Drupal notice you added a hook into that installed module, as Drupal caches the list of hooks implemented by modules, and clears it when a module is installed or uninstalled.

0

Hooks are not part of classes. Hooks go into the .module file, and hook is replaced with the key of your module. In your case, your module appears to be named sno, so the function name is right. It just should not be part of a class.

3
  • Thanks for that! I've tried putting the code from here drupal.stackexchange.com/questions/223346/… only in the .module file, but it seems it isn't updating but I am not getting what I want done. I'll try again putting it in .module the code mentioned. – schnydszch Mar 3 at 7:27
  • You will need to clear the registry before your hook is picked up. – Jaypan Mar 3 at 7:52
  • I did that several times (cleared the cache) for the other implementation. – schnydszch Mar 3 at 8:20

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.