I am using Yii to help me get more accustomed to a well-organized MVC setup. It is going well so far, using the example code for a base, and searching around the Wiki and forum. I had a few questions:
I have a user model, that is has country_id field, linking it to a row in the countries table. I want to store the variable ‘country’ which uses the name column from that row. Is it better/faster to use a getter like I am below, or to add another relational rule? If I add a relational rule with a SELECT option to only query a single column, would it be stored in $usermodel->country, or as an array key?
public function getCountry()
{
$country = Countries::model()->findByPk($this->country_id);
if ($country) { return $country['name']; }
}
Does code like this belong in the view? Loops over a HAS_MANY, display conditionals, etc. Should it be separated out to widgets or a custom component library? It feels like it maybe shouldn’t be there.
// A
foreach( $model->reviews as $rev ){
// list each review. lots custom html layout with data goes here
// blah blah
}
// B
if ($model->reviewCount > 1){
echo $model->reviewCount, ' Reviews';
} elseif ($model->reviewCount == 1) {
echo $model->reviewCount, ' Review';
} else {
echo 'N/A';
}
More of a speed/behind-the-scenes question; if my model includes a HAS_MANY relational rule, when is this queried? I’m concerned that there could be too much data tagging along when I use the model for overall index listings, etc.
I think this is a matter of style. I hope others chime in because I am interested to see what experienced devs say on this great question. My gut says that your method is faster because it returns less data. When you run an AR query you get back AR-stuff in addition to your data. Whether or not it actually matters is hard to say - you still have to hit the database anyway. I can say at this point in my personal project I am focusing on functionality and will optimize for speed later on slow AR queries.
If you use a relation to pull the data (whether you select a single column or the whole model instance) it will return as $object->attribute.
Example A that you cite is typical ‘view’ code - simple loops. I have this all over the place in my views. I am not sure how you could refactor or rearrange that code any further.
However, I think for example B you could package this into a reusable component/widget. You make it reusable by passing in a model and attribute and asking it to return a value in single/plural form. If you need it in this view you probably will need it elsewhere in your app.
It is used when you run a relational query. You are correct in that a lot of AR data comes with the query result. You can mitigate that by caching the database schema (see Guide) and optimizing slow queries. As a general rule I would say do not prematurely optimize. AR is a trade-off between development ease and performance and I would not worry about every AR query. Do some testing to see which queries are too slow and optimize those by using DAO or even raw SQL if thats your thing.
I use the Yii toolbar extension which among other things does profiling so it is easy to see where a query is taking too long.
#1- Perhaps this gets down to personal choice. I’m leaving it as is for now and am not worrying about it. It’s just one of those ‘I am doing this right?’ questions while coding. I’ll see if anyone else has a response.
#2- Okay, this makes sense.
#3- I’ll check out this Yii toolbar that you speak of. I’m not worrying about this sort of optimization for now. There is too much other functionality to get working. This particular query won’t be an issue until some serious growth after launch.