Sometimes “experience” means all the little stuff that no one ever bothered to write down. Learning code through doing will lead you on a zig-zag path from one problem to the next, that is different per-project. In starting a big website made with Yii, having never touched the framework before, I took notes on some of the issues and questions that arose while developing:

1. If I define additional field in my model (AR) that is not stored in DB, only calculated basing on other fields, where do I keep code that will calculate this additional field value?

You may have some variables that will be reused, that aren’t a single database field. For example, a rating that is determined by querying some rows. Or perhaps some strings that are always combined, such as the page URL or someone’s location.

Using __get and __set methods in your models allows you to create a function that will act like a class property (member variable). If you create a method in your model named getRating, which returns a value, you can then access it via $model->rating.

See the following for more information:

2. What if this field is pulled from the database? How do I put in a SELECT list on my add/edit page?

A common situation would be needing a list of countries displayed in a select list, that are pulled from a database table. This Yii tutorial will explain it more in depth:

Assuming a model named ‘Countries’ (try generating with Gii), the basic code for the view is the following. It makes use of the findAll() method to query all rows in the country database, and CHtml:listData which generates an array of data suitable for list-based HTML elements and the dropDownList function.

echo $form->dropDownList(
    $model,
    'country_id',
    CHtml::listData(Countries::model()->findAll(),'id','name')
);

3. MVC Question: Should I be putting loops and IF statements in my view? I’m getting concerned that this might not be the right place to keep things organized in an MVC sort of way

This is fine, as long as all the loop logic is display-related. Your views are going to contain some conditional logic and loops. But, consider using display widgets for modular areas. For example, I have many not-set/empty checks to display different HTML on the front-end, as well as foreach loops to display an array of a model’s One-to-Many relation. For the general purpose of displaying recent reviews on my site, I have a method in the model that returns the latest reviews, and two display widgets that use it; one for the home page, and one for a basic unordered list.

4. What about utility and conversion functions? Does that belong in the model or controller?

The best recommendations I found are to put these in a separate library. It’s not related to the model (database/fields), the operator logic of the controller (coordinates and takes user input), or the views (display). You can either put your generic functions for your project in /protected/components, or create an extension. I thought this quote was very appropriate:

MVC should be renamed to MVCL .. that is Model-View-Controller-Library. These kind of functions should go into a separate system of libraries.

If you are using a 3rd-party library (an encryption class for example), then you could include the class in your components folder where your application should be automatically loading it. Then, instantiate the class and use as necessary.

5. How to Add a Registration Form to Your Model/Controller

In the user model, you can set different rules for different scenarios. Such as, repeated password. The trick is to use the on=> parameter in your rules, which allows you to set the scenario that it applies to. Here’s an example of a rule used for registration only:

array('passwordVerify', 'required', 'on'=>'register'),

In your controller, the scenario you are using can be used when you instantiate your model

$model = new User('register');

…or set manually afterwards:

$model->scenario = 'register';

You also may want to consider using a separate model for this sort of purpose, to avoid any conflicting rules. See the Gii-generated LoginForm.php for an example of that.

6. Why am I Having Problems with Password Repeat or Other Fields Not in the Model?

Property “User.passwordVerify” is not defined.

In CActiveRecord, if you want to have a property that isn’t connected to a column of the database table, you can do so by declaring it as a public variable.

class User extends CActiveRecord
{
public $password_repeat;

7. Stop Browsers from Auto-completing Registration Form Fields

Firefox was autocompleting the username and password fields on my registration form, and change password forms. To disable this, you can set the FORM attribute autocomplete to off. On your CActiveForm options, you can set this in htmlOptions:

'htmlOptions'=>array('class'=>'reg-form', 'autocomplete'=>'off'),

8. Saving An Array of Checkboxes connected to a Related Model

This one is a little tricky. I wish Yii had a built-in way of handling the saving of an array of checkboxes with values from a related model. I was able to put together some code using the examples from these two pages:

9. How do I Integrate OpenID or sign-in with Google/Facebook etc:

A lot of sites now are allowing account registration and login using their existing Google/Facebook/Twitter accounts. Integrating this sort of login is going to totally change your user registration system, and I was interested in how it is designed. There are the external APIs to handle. Then there are all the account management sections and UI/account issues such as users accidentally registering again, linking existing accounts to multiple Google/Facebook/etc accounts, etc. I found this post which has some of the best explanations:

Yii has the LOID (LightOpenID) extension available for this sort of OpenID login, or if you need a full login system, there is yiiauth which includes this functionality. For now I’ve decided to stick to a regular-old signup with email verification on the project I am working on, because I need to focus on other parts of the site first. I plan to add it in sometime after launch, and will write another post about the specifics.

10. How do I Create SEO-Friendly URLs

See my separate post on SEO-Friendly URLs using the Yii Framework.

Comments on this Article

  1. Rohit Dev says:

    Plz, tell me how to configure yii with eclipse using PHP and where to keep Model file, View file and Controller file…

    Alo, tell me about setting class path…

    Regards,
    Rohit Dev

  2. yiqing says:

    great collections !

  3. Kremon says:

    This is indeed a great collection! Thank you for doing it!
    Could you also let us know how to fill up a dropdownlist from DB? I’ve seen examples all over the internet but nothing seems to work.

Comments are closed.