覆盖Doctrine 2.6中特征属性的关联映射

gen*_*sst 10 php doctrine symfony doctrine-orm symfony-3.3

先决条件:

  • PHP 7.1.8
  • Symfony 3.3.9
  • Doctrine 2.6.x-dev

我想知道是否可以覆盖从inversedBy特征中获取的属性关联映射的属性.

我用作具体用户实体占位符的接口:

ReusableBundle\ModelEntrantInterface.php

interface EntrantInterface
{
    public function getEmail();

    public function getFirstName();

    public function getLastName();
}
Run Code Online (Sandbox Code Playgroud)
  1. 以下架构工作得很好(需要创建User实现的实体EntrantInterface和从这些抽象类派生的所有其他实体AppBundle):

ReusableBundle \实体\ Entry.php

/**
 * @ORM\MappedSuperclass
 */
abstract class Entry
{
    /**
     * @var EntrantInterface
     *
     * @ORM\ManyToOne(targetEntity="ReusableBundle\Model\EntrantInterface", inversedBy="entries")
     * @ORM\JoinColumn(name="user_id")
     */
    protected $user;

    // getters/setters...
}
Run Code Online (Sandbox Code Playgroud)

ReusableBundle \实体\ Timestamp.php

/**
 * @ORM\MappedSuperclass
 */
abstract class Timestamp
{
    /**
     * @var EntrantInterface
     *
     * @ORM\ManyToOne(targetEntity="ReusableBundle\Model\EntrantInterface", inversedBy="timestamps")
     * @ORM\JoinColumn(name="user_id")
     */
    protected $user;

    // getters/setters...
}
Run Code Online (Sandbox Code Playgroud)

并结合使用相似结构的更多实体 EntranInterface

  1. 这就是我想要实现的目标 - UserAwareTrait可以跨多个实体重用:

ReusableBundle \实体\特征\ UserAwareTrait.php

trait UserAwareTrait
{
    /**
     * @var EntrantInterface
     *
     * @ORM\ManyToOne(targetEntity="ReusableBundle\Model\EntrantInterface")
     * @ORM\JoinColumn(name="user_id")
     */
    protected $user;

    // getter/setter...
}
Run Code Online (Sandbox Code Playgroud)

在Doctrine 2.6中,如果我使用超类并想要覆盖它的属性,我会这样做:

/**
 * @ORM\MappedSuperclass
 * @ORM\AssociationOverrides({
 *     @ORM\AssociationOverride({name="property", inversedBy="entities"})
 * })
 */
abstract class Entity extends SuperEntity
{
    // code...
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我希望该实体使用UserAwareTrait和覆盖属性的关联映射...

/**
 * @ORM\MappedSuperclass
 * @ORM\AssociationOverrides({
 *     @ORM\AssociationOverride({name="user", inversedBy="entries"})
 * })
 */
abstract class Entry
{
    use UserAwareTrait;
    // code...
}
Run Code Online (Sandbox Code Playgroud)

...并运行php bin/console doctrine:schema:validate我在控制台中看到此错误:

[Doctrine\ORM\Mapping\MappingException]
类'ReusableBundle\Entity\Entry'名为'user'的字段覆盖无效.

有没有可以遵循的解决方法来达到预期的效果?

  1. 使用trait存储共享属性

  2. 覆盖使用该特征的类中的assotiation mapping或(可能)属性映射

del*_*8uk 0

您必须在自己的代码中尝试一下才能看到,但这可能的。

作为实验,我覆盖了类中的一个特征,然后使用class_uses() http://php.net/manual/en/function.class-uses.php检查该特征

<?php

trait CanWhatever
{
    public function doStuff()
    {
        return 'result!';
    }
}

class X
{
    use CanWhatever;

    public function doStuff()
    {
        return 'overridden!';
    }
}

$x = new X();
echo $x->doStuff();
echo "\n\$x has ";
echo (class_uses($x, 'CanWhatever')) ? 'the trait' : 'no trait';
Run Code Online (Sandbox Code Playgroud)

这输出:

overridden! 
$x has the trait
Run Code Online (Sandbox Code Playgroud)

您可以在这里看到https://3v4l.org/Vin2H

然而,Doctrine Annotations 仍然可能从特征本身而不是重写的方法中获取 DocBlock,这就是为什么我不能给你一个明确的答案。您只需尝试一下即可!