Τρίτη 1 Φεβρουαρίου 2011

Fast and easy dropDownList for Yii

Lately I have been using a fantastic php framework called Yii. It is great for my needs and with a little coding here and there you can build and maintain large projects.

So I had this problem: There are a lot of different forms with lots of fields and some of them need a drop-down list instead of an input-box which is what gii (the yii code generator) gives me. Say, I have a model called Address with fields like: country, city, street, zipcode etc. In the database, the model Address corresponds to the table Address and the fields country and city actually are integer fields which are foreign-keys mapped to the tables Countries and Cities respectively. I would expect the code generator to give me a form which in the field country has a drop-down list where the user can select the country from a list of countries taken from the table Countries. What we get instead is an input-box where we can type integers. So we need to fix this and we need to do it fast and with as little code as possible because there are a lot of files to fix!


First of all we need to calculate what the correct code would be in our above example. We want a drop-down list taking it's values from a table from the database, in our case the tables Countries and Cities. We have to generate the models for each of those tables first. Let's also assume that the table Countries has the fields countryid and countryname. What each of them should contain is quite obvious. Then the code for the field country would be like this:
$avals=Countries::model()->findAll(array('order'=>countryname asc"));
$avals=CHtml::listData($avals,'countryid','countryname');
$avals[""]="";
echo $form->dropDownList($model,'country',$avals);
This is what happens in the above snippet of code:
  • We get the list of the countries from the database.
  • We create the listData array required for the dropDownList function which we will use later.
  • We also add an empty value to the list of countries in case the user doesn't want to pick a country and wants to leave the field empty - null (this is optional)
  • We call the dropDownList and print it. The $form and $model objects are found and defined in the generated code so you do not have to worry about them.
So, all we have to do now is to transform the code above to a nice function which can be defined in our application and used anytime. You can create a globals.php file inside the protected folder and use it to define your functions there. Instructions on how to create and import your own globals.php file can be found here.

The function code is here:
function fastEasyDrop($model,$form,$hclass,$hvar,$valid='countryid',$valname='countryname'){
    $avals=$hclass::model()->findAll(array('order'=>$valname." asc"));
    $avals=CHtml::listData($avals,$valid,$valname);
    $avals[""]="";
    echo $form->dropDownList($model,$hvar,$avals);
}
As you can see, we pass the $model and $form object as arguments along with the model-class name (Countries) and the form variable name (country). The last 2 arguments are optional and are the id field-name and the name field-name of the database table countries. In you follow a strict naming convention in your database you won't ever have to use the last two arguments.

That is how we would call that function from our form code:
fastEasyDrop($model,$form,'Countries','country');
If our field-names are not the default ones defined in the function the calling of fastEasyDrop would then be like:
fastEasyDrop($model,$form,'Countries','country','myIdField','myNameField');

That's all! We now have a simple function that we can call anytime we need a dropDownList populated by a database table!

#I will soon update with instructions on how to create dependent database-dropDownLists with Yii (with no ajax just javascipt).

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου