Question

I have done a bit off searching around for an answer, but most results are either not clear enough or I find it hard to implement in my current pattern... What I wish to achieve is having a query to select all products from the products table matching a category ID from the category table, But now i wish to also get products that are sub categories of the said parent category. I am using Doctrine 2 with codeigniter and my function so far looks like this

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();
        }
    }   
}

I also don't think it would be practical to get all products then do it from application level as I'm using pagination and products could become quite large.

Was it helpful?

Solution 2

To answer my own question, I decided to take the easy way out, and considering i would only have around 40 categories max, i don't think this should be much of a problem.

In my categories model class i created 2 static methods,

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;
}

So pretty much this will get the parent and iterate all the children and assign each 1 to the flat array.

Then from my searchProducts method i just added a bit more under the $category check.

        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);
            }               
        }

May not be best or practical, but it works and does what I need for the time being.

OTHER TIPS

When you do Product -> Category -> Child Categories -> Product then the resulting Products will not be returned in the same column. Thus Doctrine will hydrate them in the same manor. Which is no good if you want to use pagination on all the products.]

Your best bet is to use a native SQL with result set mapping. Then your query should use a UNION, so that the main Product lines up in the same columns as the child Products

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top