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. Основна категория parentID ще бъде NULL.   -  person Edhen    schedule 30.11.2013


Отговори (2)


Когато направите Product -> Category -> Child Categories -> Product, тогава получените Product няма да бъдат върнати в същата колона. Така Doctrine ще ги хидратира в същото имение. Което не е добре, ако искате да използвате пагинация на всички продукти.]

Най-добрият ви залог е да използвате собствен 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