2013-04-23 92 views
0

我正在用syfmony2框架构建我的第一个应用程序。 现在我坚持一点关于如何从我的数据库中获取数据。Symfony2/Doctrine关系映射

首先这里我表(唯一重要的领域)

#客户

CUSTOMER_ID | INT | AI | PK

#文章

的article_id | INT | AI | PK

number | VARCHAR

#customer_article(这两个领域打造PK)

CUSTOMER_ID | INT | PK

article_id | INT | 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文件。

Customer.php

Article.php

CustomerArticle.php

但我很困惑,做什么和在哪个方向。 (http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html

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

客户到CustomerArticle是一个一对多(单向)关系

CustomerArticle到客户是多到一(单向)关系

文章CustomerArticle是一个一对多(单向)关系

CustomerArticle条是多到一(裁研ectional)Relationship

在这一点上它是正确的吗?

现在是否需要在每个 实体文件中进行此(4)关系映射?或者我只需要做一个方法,例如 客户向CustomerArticle(一到多 - 单向)和 文章CustomerArticle(一到多 - 单向)

不幸的是,“一到五月,单向”是唯一一个没有 正确在学说参考页上的例子。

他们写道: “从主义的角度来看,它是简单地映射为一个单向多到很多,其中连接列上的一个独特的约束强制一对多基数”

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

很抱歉有很多问题。

我阅读了大量的单证,但我不能回答这些问题我自己。

感谢您的任何帮助。

更新2013年4月26日

不幸的是我不能让它甚至与Lighthart的帮助和阅读文档学说工作。

我认为这是有益的给你关于我的表和代码的更多细节。也许有人可以给我必要的答案,所以我最终理解它背后的概念。

我的一些示例表中的条目

Table: customer (PK: customer_id) 
+-------------+--------+----------+-------------------+------+-----------+ 
| customer_id | number | password | email    | salt | is_active | 
+-------------+--------+----------+-------------------+------+-----------+ 
| 1   | CU0001 | 43t9wef | [email protected] | test | 1   | 
| 2   | CU0002 | 32rk329 | [email protected] | 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表
  • 添加一个多对多的关系给客户(和文章)实体

这是实体文件什么样子的此刻(无方法)

Customer.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 
} 

Article.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”代码,但它没有帮助。

我的目标是什么?

我从某些csv文件导入数据到表中: “customer”,“article”以及当前不存在的表“customer_article”中。

在我的应用程序中,每个客户都有一些引用他的文章。 因此该表将看起来像这样

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

这不是一个店铺或类似这样的东西。要解释这一点非常困难,因为只有知道每个客户都有未定义数量的相关文章才是必要的。

现在,我必须能够通过customer_id获得所有与一位顾客相关的物品。 (看看我上面的起始帖子中的示例sql语句)

我希望你能帮助我。

非常感谢大家。

回答

1

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

主义将为您制作中间表(customer_article)并对其进行管理。

你会使用DQL:

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

然后,你会处理文章为实体,并调用article.getCustomer()用于与商品相关的客户名单。

这是一个与SQL根本不同的范例,需要一些习惯。

+0

感谢您的反馈。 我有点困惑这是否意味着我必须删除我的CustomerArticle实体并使用它创建的表? 您写下了 “Doctrine将为您创建中间表(customer_article)并对其进行管理。” 这是否意味着我在 Customer.php和Article.php中创建一个多对多的注释,Article.php确保Doctrine将创建一个 表“customer_article”,而不必在CustomerArticle.php中指定它? 据我了解你的DQL-Example我也可以做它反之亦然 所有与用户相关的文章? 这是真的不同的方法 - 谢谢 – Manuel 2013-04-24 07:24:05

+0

如果,并且只有如果您有其他属性与多对多关联,您将需要手动指定连接表。否则,你不需要它作为一个实体。如果除了外键之外没有其他字段,则应该删除它并让教条为您处理。你正确地使用反向查询'$ query = $ em-> createQuery(“SELECT c FROM Customer c JOIN c.article a”);'是获取客户列表所必需的。 – Lighthart 2013-04-24 13:46:02

+0

我无法得到它的工作。我延长我的第一篇文章,也许有助于理解这个问题。 – Manuel 2013-04-26 15:35:14

0

您的映射不好。您指定了连接表,但不指定反向连接列。尝试:

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

另外,将主键映射到'id'以外的东西有点不寻常。

+0

这效果很好,谢谢!目前我并不完全理解为什么要使用“inverseJoinColumns”(因为它在多对多双向文档中也缺少),但它是我可以搜索以获取更多信息的关键字。还有一个问题:在“ManyToMany”符号中,inversedBy =“customers”缺失。Doku教条说:“双向关系的拥有者必须通过使用inversedBy属性来引用它的反面”非常感谢你帮助我。 – Manuel 2013-04-29 08:04:47

+0

InversedBy用于oneToMany或ManytoOne。在这些情况下,它存储在数据库中“多”一侧的字段。 InversedBy允许你指定你想要的列名称,如果你不喜欢默认的(类似于ManytoMany中的JoinColumns和InverseJoinColumns) – Lighthart 2013-04-29 13:55:48