【问题标题】:Symfony2 / Doctrine Relationship MappingSymfony2 / 学说关系映射
【发布时间】:2013-04-23 13:25:14
【问题描述】:

我正在使用 syfmony2 框架构建我的第一个应用程序。 现在我稍微介绍一下如何从我的数据库中获取数据。

首先是我的表格(仅重要字段)

# 客户

customer_id |情报 |人工智能 | PK

# 篇文章

article_id |情报 |人工智能 | PK

号码 | VARCHAR

# customer_article(两个字段都构建 PK)

customer_id |情报 | PK

article_id |情报 | PK

现在我想像这样执行一个简单的查询:

SELECT 
   ca.article_id, a.number 
FROM 
   customer_article AS ca
LEFT JOIN 
   article AS a ON a.article_id = ca.article_id
WHERE 
   ca.customer_id = {customer_id}

据我了解文档,最好的方法是 在我的实体 php 文件中进行关系映射。

客户.php

文章.php

CustomerArticle.php

但我很困惑该做什么以及朝哪个方向发展。 (http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html)

在我看来,这一定是正确的关系

Customer 到 CustomerArticle 是一对多(单向)关系

CustomerArticle 到 Customer 是多对一(单向)关系

Article 到 CustomerArticle 是一对多(单向)关系

CustomerArticle 到 Article 是多对一(单向)关系

现在是正确的吗?

现在是否有必要在每个 实体文件?还是我只需要以一种方式进行,例如 客户对客户文章(一对多 - 单向)和 文章到客户文章(一对多 - 单向)

不幸的是,“One-To-May, Unidirectional”是唯一一个没有 教义参考页面上的适当示例。

他们写道: “从 Doctrine 的角度来看,它被简单地映射为单向多对多,其中一个连接列上的唯一约束强制执行一对多基数”

这是否意味着我只需要像页面的“单向多对多”部分那样进行映射?

很抱歉有很多问题。

我阅读了很多文档,但我无法自己回答这些问题。

感谢您的帮助。

26.04.2013 更新

不幸的是,即使在 Lighthart 的帮助和阅读 Doctrine 文档的帮助下,我也无法让它工作。

我认为向您提供有关我的表格和代码的更多详细信息会很有帮助。也许有人可以给我基本的答案,以便我最终理解其背后的概念。

带有一些示例条目的我的表格

Table: customer (PK: customer_id)
+-------------+--------+----------+-------------------+------+-----------+
| customer_id | number | password | email             | salt | is_active |
+-------------+--------+----------+-------------------+------+-----------+
| 1           | CU0001 | 43t9wef  | test@example.com  | test | 1         |
| 2           | CU0002 | 32rk329  | test2@example.com | test | 1         |
+-------------+--------+----------+-------------------+------+-----------+

Table: article (PK: article_id)
+-------------+---------+
| article_id  | number  |
+-------------+---------+
| 1           | TEST-01 |
| 2           | TEST-02 |
| 3           | TEST-03 |
| 4           | TEST-04 |
| 5           | TEST-05 |
+-------------+---------+

自从我第一次发帖后我做了什么?

  • 删除 CustomerArticle.php
  • 删除 customer_article 表
  • 向客户(和文章)实体添加多对多关系

这是实体文件此时的样子(没有方法)

客户.php

<?php
namespace Test\ExampleBundle\Entity;

use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="customer")
 */
class Customer implements UserInterface
{
/**
 * @ORM\Id
 * @ORM\Column(type="integer")
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $customer_id;

/**
 * @ORM\ManyToMany(targetEntity="Article", inversedBy="customers")
 * @ORM\JoinTable(name="customer_article",
 *  joinColumns={ @ORM\JoinColumn(name="customer_id", referencedColumnName="customer_id" ) }
 * )
 */
private $articles;

/**
 * @ORM\Column(type="string", length=255, nullable=false, unique=true)
 */
protected $number;

/**
 * @ORM\Column(type="string", length=255, nullable=false)
 */
protected $password;

/**
 * @ORM\Column(type="string", length=255, nullable=true)
 */
protected $email;

/**
 * @ORM\Column(type="string", length=255)
 */
protected  $salt;

/**
 * @ORM\Column(name="is_active", type="boolean")
 *
 */
protected  $isActive;

// ... methods
}

文章.php

<?php
namespace Test\ExampleBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="article")
 */
