Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UniqueConstraint worked on annotation on Parent class, not anymore after using Attribute #11421

Open
rudy286 opened this issue Apr 23, 2024 · 0 comments

Comments

@rudy286
Copy link

rudy286 commented Apr 23, 2024

BC Break Report

Q A
BC Break yes
Version 2.19.4
php 8.1
DB PostgrSQL
Symfony 6.4

Summary

During the upgrade from php 7.4 to php 8.1 (same DB server, with same database_url, from sf 5.4 to 6.4), I have a break while converting Annotation to Attribute: does not work for ORM\UniqueConstraint.

Note: My application extend the user (utilisateur) class from my custom bundle (it is an important detail as we will see in the end):

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use My\MyBundle\Entity\Utilisateur as BaseUtilisateur;

#[ORM\Table(name: '`utilisateur`')]
#[ORM\Entity(repositoryClass: \App\Repository\UtilisateurRepository::class)]
class Utilisateur extends BaseUtilisateur
{
}

Previous behavior

//...

/**
 * @ORM\MappedSuperclass
 * @ORM\HasLifecycleCallbacks
 * @ORM\Table(
 *  name="utilisateur",
 *  uniqueConstraints={
 *    @ORM\UniqueConstraint(
 *      columns={"identifiant"},
 *      options={"where": "est_actif = true"}
 *    )
 *  },
 * )
 */
class Utilisateur implements UserInterface, EquatableInterface
{
// ...

This code would produce this migration (php bin/console make:migration):

// ...
    public function up(Schema $schema): void
    {
        // this up() migration is auto-generated, please modify it to your needs
        // ...
        $this->addSql('CREATE UNIQUE INDEX UNIQ_1D1C63B3C90409EC ON utilisateur (identifiant) WHERE est_actif = true');
   // ...
}

Current behavior

With attributs, now the code produces this migration (php bin/console make:migration):

// ...
    public function up(Schema $schema): void
    {
        // this up() migration is auto-generated, please modify it to your needs
        $this->addSql('CREATE UNIQUE INDEX UNIQ_1D1C63B3C90409EC ON "utilisateur" (identifiant)');
   // ...
}

How to reproduce

In my class user I tried 2 way to write the UniqueConstraint:

  1. combined with Table:
//...

#[ORM\MappedSuperclass]
#[ORM\HasLifecycleCallbacks]
#[ORM\Table(name: 'utilisateur', uniqueConstraints: [
    new ORM\UniqueConstraint(
        columns: ['identifiant'],
        options: ["where" => "est_actif = true"],
        )
])]
class Utilisateur implements UserInterface, EquatableInterface
{
// ...
  1. separated from Table (default when using rector to automatically migrate anotations to attributes:
//...

#[ORM\MappedSuperclass]
#[ORM\HasLifecycleCallbacks]
#[ORM\Table(
    name: "utilisateur",
)]
#[ORM\UniqueEntity(
    columns: ["identifiant"],
    options: ["where" => "est_actif = true"],
)]
class Utilisateur implements UserInterface, EquatableInterface
{
// ...
  1. I even tryed to remove the prefix ORM to be more "compliant" with the documentation:
//...
use Doctrine\ORM\Mapping\Table;
use Doctrine\ORM\Mapping\UniqueConstraint; // I've checked, this file exists in folder vendor

#[ORM\MappedSuperclass]
#[ORM\HasLifecycleCallbacks]
#[Table(
    name: "utilisateur",
)]
#[UniqueEntity(
    columns: ["identifiant"],
    options: ["where" => "est_actif = true"],
)]
class Utilisateur implements UserInterface, EquatableInterface
{
// ...

According to the documentation, the parameter fieldis required, so I added it, still produce the not expected migration

#[Table(
    name: "utilisateur"
)]
#[UniqueConstraint(
    fields: ["identifiant"],
    columns: ["identifiant"],
    options: ["where" => "est_actif = true"]
)]

I explicitly told doctrine to use attibutes:

## config/packages/doctrine.yaml
### ...
    orm:
        auto_generate_proxy_classes: true
        naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
        auto_mapping: false
        mappings:
            App:
                is_bundle: false
                type: attribute
                dir: '%kernel.project_dir%/src/Entity'
                prefix: 'App\Entity'
                alias: App

Note: If I update the child class 'user' (utilisateur) it will work as the following code shows, BUT, I need my bundle to works for all apps using MyBundle:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use My\MyBundle\Entity\Utilisateur as BaseUtilisateur;

#[ORM\Table(name: '`utilisateur`')]
#[ORM\Entity(repositoryClass: \App\Repository\UtilisateurRepository::class)]
#[ORM\UniqueConstraint(
    name: 'uniq_identifiant_actif',    // here I added a name, or it will conflict with parent constraint, i just want to check what happend if i created a constraint here for the science
    columns: ['identifiant'],
    options: ['where' => 'est_actif = true']
)]
class Utilisateur extends BaseUtilisateur
{
}

And the migration created:

// ...
    public function up(Schema $schema): void
    {
        // this up() migration is auto-generated, please modify it to your needs
        $this->addSql('CREATE UNIQUE INDEX UNIQ_1D1C63B3C90409EC ON "utilisateur" (identifiant)'); // this comes from the  is the attribut of the parent user class: FAIL 
        $this->addSql('CREATE UNIQUE INDEX uniq_identifiant_actif ON "utilisateur" (identifiant) WHERE est_actif = true'); // this comes from the attribute of the child user class: SUCCESS

This suggest myBundle can't hold the description of the user entity of all my apps using the bundle.
It looks like all the apps using the same bundle must explicitly tells ORM how to migrate correctly the constraint (why would i create a bundle to extend the parent class then?)

Do you confirm there is a break/regression here, or it is something else?
Any hint welcome !

thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant