Într-un proiect drupal 9 complet decuplat, am un tip de entitate personalizat și am adăugat o constrângere unică pentru mai multe câmpuri, așa cum este descris Aici. Acest lucru funcționează bine și adăugarea unei a doua entitati cu aceleași valori de câmp nu este posibilă. Cu toate acestea, folosesc cereri JSONAPI POST pentru a crea entitățile. Am observat că atunci când emit mai multe solicitări POST cu exact aceleași valori de câmp imediat după alta, metoda validatorului (folosind entityTypeManager->getStorage(...)->getQuery(...)->condition(...)->execute()
pentru a verifica DB) nu returnează alte entități, deoarece nu există încă o entitate duplicată. i.e. se întâmplă atât de repede încât mai multe entități cu valori identice sunt create exact la aceeași amprentă temporală (The creată
valorile entităților sunt identice)!
Ocolirea constrângerii este periculoasă și trebuie prevenită.
Ce pot face pentru a rezolva această problemă?
Actualizați
Aceasta este funcția numită în interiorul ConstraintValidator
validare funcție publică ($entity, Constraint $constraint)
{
...
dacă (!$acest->este Unic($entitate))
$this->context->addViolation($constraint->notUnique);
...
}
funcția privată esteUnică(CustomType $entity) {
$date = $entity->get('data')->value;
$tip = $entitate->bundle();
$angajat = $entitate->get('angajat')->target_id;
$query = $this->entityTypeManager->getStorage('custom_type')->getQuery()
->condition('status', 1)
->condition('tip', $tip)
->condition('angajat', $angajat)
->condition('data', $data);
dacă (! este_null($entity->id()))
$query->condition('id', $entity->id(), '<>');
$workIds = $query->execute();
return empty($workIds);
}
Mă bucur să găsesc orice defecte. Până acum, acest cod funcționează bine în toate celelalte cazuri.
Actualizați Drupal::lock()
Am implementat 2 abonați la eveniment pentru a adăuga și a elibera \Drupal::lock()
asa cum se mentioneaza in comentarii. Folosind xdebug, pot confirma că codul este rulat, totuși, blocarea nu pare să aibă niciun efect. Documentatia pentru Lacăt()
este destul de limitat. Nu sunt sigur ce este în neregulă aici.
<?php
spațiu de nume Drupal\custom_entities\EventSubscriber;
utilizați Symfony\Component\EventDispatcher\EventSubscriberInterface;
utilizați Symfony\Component\HttpKernel\Event\RequestEvent;
utilizați Symfony\Component\HttpKernel\KernelEvents;
clasa JsonApiRequestDBLock implementează EventSubscriberInterface {
/**
* Adaugă o blocare pentru solicitările JSON:API.
*
* @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
* Evenimentul de procesat.
*/
funcția publică onRequest(RequestEvent $event) {
$cerere = $eveniment->getRequest();
if ($request->getRequestFormat() !== 'api_json') {
întoarcere;
}
if ($request->attributes->get('_route') === 'jsonapi.custom_type--work.collection.post' &&
$request->attributes->get('_controller') === 'jsonapi.entity_resource:createIndividual'
) {
$lock = \Drupal::lock();
$lock->acquire('custom_create_lock');
}
}
/**
* {@inheritdoc}
*/
funcție publică statică getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = ['onRequest'];
returnează $evenimente;
}
}
și eliberați blocarea după răspuns
<?php
spațiu de nume Drupal\custom_entities\EventSubscriber;
utilizați Symfony\Component\EventDispatcher\EventSubscriberInterface;
utilizați Symfony\Component\HttpKernel\Event\ResponseEvent;
utilizați Symfony\Component\HttpKernel\KernelEvents;
clasa JsonApiResponseDBRelease implementează EventSubscriberInterface {
/**
* {@inheritdoc}
*/
funcție publică statică getSubscribedEvents() {
$events[KernelEvents::RESPONSE][] = ['onResponse'];
returnează $evenimente;
}
/**
* Eliberați răspunsuri JSON:API.
*
* @param \Symfony\Component\HttpKernel\Event\ResponseEvent $event
* Evenimentul de procesat.
*/
funcția publică onResponse(ResponseEvent $event) {
$răspuns = $eveniment->getResponse();
if (strpos($response->headers->get('Content-Type'), 'application/vnd.api+json') === FALSE) {
întoarcere;
}
$cerere = $eveniment->getRequest();
if ($request->attributes->get('_route') === 'jsonapi.custom_type--work.collection.post' &&
$request->attributes->get('_controller') === 'jsonapi.entity_resource:createIndividual'
) {
// Eliberează blocarea.
$lock = \Drupal::lock();
dacă (!$lock->lockMayBeAvailable('custom_create_lock'))
$lock->release('custom_create_lock');
}
}
}
Aceasta a fost adăugată la servicii.yml
# abonați la eveniment.
custom_entities.jsonapi_db_lock.subscriber:
clasa: Drupal\custom_entities\EventSubscriber\JsonApiRequestDBLock
Etichete:
- { nume: event_subscriber }
custom_entities.jsonapi_response_db_release.subscriber:
clasa: Drupal\custom_entities\EventSubscriber\JsonApiResponseDBRelease
Etichete:
- { nume: event_subscriber }