Image Image Image Image Image

© Copyright 2012 ABCoder | Email | RSS

Scroll to Top

To Top

CakePHP

06

Jan
2010

8 Comments

In CakePHP

By abcoder

HAVING clause in CakePHP find query

On 06, Jan 2010 | 8 Comments | In CakePHP | By abcoder

Recently I’m in love with Cake. Yes it’s true cake is too much addictive. ;) As a novice it’s not that comfortable to start with cakephp framework, cos most of the stuffs from the cake book hardly work perfectly, it’s good they update their code too frequently, but not the cake book. I’ll write several posts on cakephp issues for beginners with solutions in the coming days. Still a lot of ingredients of the cake are mysterious to me, but there is no doubt, I won’t hesitate to give them two thumbs up with 5 star rating :)

Right now I’m working on a price-comparison project using cakephp. This is the first time I’m using cake. I know you’d say why didn’t I try a smaller project first, actually I like to take risk (once my astrologist friend Imon told me this).

Whatever, lets get back to the “title” of this post. One of my queries needed HAVING clause, but did not find any way to use HAVING clause with cakephp find() function. I searched a lot on google, didn’t find anything, even very few people asked for it on popular groups/forums like google/nabble! The SQL query I wanted to run is:

SELECT `Product`.`id` , `Product`.`title` , `Product`.`image_link` , MIN( `ProductsOfMerchant`.`price` ) AS lowest_price, AVG( `ProductReview`.`rating` ) AS average_rating, COUNT( DISTINCT (
`ProductReview`.`id`
) ) AS total_reviews
FROM `products` AS `Product`
LEFT JOIN `products_of_merchants` AS `ProductsOfMerchant` ON ( `ProductsOfMerchant`.`is_active` =1
AND `ProductsOfMerchant`.`product_id` = `Product`.`id` )
LEFT JOIN `product_reviews` AS `ProductReview` ON ( `ProductReview`.`is_approved` =1
AND `ProductReview`.`product_id` = `Product`.`id` )
WHERE `Product`.`is_active` =1
GROUP BY `Product`.`id`
HAVING total_reviews & gt ; =2
ORDER BY `average_rating` DESC
LIMIT 4 

I added the “HAVING” in ‘group’ key of the find() function’s parameters. This is the cakephp code I used and it worked great!

$highRatedProducts = $this->find('all', array(
	'fields' => array('Product.id', 'Product.title', 'Product.image_link', 'MIN(ProductsOfMerchant.price) AS lowest_price', 'AVG(ProductReview.rating) AS average_rating', 'COUNT(DISTINCT(ProductReview.id)) AS total_reviews'),
	'conditions' => array('Product.is_active' => 1),
	'order' => 'average_rating DESC',
	'group' => 'Product.id HAVING total_reviews >= 2',
	'limit' => 4)
);

Please share in comments if you know any better(proper) “Cake way” to accomplish this.

Tags | , , , , , , , ,

Comments

  1. Neat idea. Found your page after googling for this exact problem and it works like a charm.

    Kinda feels like an SQL injection attack on your own code, no?

  2. haha, liked your comment :)
    umm.. as long it works fine some sql injection is not bad to make it work in “cake way” :-P

  3. It’s a slight hack, but not too much so because it produces perfect SQL using $this->Model->find. It’s when you start using $this->Model->query that it starts to get hacky!

  4. that’s why I tried so hard to find out the way to do it using find() function. Using query() with cake is the last option. And yes, you are right SQL injection is a big concern too to avoid query() function.

    I checked your site http://www.heybaloo.com. What is it about? can you pls send me an invitation :)

    Thanks

  5. Heybaloo is a site for sharing local news. Users submit news stories about where they live and we tag them with locations, so you can view a news feed for your area (right down to a city suburb or small village). It’s kinda like a hyperlocal Digg or Reddit.

    If you go to http://www.heybaloo.com/account/request and register your name and email, I’ll get an invite sent right out to you.

  6. I have a few days I have this blog bookmarked as a favorite site. A little funny, because even kilak weeks ago on this forum I said before, but no blog you will not find among my esteemed pages. Testifying to the extraordinary discussion that blogs are always niewartosciowym Internet junk, on which there is no reliable knowledge, or objectivity. I’m not talking now about a specific address here, but all – is talking about blogs in the form of handbooks, diaries, and information services – there is always a lot of unreliable knowledge and unverified information, which translates into my long-standing aversion to these sites. However, its unwillingness to revise its humility, a few days ago I searched the Internet resources in the search for specific knowledge. A little of the case visited a few blogs, because even though the subject matter often appears in the network, but this subject rather superficially presented. Kidy came across this blog, I was more than surprised. It turned out that the issue presented here is very extensive. There is no doubt that in terms of content is the best service of its kind in the Polish network. Not only that – even scientific, popular, and service breaks are not able to match this portal. So far not succeeded, and even contact the author of all the major publications. But I hope it succeeds – it will write to my email and did not disappoint me, as a faithful reader of the future and will continually grow your blog. Because these sites are thin on the ground in the Polish Internet. Why did I write all this? All through my character, I do not like making mistakes, but if … is to admit them. Such is the case here. Of course, one swallow does not make (they say), but on the basis of this blog I’m willing to admit that this kind of sites on the Internet can be very valuable, kind and above all interesting.

  7. Appreciating the time and effort you put into your website and in depth information you provide. It’s awesome to come across a blog every once in a while that isn’t the same outdated rehashed material. Great read! I’ve saved your site and I’m including your RSS feeds to my Google account.

  8. Jonathan

    Great idea.
    You can do the same thing by adding a final condition:

    $conditions = array(
    ‘Product.is_active’ => 1,
    ’1 HAVING total_reviews >= 2′
    );

Submit a Comment