LogicException:コントローラーの結果は、関連するキャッシュメタデータを提供していると主張していますが、メタデータのリークが検出されました。コンテンツのレンダリングが早すぎないことを確認してください。返されるオブジェクトクラス:Drupal\rest\ResourceResponse。 Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-> wrapControllerExecutionInRenderContext()内(/ srv/bindings/8c5ccf24ccc9492bb85469725da608ea/code/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWphpperSubscriberの154行目)。
REST ajax getリクエストを介してエンドポイントにアクセスしようとすると、この問題に直面しています。重要なのは、ログインしたときにすべての作品が見つかりましたが、上記の例外を通じてログインしていない場合です。
これが私のコードです
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"));
}
}
そして以下は私の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);
});
});
}
drupalコードに欠けているものを理解できませんでした
エンティティクエリを以下のように変更します
$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();
ResourceResponseクラスはメタデータのキャッシュを担当するCacheableResponseTraitを使用しているため、コードを最後に追加することで解決しました。 POST、PATCH、DELETEでは、リソースが変更されているため、これは望ましくありません。
return new ModifiedResourceResponse($node);
https://tutel.me/c/drupal/questions/249627/logicexception+node+save+via+resourcebase+post#
現在リストされている答えは、従うべき適切な方法だと思います。ただし、私はこれが適切であると思います。jsonapiモジュールをdrupal composerを使用して再インストールすることでこれを(おそらく一時的に)修正することができました。それが誰かを助けるかもしれない場合、これは私がコマンドラインから実行しました:
composer require 'drupal/jsonapi:^1.24'
インストールしようとしているバージョンにコードを変更することを忘れないでください。ご覧のとおり、これはバージョン1.24専用です。