newbie CDbCriteria Best Practices

Hi all

I’m using CDbCriteria for some queries and have some questions regarding where the code should go… when I put it in the controller I can get it to work, but some tutorials I have looked at seem to put it in the model - not always clear - and the docs show how to create the queries, but not necessarily how to access them from a view.

As I said, I got it to work, but as I am new to MVC I would prefer to learn it right. As was mentioned in the "Documentation for Zii" thread of last week, it would be really great to have more examples, not only of commands, but also of the best context to use them and how they fit into / are accessed by MVC.

Thanks for everyone’s help, these forums are great.

On the long run it pays off to follow the "thin controller/fat model" principle. That means try to keep the code in controller actions as easy and small as possible. Controllers should only inspect the request and based on that use model(s) to get the data required for views and then push that data into a view.

So if you have to build a complex criteria, maybe better put the complete query into another model method. My models are full of custom methods like e.g. s queryUserReport($userID,$from,$to). And actually this is where logic like this belongs. That way it’s very easy to adopt e.g. DB changes into your model. All you have to touch in this case is 1 model file and some view files that use the provided model data.

Thanks! This was my guess from the beginning, but I was not clear at all on the syntax to access a function in the model method directly from the view - that is why I was looking for example code that would explain not only how and where to create the query, but also how to access it from the view - and if that requires controller code, an example of that too. I have been looking through the docs but haven’t found anything that goes into that, and a significant portion of the forum links that might help seem to be dead…

Views should never query/update any models directly. That’s the responsibility of the controller (except maybe for simple pseudo static data, e.g. dropdown options that rarely change). So: Yes, you’ll need a controller anyway. Think of it as the “glue” between your model and view.

OK. I was pretty much familiar with the thin controller concept. what I am still unfamiliar with - and which doesn’t seem to be covered in an easily find-able way in the docs - is the syntax. There are lots of docs on the individual commands, but without knowing that “x” command in the view triggers “y” method in the controller which accesses “z” function (in this case a function based on CDbCriteria) in the model.

Which brings me back to one of my original questions - are there any examples anyone can point to or recommend?

Not sure what you mean. Views don’t contain commands, but links or form actions pointing to a controller action (a.k.a. “route”). It’s described very detailled in the Fundamentals chapter in the guide. For routes, check the controller page:

http://www.yiiframework.com/doc/guide/basics.controller

So whenever you click something in the view that triggers a request, a controller action is called.

sorry to be so dense…

lets say i have a link that calls a page. blahblah.com/myapp/menu

tbl_menu is the name of a table. I have already generated a model and crud for that table and set up mysql in config/main.php

the generated menu.php (model), menuController.php (controller) and index.php (view) exist, but aren’t exactly what I want. In particular, the actionIndex() function in the controller is using CActiveDataProvider which I assume communicates with AR in the model and then to index.php in the view to output the generic list.

Since I want a subset of the tbl_menu table, I want to use a query with several criteria. I can remove the CActiveDataProvider stuff ( including the render() ) from actionIndex(), and replace it with :

$criteriaA=new CDbCriteria;


$criteriaA->select='category, item, description, price'; 


$criteriaA->condition='active="y" and category = "Appetizers"';





    $this->render('index', array(


       'menusA' => Menu::model()->findAll($criteriaA),


    ));

then i can put the data in the view with a foreach in index.php

I would rather have the CDbCriteria stuff as a function in the model that I can use with parameters for the condition, but I don’t know the syntax for;

(A.) the code for what I would return from the function (possibly return array()->findAll($criteriaA); ???)

(B.) the way to call that function from the controller and feed the data to the view ???

When I look at the link to the docs re: controllers, there is a lot of info, but it seems very abstract, and nothing about specific syntax for communicating with the model.

Once again, sorry! I have mostly used OOP libraries to access databases directly from pages and am still trying to get my head around MVC in general and Yii in particular…

The CRUD code should be taken as a base for your own requirements. It might be perfect for some situations but in most cases you’ll change it - or even start from scratch as you need a completely different logic.

(A.) Your suggestion is absolutely fine. You could implement it like this


public function findByCategory($category='YourDefaultCat')

{

    // findAll also accepts an Array with properties for CDbCriteria

    return $this->findAll(array(

      'select'=>'category, item, description, price',

      'condition'=>"active='y' and category =:category",

      'params'=>array(':category'=>$category),

    ));

}

(B.) your custom method behaves like a "built in" AR method. So usage is a simple as:


  $categories=Menu::model()->findByCategory($yourRequestedCategory)

Thanks much!!