LogicException: le résultat du contrôleur prétend fournir des métadonnées de cache pertinentes, mais une fuite de métadonnées a été détectée. Veuillez vous assurer de ne pas rendre le contenu trop tôt. Classe d'objet retournée: Drupal\rest\ResourceResponse. dans Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-> wrapControllerExecutionInRenderContext () (ligne 154 de /srv/bindings/8c5ccf24ccc9492bb85469725da608ea/code/core/lib/Drupal/Core/EventScripts.
Je suis confronté à ce problème lorsque j'essaie d'accéder à REST endpoint via ajax get request. Chose importante, lorsque j'étais connecté, toutes les œuvres sont trouvées, mais quand je ne le suis pas via l'exception ci-dessus) .
Voici mon code
namespace Drupal\one_rest_api\Plugin\rest\resource;
use Drupal\file\Entity\File;
use Drupal\image\Entity\ImageStyle;
use Drupal\media_entity\Entity\Media;
use Drupal\node\Entity\Node;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\taxonomy\Entity\Term;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\HttpException;
/**
* Provides article resource endpoint
*
* @RestResource(
* id = "one_article_resource",
* label = @Translation("One Article Resource"),
* uri_paths = {
* "canonical" = "/api/one/v1/articles"
* }
* )
*/
class ArticleResource extends ResourceBase
{
/**
* A current user instance.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* Constructs a Drupal\rest\Plugin\ResourceBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param array $serializer_formats
* The available serialization formats.
* @param \Psr\Log\LoggerInterface $logger
* A logger instance.
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* A current user instance.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
array $serializer_formats,
LoggerInterface $logger,
AccountProxyInterface $current_user) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
$this->currentUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->getParameter('serializer.formats'),
$container->get('logger.factory')->get('one_rest'),
$container->get('current_user')
);
}
/**
* Responds to GET requests.
*
* Returns a list of bundles for specified entity.
*
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
* Throws exception expected.
*/
public function get() {
global $base_url;
$response_result = [];
$response_code = 200;
// You must to implement the logic of your REST Resource here.
// Use current user after pass authentication to validate access.
if (!$this->currentUser->hasPermission('access content')) {
throw new AccessDeniedHttpException();
}
$entities = \Drupal::entityQuery('node')
->condition('status', 1)
->condition('type', 'article')
->condition('langcode','en')
->notExists('field_f1')
->sort('created', 'DESC')
->range(0, 20)
->execute();
if(!empty($entities)){
foreach ($entities as $node_id) {
$node = Node::load($node_id);
if(is_object($node)){
$image_url = '';
$image_target = $node->get('field_image')->target_id;
if(!empty($image_target)){
$media = Media::load($image_target);
if(is_object($media)){
$image = File::load($media->get('field_image')->target_id);
$image_url = ImageStyle::load('rest_api')->buildUrl($image->getFileUri());
}
}
$output_tags = [];
$tags = $node->get('field_tags')->getValue();
if(!empty($tags)){
foreach($tags as $key => $tag){
$term = Term::load($tag['target_id']);
$output_tags[] = $term->get('name')->value;
}
}
$result = [
"nid" => $node->id(),
"base_url" => $base_url,
"title" => $node->getTitle(),
"field_image" => $image_url,
"field_tags" => $output_tags
];
$response_result[] = $result;
}
}
}
if(!empty($response_result)) {
$headers = [
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PATCH, DELETE',
'Access-Control-Allow-Headers' => 'Authorization'
];
$response = new ResourceResponse($response_result, $response_code, $headers);
return $response;
}
throw new HttpException(t("Empty Response"));
}
}
Et ci-dessous est mon code TypeScript
load(){
if(this.data){
return Promise.resolve(this.data);
}
return new Promise(resolve => {
this.http.get('https://example.com/api/one/v1/articles?_format=json')
.subscribe(data => {
this.data = data;
resolve(this.data);
},err => {
console.log(err);
});
});
}
Je n'ai pas compris ce qui me manque dans le code drupal
Modifiez votre requête d'entité en quelque chose comme ci-dessous
$entities = \Drupal::entityQuery('node')
->condition('status', 1)
->condition('type', 'article')
->condition('langcode','en')
->notExists('field_f1')
->sort('created', 'DESC')
->range(0, 20)
->accessCheck(false)
->execute();
Je l'ai résolu en ajoutant du code à la fin parce que la classe ResourceResponse utilise CacheableResponseTrait qui est responsable de la mise en cache des métadonnées. Dans POST, PATCH, DELETE, nous ne voulons pas cela car les ressources sont modifiées.
return new ModifiedResourceResponse($node);
https://tutel.me/c/drupal/questions/249627/logicexception+node+save+via+resourcebase+post#
Je pense que les réponses qui sont actuellement énumérées sont les méthodes appropriées à suivre. Cependant, je pense qu'il est pertinent de noter que j'ai pu résoudre ce problème (éventuellement temporairement) en réinstallant le module jsonapi dans drupal à l'aide de composer. Au cas où cela pourrait aider quelqu'un, voici ce que je exécuté à partir de la ligne de commande:
composer require 'drupal/jsonapi:^1.24'
N'oubliez pas de changer le code en la version que vous essayez d'installer. Comme vous pouvez le voir, c'est spécifiquement pour la version 1.24.