2011-01-29 2 views
2

Хорошо, у меня есть объект пользователя следующимDoctrine2 ArrayCollection

<?php 
class User 
{ 
    /** 
    * @var integer 
    * @Id 
    * @Column(type="integer") 
    * @GeneratedValue 
    */ 
    protected $id; 
    /** 
    * @var \Application\Entity\Url[] 
    * @OneToMany(targetEntity="Url", mappedBy="user", cascade={"persist", "remove"}) 
    */ 
    protected $urls; 
    public function __construct() 
    { 
     $this->urls = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 
    public function addUrl($url) 
    { 
     // This is where I have a problem 
    } 
} 

Теперь, что я хочу сделать, это проверить, если пользователь уже имеет $url в $urlsArrayCollection перед тем сохраняющиеся в $url.

Теперь некоторые из примеров, которые я нашел говорит, что мы должны сделать что-то вроде

if (!$this->getUrls()->contains($url)) { 
    // add url 
} 

, но это не работает, так как это сравнивает значения элементов. Поскольку значение $url не имеет значения id, это всегда будет терпеть неудачу, и $url будет дублироваться.

Так что я бы очень признателен, если кто-то может объяснить, как я могу добавить элемент к ArrayCollection без сохраняющиеся это и избежать дублирования?

Редактировать

мне удалось для того чтобы достигнуть этого с помощью

$p = function ($key, $element) use ($url) 
{ 
    if ($element->getUrlHash() == $url->getUrlHash()) { 
     return true; 
    } else { 
     return false; 
    } 
}; 

Но не это по-прежнему загружать все URLs, а затем выполняет проверку? Я не думаю, что это эффективно, поскольку на пользователя может быть тысячи URL-адресов.

ответ

2

Это еще не возможно в режиме "domain driven", т.е. просто используя объекты. Вы должны выполнить запрос для проверки существования:

SELECT COUNT (u.id) FROM пользователя ˙U ГДЕ 1 В u.urls И u.id = 2

С доктриной 2.1 это будет возможно? используя комбинацию двух новых функций:

  1. Extra Ленивые коллекции
  2. @IndexBy для коллекций, так что вы определили бы @OneToMany (targetEntity = "URL", indexBy = "расположение")
  3. Поддержка
  4. ExtraLazy Collection для индекса с помощью -> contains().

Очки 1 и 2 уже реализованы в мастерстве Doctrine 2, но 3 все еще отсутствуют.

+0

Итак, как вы думаете, это хорошая идея создать 'UrlService' с' addUrl ($ url, $ user) 'метод, где будет использоваться DQL, до тех пор, пока не исчезнет доктрина 2.1?Я предполагаю, что использование DQL в сущности невозможно/хорошая идея. – Optimus

+0

или, может быть, 'UrlService :: checkIfExists ($ url, $ user)' и запустить DQL в этом методе? – Optimus

1

Вы должны попытаться использовать метод exists для сбора и вручную сравнить значения.

+0

Привет, Cobby, спасибо за ответ. Не могли бы вы дать мне простой пример кода? Я не очень хорошо разбираюсь в закрытии. – Optimus

+0

Мне удалось получить это через '$ p = function ($ key, $ element) use ($ url) { if ($ element-> getUrlHash() == $ url-> getUrlHash()) { return true; } else { return false; } }; ' Но разве это все еще загружает все URL-адреса, а затем выполняет проверки? Я не думаю, что это эффективно, поскольку на пользователя может быть тысячи URL-адресов. – Optimus