2013-04-23 5 views
0

Я строю свое первое приложение с каркасом syfmony2. Теперь я немного вставлю о том, как получить данные из моей базы данных.Symfony2/Doctrine Relationship Mapping

Сначала здесь в мои таблицы (только важные поля)

# клиент

customer_id | INT | AI | PK

# статья

article_id | INT | AI | PK

номер | 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} 

Насколько я понимаю, в документации лучшим способом является сделать отношения Mapping в моих файлах PHP сущностей.

Customer.php

article.php

CustomerArticle.php

Но я запутался, что делать и в каком направлении. (http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html)

По моему мнению, это должно быть правильные отношения

клиентов к CustomerArticle является One-To-Many (однонаправленный) Отношения

CustomerArticle Клиенту является Many-To-One (Однонаправленный) Отношения

Статья к CustomerArticle является One-To-Many (однонаправленный) Отношения

CustomerArticle статьи является Many-To-One (UNIDIR ectional) Отношения

Правильно ли в этот момент?

И теперь необходимо сделать это (4) Сопоставление карт в каждом Файл сущности? Или мне нужно только сделать это одним способом, например. Клиенту CustomerArticle (One-To-Many - однонаправленный) и Статья в CustomerArticle (One-To-Many - однонаправленный)

, к сожалению, "One-To-мая, однонаправленный" является единственным, не надлежащего пример на странице справки доктрины.

Они пишут: «С точкой Доктрины зрения, она просто отображаются как однонаправленный многие-ко-многим при этом ограничение уникальности на одной из столбцов усиливает один-ко-многим кардинальности»

Означает ли это, что мне нужно сделать только сопоставление, например, в разделе «однонаправленные многие-ко-многим» на странице?

Извините за много вопросов.

Я много читал в документах, но я не могу ответить на эти вопросы для себя.

Спасибо за любую помощь.

Update 26.04.2013

К сожалению, я не могу заставить его работать даже с помощью Lighthart и чтения документации Doctrine.

Я думаю, что полезно дать вам более подробную информацию о моих таблицах и коде. Может быть, кто-то может дать мне важный ответ, чтобы я окончательно понял концепцию.

Моих таблиц с некоторым Примером запись

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
  • Добавить в ManyToMany отношения к Клиенту (статья) Entity

Это как файлы сущностей выглядеть на этот момент (без методов)

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» -Code, но это не помогло.

Моя цель?

Я импортирую данные из некоторых csv-файлов в таблицы: «клиент», «статья», а также в существующую в настоящее время таблицу «customer_article».

В моем приложении каждый клиент имеет несколько статей, на которые он ссылается. Таким образом, таблица выглядит следующим образом

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

Это не магазин или что-то вроде этого. Это довольно сложно объяснить, поэтому сначала необходимо знать, что каждый клиент имеет неопределенное количество связанных статей.

Теперь я должен быть в состоянии получить все статьи, ассоциированные с одним клиентом, используя t_ customer_id. (Посмотрите мой пример sql в стартовом сообщении выше)

Надеюсь, вы можете мне помочь.

Большое спасибо всем.

ответ

1

Это действительно похоже на двунаправленное много для многих с клиентом и статьей. Сущности, которые вы создадите, это Customer.php и Article.php, и вы указываете много-ко-многим в этих файлах через аннотацию или в doctrine.orm.yml в зависимости от ваших предпочтений.

Doctrine сделает промежуточную таблицу для вас (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 гарантирует, что Doctrine создаст таблицу «customer_article» без указания ее в CustomerArticle.php? Насколько я понимаю ваш DQL-пример, я также могу сделать это наоборот, чтобы получить все статьи, связанные с пользователем? Это действительно другой подход - спасибо – Manuel

+0

Если И ТОЛЬКО ЕСЛИ у вас есть другие свойства, связанные с соединением «многие-ко-многим», вам нужно будет вручную указать таблицу соединений. В противном случае вам это не нужно как сущность. Если кроме внешних ключей нет других полей, вы должны удалить их и позволить доктрине обрабатывать это для вас. И вы правы в обратном запросе '$ query = $ em-> createQuery (" SELECT c FROM Customer c JOIN c.article a ");' необходимо получить список клиентов. – Lighthart

+0

Я не могу заставить его работать. Я распространяю свой первый пост, возможно, это помогает понять проблему. – Manuel

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 = «клиенты».Доктрина Доку говорит: «Собственная сторона двунаправленного отношения должна ссылаться на свою обратную сторону с помощью атрибута inversedBy« Большое вам спасибо за помощь. – Manuel

+0

InversedBy используется для oneToMany или ManytoOne. В этих случаях это поле хранится на стороне «много» в базе данных. InversedBy позволяет указать, что вы хотите, с именем столбца, если вам не нравится значение по умолчанию (похоже на JoinColumns и InverseJoinColumns в ManytoMany) – Lighthart