Как получить частичный результат от построителя запросов доктрины

У меня есть объект продукта, в котором он имеет массив в качестве атрибутов:

     /**
     * @ORM\OneToMany(targetEntity="Shopious\MainBundle\Entity\ProductPicture", mappedBy="product", cascade={"persist","remove"})
     */
    protected $pictures;

    /** 
    * @Accessor(getter="getCover") 
    */
    private $cover;
    public function getCover()
    {
        if($this->pictures->count() > 0) {
            return $this->pictures[0];
        }
        return new ProductPicture();
    }

Теперь в моем построителе запросов у меня есть следующий код:

 $query = $em->createQueryBuilder()->select('p')
            ->from("SiteMainBundle:Product", 'p')
            ->innerJoin('p.category', 'c')
            ->innerJoin('p.shop', 'shop')
            ;

Проблема здесь в том, что я не хочу выбирать все атрибуты p. Поэтому я хотел получить только первый ProductPicture в массиве изображений (в моем случае это похоже на метод getCover()). Как мне это сделать?

Пока я могу отфильтровать частичные атрибуты, которые мне нужны, выполнив следующие действия:

 $query = $em->createQueryBuilder()->select('p.name, p.id')
                ->from("SiteMainBundle:Product", 'p')
                ->innerJoin('p.category', 'c')
                ->innerJoin('p.shop', 'shop')
                ->innerJoin('p.pictures', 'pictures')
                ;

поэтому в приведенном выше примере я выполнил внутреннее соединение изображений, но как мне получить отсюда первый элемент?

В заключение, мой вопрос: как выбрать/запросить первый ProductPicture в массиве изображений с помощью построителя запросов? Потому что когда я делаю:

$query = $em->createQueryBuilder()->выбрать('p')

он возвращает все атрибуты продукта, но мне не нужны все атрибуты продукта. Мне нужны только некоторые из них, такие как идентификатор, имя и т. д. Однако один из атрибутов продукта на самом деле является сущностью (то есть ProductPicture ), так как мне вернуть это в операторе select?

ИЗМЕНИТЬ:

Вот эквивалент SQL о том, как изображения должны быть объединены внутри:

SELECT * 
FROM  `product` 
JOIN  `product_picture` ON  `product`.id =  `product_picture`.product_id
WHERE  `product`.id =100
LIMIT 1

person adit    schedule 07.06.2013    source источник
comment
Вы имеете в виду, где поставить where или как выполнить запрос?   -  person cheesemacfly    schedule 08.06.2013
comment
Я спрашиваю, есть ли способ преобразовать SQL в построитель запросов? Я немного смущен переводом предела в запрос. Я знаю, что в доктрине есть setMaxResults, но это дает другой результат.   -  person adit    schedule 08.06.2013
comment
Какой разный результат? как другая картинка? или весь ряд отличается?   -  person Mohammad AbuShady    schedule 08.06.2013
comment
Я проголосовал за ваш вопрос, потому что он интересный, но он также неоднозначен, основываясь на вашей попытке построения запросов и предоставленном впоследствии SQL. Если бы вы могли предоставить нам пример того, какие данные вы хотели бы вернуть, как если бы запрос был успешно выполнен, тогда я могу помочь понять, как построить запрос.   -  person Adam Elsodaney    schedule 08.06.2013
comment
@ Adam-E Я снова отредактировал/обновил вопрос   -  person adit    schedule 08.06.2013
comment
@MohammadAbuShady добавил больше деталей в мой вопрос   -  person adit    schedule 08.06.2013


Ответы (2)


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

PS: при условии, что объект ProductPicture имеет свойство URL, которое вы хотите получить

$query = $em->createQueryBuilder()->select('p.id, p.name, pictures.url')
            ->from("SiteMainBundle:Product", 'p')
            ->innerJoin('p.category', 'c')
            ->innerJoin('p.shop', 'shop')
            ->innerJoin('p.pictures', 'pictures')
            ;
person Mohammad AbuShady    schedule 08.06.2013
comment
Итак, проблема с этим запросом в том, что он возвращает один и тот же идентификатор продукта пару раз. Я добавлю больше деталей в исходный вопрос. - person adit; 09.06.2013
comment
сначала вам нужно понять mysql, если у нас есть продукт p с изображениями img1, img2, img3, и вы выполняете запрос, он вернет 3 записи, все 3 записи имеют один и тот же продукт p, но каждая запись имеет другое изображение ( p, img1), (p, img2), (p, img3), вы должны указать, какое именно изображение вы хотите, например, изображение с main=1 или что-то в этом роде - person Mohammad AbuShady; 09.06.2013
comment
Я все это понимаю, я думаю, что решение состоит в том, чтобы сделать group by - person adit; 09.06.2013

Добавьте пользовательский метод репозитория с DQL для вашей сущности, а затем вызовите его из контроллера.

Вы можете назвать метод репозитория как хотите, для этого примера я использую findProductWithPicture

class ProductRepository extends EntityRepository
{
    /**
     * @param integer $id
     */
    public function findProductWithPicture($id)
    {
        $dql = <<<SQL
SELECT
    p.id    id,
    p.name  name,
    q       picture
FROM
    Shopious\MainBundle\Entity\ProductPicture q,
    Shopious\MainBundle\Entity\Product p
WHERE
    p.id        = :picture_id  AND
    q.product   = p.id
SQL;

        $query = $this->_em->createQuery($dql)->setParameter('picture_id', $id);

        return $query->setMaxResults(1)->getResult();
    }
}

Чтобы использовать это с контроллера

$em = $this->getDoctrine()->getManager();
$product = $em->getRepository('ShopiousMainBundle:Product')->findProductWithPicture($id);

return $this->render('ShopiousMainBundle:Product:show.html.twig', array(
    'product' => $product[0]
));

В обработанном шаблоне Twig вы можете получить к ним доступ следующим образом:

<p>{{ product.id }}
<p>{{ product.name }}
<p>{{ product.picture.whatever_property }}
person Adam Elsodaney    schedule 08.06.2013