Doctrine with MySQL. Могу ли я выбрать все продукты в родительской и подкатегориях?

Я немного поискал ответ, но большинство результатов либо недостаточно ясны, либо мне трудно реализовать их в моем текущем шаблоне... Чего я хочу добиться, так это иметь запрос на выбор всех продуктов из продуктов. таблица, соответствующая идентификатору категории из таблицы категорий. Но теперь я хочу также получить продукты, которые являются подкатегориями указанной родительской категории. Я использую Doctrine 2 с codeigniter, и пока моя функция выглядит так:

function searchForProducts( $offset, $limit ) {
    $search = $this->input->get('search');
    $category = (int)$this->input->get('category');
    $supplier = (int)$this->input->get('supplier');

    for( $i = 0; $i < 2; $i++ ) {
        $select = ($i == 0) ? 'count(p)' : 'p';
        $qb = $this->em->createQueryBuilder();
        $qb ->select($select)
            ->from(self::ENTITY, 'p');

        if( $i != 0) {
            $qb ->setFirstResult( (int)$offset )
                ->setMaxResults( (int)$limit );
        }

        if( $search ) {
            $qb ->where( "p.title LIKE :search" )
                ->orWhere( "p.sku LIKE :search" )
                ->setParameter('search', "%$search%");
        }

        if( $category ) {
            $qb ->andWhere( "p.category = ?1" )
                ->setParameter(1, $category);
        }

        if( $supplier ) {
            $qb ->andWhere( "p.supplier = ?2" )
                ->setParameter(2, $supplier);
        }

        if( $i == 0 ) {
            $this->totalRows =  $qb->getQuery()->getSingleScalarResult();
        } else {
            return $qb->getQuery()->getResult();
        }
    }   
}

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


person Edhen    schedule 26.11.2013    source источник
comment
как выглядит ваша схема?   -  person Flip    schedule 30.11.2013
comment
таблица продуктов имеет id|title|categoryID|supplierID... и т. д., а таблица категорий имеет id|parentID|title. Родительский идентификатор корневой категории будет NULL.   -  person Edhen    schedule 30.11.2013


Ответы (2)


Когда вы делаете Product -> Category -> Child Categories -> Product, результирующие Product не будут возвращены в том же столбце. Таким образом, Доктрина будет гидратировать их в одном и том же поместье. Что нехорошо, если вы хотите использовать нумерацию страниц для всех продуктов.]

Лучше всего использовать собственный SQL с отображением набора результатов. Тогда ваш запрос должен использовать UNION, чтобы основные Product располагались в тех же столбцах, что и дочерние Products.

person Flip    schedule 30.11.2013
comment
Ох, я боялся, что это может быть так, я попробую позже, а потом дам вам знать, как все прошло. Я мог бы просто создать отдельный метод только для этого. - person Edhen; 30.11.2013

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

В моем классе моделей категорий я создал 2 статических метода,

static function getCategoryWithChildren( $id = NULL ) {
    $obj = new self;
    $parent = $obj->getCategory( $id );
    $list = array();
    self::iterateCategoriesChildren($parent, $list);
    return array_reverse($list);    
}

static function iterateCategoriesChildren( $category, &$array ) {
    if( $category->hasChildren() ) {
        foreach( $category->getChildren() as $child ) {
            self::iterateCategoriesChildren($child, $array);                
        }
    }
    $array[] = $category;
}

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

Затем из моего метода searchProducts я просто добавил немного больше под проверкой $category.

        if( $category ) {
            if( $this->settings->get('product_child_categories') ) {
                $categories = Categories_model::getCategoryWithChildren($category);
                foreach($categories as $_category) {
                    $qb ->orWhere( "p.category = " . $_category->getID() );
                }                   
            } else {                
                $qb ->andWhere( "p.category = ?1" )
                    ->setParameter(1, $category);
            }               
        }

Может быть, не лучший или практичный, но он работает и делает то, что мне нужно на данный момент.

person Edhen    schedule 01.12.2013