Добрый вечер.
Мне нужно создать уникальное значение для столбца, который не является идентификатором.
В сущности столбец обозначен следующим образом:
```php
#[ORM\Column(type: 'integer', nullable: true)]
private int $internalId;
```
Я создаю миграцию:
```sql
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE amqp_auth_user ADD internal_id INT NULL');
$this->addSql('CREATE SEQUENCE amqp_auth_user_internal_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('ALTER TABLE amqp_auth_user ALTER internal_id SET DEFAULT nextval(\'amqp_auth_user_internal_id_seq\')');
$this->addSql('ALTER SEQUENCE amqp_auth_user_internal_id_seq OWNED BY public.amqp_auth_user.internal_id;');
}
```
После выполнения запроса на вставку в таблицу все работает, и значение "internal_id" заполняется последовательными числами.
Тем не менее, схема не проходит валидацию и выдает следующую ошибку:
> [ERROR] The database schema is not in sync with the current mapping file.
Команда **orm:schema-tool:update --dump-sql** генерирует запрос на удаление значения по умолчанию для столбца "internal_id":
```sql
ALTER TABLE amqp_auth_user ALTER internal_id DROP DEFAULT;
```
После выполнения этого запроса, как вы понимаете, "internal_id" будет заполняться значением "null".
В чем заключается моя ошибка?
P.S.
Я также попробовал следующий вариант:
```php
#[ORM\Column(insertable: false, updatable: false, columnDefinition: 'serial')]
private int $internalId;
```
Вы столкнулись с проблемой синхронизации схемы базы данных и маппинга Doctrine, так как добавили последовательное значение для столбца `internal_id` через миграцию, но не указали это в настройках ORM.
Когда вы добавляете столбец в базу данных, идентифицируя его как `bigint` или `serial` в миграции, вы должны обязательно указать в вашем классе сущности правильное значение по умолчанию и его свойства.
### Решение 1: Правильная настройка поля
Для того, чтобы избежать конфликта с ORM Doctrine, обеспечьте правильное определение вашего столбца в сущности. Если вы хотите, чтобы `internalId` автоматически заполнялся значениями последовательности, вам нужно настроить его соответствующим образом, используя Doctrine:
```php
#[ORM\Column(type: 'integer', nullable: true, options: ["default" => "nextval('amqp_auth_user_internal_id_seq')"])]
private ?int $internalId = null;
```
Убедитесь, что у вас стоит `nullable: true`, если вы хотите разрешить значения `null`. Не забудьте сделать поле типа `?int` для обработки `null` значений.
### Решение 2: Используйте последовательности
Если у вас уже есть последовательность, вы можете использовать его в вашем SQL-коде, как в вашем примере. Подход с использованием `serial` в `columnDefinition` также должен работать, но необходимо убедиться, что данные правильно отрабатываются.
Пример настройки:
```php
#[ORM\Column(type: 'integer', options: ['default' => 'nextval(\'amqp_auth_user_internal_id_seq\')'], nullable: true)]
private ?int $internalId = null;
```
### Подход с сериализацией
Использование `serial` в `columnDefinition` — это еще один вариант, но он зависит от того, как вы планируете управлять миграциями. Если вы используете `serial`, вы можете не указывать `nextval`, так как это встроенная функциональность PostgreSQL:
```php
#[ORM\Column(type: 'integer', nullable: true, columnDefinition: 'serial')]
private ?int $internalId = null;
```
### Вывод
Чтобы избежать проблем с синхронизацией между вашей базой данных и маппингом Doctrine, убедитесь, что свойства поля описаны верно и что значения по умолчанию совпадают с тем, что было установлено на уровне базы данных. После этого ваши команды Doctrine должны проходить без конфликтов.
Если вы будете продолжать испытывать проблемы, возможно, стоит выполнить `doctrine:schema:update` для полного обновления схемы, но помните, что лучше всего следовать своим миграциям, чтобы обработать все изменения в архитектуре базы данных.
Не читаем документацию: <br/> <a href="https://www.doctrine-project.org/projects/doctrine-orm/en/3.3/reference/basic-mapping.html#identifiers-primary-keys" rel="nofollow">https://www.doctrine-project.org/projects/doctrine...</a> <br/> <pre><code class="php">class Message
{
#[ORM\Id]
#[ORM\Column(name: "internalId", type: Types::INTEGER, nullable: false)]
#[ORM\GeneratedValue]
private int|null $internalId = null;
// ...
}</code></pre> <br/> Если у вас PostgreSQL, то нужно так: <br/> <pre><code class="php">class Message
{
#[ORM\Id]
#[ORM\Column(name: "internalId", type: Types::INTEGER, nullable: false)]
#[ORM\GeneratedValue(strategy: "IDENTITY")]
private int $internalId;
// ...
}</code></pre> <br/> Хотя если, вам ИМЕННО нужен sequence, то на всякий случай можно прямо в <code>strategy</code> это и указать