class Article
{
/**
 * @ORM\Id
 * @ORM\Column(type="integer")
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $article_id;

/**
 * @ORM\ManyToMany(targetEntity="Customer", mappedBy="articles")
 */
private $customers;

/**
 * @ORM\Column(type="string", length=255, nullable=false, unique=true)
 */
protected $number;

// ... methods
}

当我尝试执行时:

php app/console doctrine:schema:update --force

我收到以下消息

[Doctrine\ORM\ORMException]
Column name `id` referenced for relation from    Test\ExampleBundleBundle\Entity\Customer towards Test\ExampleBundleBundle\Entity\Article does not exist.

我不知道为什么学说要使用列名“id”。我阅读了有关此错误的内容并添加了“JoinColumns”-Code,但没有帮助。

我的目标是什么?

我将一些 csv 文件中的数据导入到表中: "customer", "article" 也放入当前不存在的表 "customer_article"。

在我的应用程序中,每个客户都有几篇引用他的文章。 所以表格看起来像这样

customer_article
+-------------+------------+
| customer_id | article_id |
+-------------+------------+
| 1           | 1          |
| 1           | 2          |
| 1           | 5          |
| 2           | 2          |
| 2           | 5          |
+-------------+------------+

这不是商店或类似的东西。这很难解释,所以首先只需要知道每个客户都有未定义数量的相关文章。

现在我必须能够使用 tthe customer_id 获取与一位客户相关的所有文章。 (看我上面开始帖子中的示例sql语句)

希望你能帮助我。

非常感谢大家。

【问题讨论】:

    标签: mysql symfony doctrine entity-relationship


    【解决方案1】:

    这看起来确实像客户和文章的双向多对多。您将构建的实体是 Customer.php 和 Article.php,您可以通过注释在这些文件中指定多对多,或者根据您的偏好在教义.orm.yml 中指定。

    Doctrine 将为您制作中间表(customer_article)并进行管理。

    您将使用 DQL:

    $query = $em->createQuery("SELECT a FROM Article a JOIN a.customer c");
    $users = $query->getResult();
    

    然后您将文章作为实体处理,并调用 article.getCustomer() 以获取与文章关联的客户列表。

    这是与 SQL 完全不同的范例,需要一些时间来适应。

    【讨论】:

    • 感谢您的反馈。我有点困惑这是否意味着我必须删除我的 CustomerArticle 实体并使用它创建表?您写道“Doctrine 将为您制作中间表 (customer_article) 并对其进行管理。”这是否意味着我在 Customer.php 和 Article.php 中进行了多对多注释这一事实确保 Doctrine 将创建一个表“customer_article”而不在 CustomerArticle.php 中指定它?据我了解您的 DQL 示例,我也可以反之亦然以获取与用户关联的所有文章?这确实是一种不同的方法 - 谢谢
    • 如果且仅当您有与多对多连接相关联的其他属性时,您需要手动指定连接表。否则,您不需要它作为一个实体。如果除了外键之外没有其他字段,您应该删除它并让教义为您处理。你是对的,反向查询$query = $em-&gt;createQuery("SELECT c FROM Customer c JOIN c.article a"); 是获取客户列表所必需的。
    • 我无法让它工作。我扩展了我的第一篇文章也许有助于理解这个问题。
    【解决方案2】:

    你的映射很糟糕。您指定可连接但不指定反向连接列。试试:

     /**
      * @ManyToMany(targetEntity="Article")
      * @JoinTable(name="customer_article",
      *      joinColumns={@JoinColumn(name="Customer_id", referencedColumnName="cusomter_id")},
      *      inverseJoinColumns={@JoinColumn(name="Article_id", referencedColumnName="article_id")}
      *      )
      */
    

    顺便说一句,将主键映射到“id”以外的东西有点不寻常。

    【讨论】:

    • 这很好用,谢谢!目前我不完全理解为什么要使用“inverseJoinColumns”(因为在多对多双向的文档中也缺少它)但它是一个关键字,我可以搜索以获取有关它的更多信息。剩下一个问题:在您的“ManyToMany”表示法中,缺少 inversedBy="customers"。 Doctrine Doku 说“双向关系的拥有方必须通过使用 inversedBy 属性来引用其反面”非常感谢您帮助我。
    • InversedBy 用于 oneToMany 或 ManytoOne。在这些情况下,它存储在数据库中“多”端的字段。 InversedBy 允许您在不喜欢默认值时指定您想要的列名称(类似于 ManytoMany 中的 JoinColumns 和 InverseJoinColumns)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-22
    • 1970-01-01
    • 2013-12-01
    • 2014-09-29
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多