Symfony 4: добавить ограничение new UniqueEntity() в x, если y равно null

У меня есть класс сущностей с двумя свойствами: страна и штат. Записи в базе данных должны быть уникальными. Это означает, что если я отправлю в базу данных country=Germany и state=BB, она добавит новую запись, если такой же записи еще не существует.

Однако свойство состояния может быть нулевым, в этом случае оно не отображается доктриной (?), и я все равно могу указать значение для страны. Проблема в том, что я не могу сделать эту запись уникальной, то есть вы не сможете ввести одну и ту же страну несколько раз без уникального состояния. Вот где я борюсь.

Я пробовал различные модификации ограничений сущности.

Вот код, который проверяет, что страна и штат являются уникальной записью в базе данных:

public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addConstraint(new UniqueEntity([
            'fields' => ['country', 'state'],
            'message' => 'State is already used with this country!',
        ]));
    }

Я думаю, вам нужно будет написать собственное ограничение, как описано здесь: symfony.com/doc/current/validation/custom_constraint.html

Vyctorya 02.07.2019 13:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
2
1
485
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/tutorials/composite-primary-keys.html

Возможно, вам подойдет объект с составным первичным ключом.

/**
 * @UniqueEntity
 */
class UniqueEntity
{
    /** @Id @Column(type = "string") */
    private $country;
    /** @Id @Column(type = "string") */
    private $state = 'empty'; // case you have no state and a primary key can't be null

    public function __construct($country, $state)
    {
        $this->country= $country;
        $this->state= $state;
    }

    public function getCountry()
    {
        return $this->country;
    }

    public function getState()
    {
        return $this->state;
    }
}

Единственное ограничение заключается в том, что вы не можете иметь нулевое значение в качестве состояния, если это первичный ключ. Но опять же, вы можете иметь значение по умолчанию, например «нет», в качестве значения состояния, которое будет как приемлемым ключом, так и уникальным стоимость

Спасибо за ответ; возможно, мой вопрос был немного неясным, но и страна, и штат являются частью одного и того же объекта.

urlichsanais 02.07.2019 13:38

Понятно, что составной ключ — это уникальный ключ, состоящий из 2 или более полей вашего объекта, в вашем штате и стране, что гарантирует уникальность комбинации обоих. Единственное ограничение заключается в том, что вы не можете иметь нулевое значение в качестве состояния, если это первичный ключ. Но опять же, вы можете иметь значение по умолчанию, например «нет», в качестве значения состояния, которое будет как приемлемым ключом, так и уникальным стоимость

Yoann MIR 02.07.2019 15:21

Я знаю, что это составной ключ, но в этом объекте есть только один ключ, и я не собираюсь создавать фиктивные данные для генерации первичного ключа. :/

urlichsanais 02.07.2019 15:31
Ответ принят как подходящий

Мне потребовалось некоторое время, но это собственный класс валидатора, который я написал для решения своей проблемы. Может быть, это поможет кому-то еще.

<?php

namespace XXX;

use XXX\Services\CountryAndStateService;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class CountryAndStateValidator extends ConstraintValidator
{
/**
 * @var countryAndStateService
 */
 private $countryAndStateService;

   /**
    * CountryAndState constructor.
    */
     public function __construct(CountryAndStateService $countryAndStateService)
     {
         $this->countryAndStateService = $countryAndStateService;
     }

     /**
     * Taking country and state; validating whether the same country with state === null does already exist.
     *
     */
     public function validate($value, Constraint $constraint)
     {
        /* Accessing user input of state and country */
        $state = $this->context->getRoot()->getData()->getState();
        $country = $this->context->getRoot()->getData()->getCountry();

        /* Comparing the country user input to the country data in the database */
        $existingCountry = $this->countryAndStateService->getCountryByCountry($country);

        if ($state === null) {
            if ($existingCountry) {
                $this->context->buildViolation($constraint->message)
                    ->addViolation();
            } else {
                return;
            }
         }else {
            return;
        }
    }
}

Другие вопросы по теме