教义多对多关系问题

Posted

技术标签:

【中文标题】教义多对多关系问题【英文标题】:Doctrine ManyToMany relationship issues 【发布时间】:2014-01-21 21:50:26 【问题描述】:

我正在尝试将 Doctrine 实体和关系添加到我现有的数据库架构中,但遇到了一些问题。

我有 4 张桌子:

+-------------+  +-----------+  +-----------------+  +-------------------+
| customers   |  | acl_roles |  | acl_permissions |  | acl_customer_role |
---------------  -------------  -------------------  ---------------------
| customer_id |  | id        |  | role_id         |  | customer_id       |
+-------------+  | name      |  | resource_id     |  | acl_role_id       |
                 +------------  | flags           |  +--------------------
                                +------------------

在我的 ACL 中,客户可以有很多角色,每个角色可以有很多权限。客户/角色的映射是通过acl_customer_role 表完成的。

我目前在使这种关系发挥作用时遇到问题。这些是我的实体(为简洁起见,删除了一些标准注释):

class Customer 

   /**
    * @ORM\ManyToMany(targetEntity="AclRole", cascade="persist")
    * @ORM\JoinTable(name="acl_customer_role",
    *    joinColumns=@ORM\JoinColumn(name="acl_role_id", referencedColumnName="customer_id")
    * )
    */
   protected $roles;



class AclRole 

    /**
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;


如您所见,在我的客户实体中,我定义了$roles。这是一个多对多关系,因为许多角色可以属于许多客户。我将连接表设置为acl_customer_role,并指定需要进行连接的列。但是,我收到以下错误:

php Fatal error:  Uncaught exception 'PDOException' with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'acl_customer_role.aclrole_id' in 'on clause'' in vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:641

Doctrine 的查询似乎试图加入显然不存在的'acl_customer_role.aclrole_id'

如何正确指定关系?

更新:

Doctrine 似乎正在修改我的专栏名称。当我指定acl_role_id 时,Doctrine 会去掉第一个下划线并假设列名是aclrole_id(如上述问题中的错误消息所示)。但是,当我添加两个下划线(例如acl__role_id)时,它会留下所有下划线并给出几乎相同的错误,除了现在它无法加入acl__role_id

我有点不知所措..

【问题讨论】:

【参考方案1】:

我知道这个问题很老,但最近我遇到了同样的错误/问题,我找到了解决方案。

默认情况下,Doctrine 使用DefaultNamingStrategy 类生成例如joinColumn、joinTableName、propertyToColumnName 名称:

...
public function joinColumnName($propertyName)

    return $propertyName . '_' . $this->referenceColumnName();

这就是在您的情况下生成aclrole_id 列的原因。

要改变这种行为,您只需在 app/config.yml 文件中将 Doctrine2 的命名策略更改为下划线:

doctrine:

    orm:
        # ...
        naming_strategy: doctrine.orm.naming_strategy.underscore

UnderscoreNamingStrategy

...
public function joinColumnName($propertyName)

    return $this->underscore($propertyName) . '_' . $this->referenceColumnName();

这将生成:acl_role_id

您还可以实现自定义命名策略:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/namingstrategy.html

注意:这是在 2.3 版中引入的。

【讨论】:

以上是关于教义多对多关系问题的主要内容,如果未能解决你的问题,请参考以下文章

教义 - 在多对多关系表中插入记录

教义 - 以表为目标的多对多

教义2多对多自我引用与中间细节

教义加入多对多没有关联

教义2多对多带翻译

从教义中的多对多自引用实体中获取孩子