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.
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.