Difference between #97 and #96 of Yii for beginners

unchanged
Title
Yii for beginners
unchanged
Category
Tutorials
unchanged
Tags
yii, tutorial, fresher, newbie, MVC
changed
Content
Intro (Part 1)
------------------

Hi. This is **first** article with my Yii tutorial. I had to split it into more
articles as there's limited length of texts on Wiki. So once you understand
basics, you can read next article here: [**Yii for beginners
2**](http://www.yiiframework.com/wiki/462/yii-for-beginners-2 "Yii for
beginners 2").

This tutorial is copy of PDF in my forum:
[Total fresher in PHP frameworks and Yii, I don't understand
tutorials](http://www.yiiframework.com/forum/index.php?/topic/6129-total-fresher-in-php-frameworks-and-yii-i-dont-understand-tutorials
"Total fresher in PHP frameworks and Yii, I don't understand
tutorials")

I'm writing this tutorial because when I was beginning with Yii I was totally
lost. I didn't understand anything. I didn't know why I needed the demo project,
where I should place my PHP scripts, what it means MVC, what should the folder
structure look like etc. No tutorial for beginners was available. 

This tutorial is meant for beginners who have never worked with any PHP
framework or with Yii. Who are able to create website with standard PHP, MySQL
etc., but are completely lost while beginning with Yii.

1. Prerequisities
----------------
I suppose the reader is familiar with PHP and databases (DB). He should be able
to write SQL query, use DB in PHP and create at least a simple web using PHP,
HTML, CSS and DB.
If you don’t know anything about PHP and DB, I recommend that you stop reading
and have a look at it. 
And what’s also important is OOP (Object oriented programming). This means
classes, overriding functions, using constructor, public and private methods and
properties, etc… Can be practiced in PHP, Java, C#, VB.NET …

2. MVC - Architecture description
---------------------------------
MVC (Model-View-Controller) is a type of application architecture. It’s used
in Yii framework. When your application uses MVC architecture, it is divided
into 3 basic parts.

**M** = Model = Part that defines relations among data in DB and rules that must
be followed when saving data to DB. It also gives us tools to read/save data
from/to DB.

**V** = View = Part that is used just to show data to user. It doesn’t write
to DB or count difficult things. It just receives data and shows them using
HTML, CSS, JS …

**C** = Controller = Part that processes and changes the data, handles user’s
actions, decides, counts, thinks and calls models and views … It simply acts.
<center>
![MVC Schema](http://racky.wz.cz/yii_manual/imgs/mvc_schema.png "MVC
Schema") 

Image 1) MVC schema
</center>


Notice the arrow directions in picture above. Controller can read/write data
from/to database only via Model. Controller also evaluates user inputs, combines
it with data, counts new values … and sends outputs and results to the View
and DB. View formats given data and shows them. (For example draws table etc.)

As we can see, the Controller is the central point. It’s the boss. Whatever
you do - Controller processes it and decides what to do next. Asks for
appropriate data from DB and does what you wanted to do. We can see that Model
and View don’t do anything, unless they are asked to. In some cases, Model and
View do not have to be used.

So let’s focus on Controller now.

### 2.1. Controller

Controller is initiated (and it's code is run) whenever you enter any address in
browser. In its code you can read data from POST, GET or SESSION variables, work
with DB etc. When you use MVC architecture (in Yii framework), addresses have
special format. They include parameter that specifies which controller will be
used. (which part of web you want to enter)

Yes, you can have more controllers. Each controller can be used to work in
different part of your web. One controller can work with user accounts, another
one with products you sell etc. And what does the web address look like when you
use MVC? 
~~~
[php]
www.myweb.com/index.php?r=myController
~~~
Parameter “r” says that you want to use Controller named “myController”.
And here we can see another speciality of MVC (or Yii). Addresses contain only
index.php. No other files. All the navigation is done by the “r” parameter
and controllers.

### 2.1.1. Action

Controller can have one or more sub-controllers. Each does something else. If
our controller works with users than his one sub-controller can delete users,
another one can add users, third one changes (edits) them … These
sub-controllers are called Actions. You can (have to) specify action using the
“r” parameter. As we saw above, controller was specified like this:
“?r=myController”. If our controller had action called “myAction”, and
if we wanted to run it, we would write this address:
~~~
[php]
www.myweb.com/index.php?r=myController/myAction
~~~
We can rewrite this address for example like this:
~~~
[php]
www.myweb.com/index.php?r=users/edit
~~~
If you do not specify action and run only controller like this
“?r=myController” than the default action will be run. The default action
has to be specified in the controller using function actionIndex().

### 2.2. Model

Model is very simple thing in Yii. You don’t have to write a single line of
its code, it can be created automatically using command line. Each table in DB
has its own model. This model has the same (or similar) name like the table.
Each model has 2 important functions. Find data and Save data. That’s all we
usually need. When you need to read data from DB to controller you just write
something like:
~~~ 
[php] 
ModelName.FindAll() 
~~~ 
and that’s it. No SQL queries, no fetching array (as you would have to do in
PHP). That’s the advantage of Yii and its object-oriented access to DB. When
you want to write to table, the command looks cca like this: 
~~~
[php]
ModelName.column = value; 
…  
ModelName.Save()
~~~
That’s it again.

Another thing that the Model provides is relations. These relations enable you
to “tunnel” through one table to another. Important are Foreign Keys.
Relation is something like SQL Join. When every employee has in its table the ID
of his department, you can easily get info about this department by writing
something like this: 
~~~
[php]
$employee->department->departmentName
~~~
Where **$employee** is 1 particular employee selected by some criteria, the word
**department** is name of the relation (leading from model of employees to model
of departments) and **departmentName** is column in table of departments.

### 2.3. View

As I wrote above, view has no intelligence. It just receives data from
Controller and shows them. This is the only place where we use HTML, CSS,
JavaScript etc. We of course can use FORs, WHILEs, Ifs, models … But the only
aim is to show data to user.

Correction: Described View is an ideal view. In praxis it’s sometimes easier
for beginners not to send data from Controller to it, but to read data from DB
in View (using model) and show then. 

3. What is it framework and why to use it
---------------------------------------------

In a shortcut. Framework is a set of functions that can ease your work.
Functions are usually grouped into Classes. One example for all. In Yii
framework there is available class named CHtml. It’s obvious, that it provides
functions for creating HTML code. (Tables, lists, forms...). You don’t have to
use HTML and solve its validity. You just call function
~~~
[php]
echo CHtml::beginForm();
~~~
and it creates this html code: 
~~~
[php]
<form method=”post” action=”thisScriptName”>
~~~

And why to use frameworks? It makes your work easier. You don’t have to code
every single detail, framework does something for you automatically. Yii for
example integrates form-validation functions, it handles user logging and much
more. You just have to discover its possibilities and learn to work with them.
But it’s the hardest thing. (Sometimes it’s faster to create your own
function than to try to understand a prepared solution) And that’s why I write
this manual. To show some possibilities in one place and in praxis so you
won’t have to google the basics.

4. Yii framework
----------------

Yii framework has its [web](http://www.yiiframework.com/ "Yii web")
and [documentation](http://www.yiiframework.com/doc/ "").
All you need to do (if you want to use it) is to download and extract it to your
localhost-folder. You of course need a PHP and MySQL server (I use
[WAMP](http://www.wampserver.com/en/ "WAMP server"). If you want to
try it, turn off Skype for the moment when Wamp is starting. Otherwise it
won’t start.)

### 4.1. The demo project and folder structure

Now you have Yii “installed” (= you copied all files to localhost-folder).
And what next? It may look useless now. The best way to become a friend with Yii
is to try the Demo project, go through it and look what it’s code looks like.
Every manual describes it, but doesn’t explain why you should use the Demo
project. I didn’t understand why everybody was pushing me into some boring
demo project, while I wanted to do a real one.

The demo project is good because you will see the folder structure, which is
important. When you walk through the code and files, you will understand how you
can send data from Controller to View or how forms are validated. You will see
how works navigation using the “r” parameter etc. So give it a time and play
with it for a while. In the future you can create demo projects, automatically
generate Models from you DB and change both to meet your requirements. It's
quick. Advantage is, that in demo project are created folders, HTML head etc. 

These:
[Hello World](http://code.google.com/p/yii/issues/detail?id=86 ""),
[First
project](http://www.yiiframework.com/news/14/screencast-how-to-create-a-blog-system-using-yii-in-less-than-30-minutes
"")
and
[Blog](http://www.yiiframework.com/files/yii-blog-1.1.0.pdf "") could
help you. Manuals describe basic work with Yii like creating demo project,
relations among tables etc …

In demo project (as same as in any other Yii project) is important folder
"protected". It contains 3 subfolders: **models**, **controllers**,
**views**. There are stored PHP scripts that power your web. 

**Models**

- You will find there only 2 models that are not connected to DB. Demo project
does not work with DB at all. These models are more like a definition of logics
for HTML forms. When a HTML form is confirmed on webpage, it's content is
checked (_validated_) using rules specified in these models. The validation is
done for example in actionContact(). (see bellow)
- The validation rules are specified in rules() method.
- Items of form are defined as properties of model class.
- Captions for form items are in method attributeLabels().
- There is almost no difference between models that are/aren't connected to DB.
They look 99% the same.
- If your model should work with database, it would not extend class CFormModel,
but CActiveRecord and it would contain method tableName().

**Controllers**

Actually, you will see only 1 controller - SiteController.php. Open it in any
text editor and have a look at methods:

- actionIndex() - it only renders view "index"
- actionContact() - creates a new instance of model ContactForm, assignes it
data from POST and tests them (all of this is described in next chapters)
Finally it renders view "contact" and sends it a variable $model as a
parameter.
- actionLogout() - you can see how to call system variables and methods of Yii
and how you can redirect to a different URL.
- These are the only important things for you in the controller.

**Views**

You will see 2 subfolders:

- layouts: contains mainly file main.php with definition of the whole website
layout, menu items, logo etc.
- site: contains views used in SiteController. Take a look at login.php file.
This view is called from actionContact() and it receives $model as a parameter.
You will see that you can start using this variable without any other
definition. Just write $model.

Last important file is "protected/config/main.php". There is
definition of DB connection, of your application name etc. You can add lines to
this file in order to enable more functions of Yii.


**Important for Windows:**

To use command line commands mentioned in manuals (you need them to create the
demo project and to use the best things Yii offers = mainly models and relations
between them), you will have to modify the “environmental variables”. Right
click “This computer” choose “Properties”, than “Advanced” tab and
click on button “Environmental Variables”. 

A new window with 2 list-boxes will appear. In the lower one find row with
variable named “Path”. Add to its value something like this: (yii framework
folder path and php path)
~~~
[php]
C:\Program Files\wamp\www\yii\framework ; C:\Program
Files\wamp\bin\php\php5.3.0 
~~~

Instead of command line you can use GII webpage in your demo project. I write
about it bellow, but I do not use it.

5. Using Yii in praxis
----------------------
(How to run your first YII project)

Here will be examples of commonly used functions, useful tricks etc. These
things are hard to be figured out just so.

### 5.1. Create demo project and set it up

If you are a rookie, first of all, you should create the demo project, set
[connection](http://blog.dmcinsights.com/2009/11/03/configuring-yii/
"") to your DB and understand how it works. When you already are a
friend with Yii, you could be able to create folder structure just by yourself.

### 5.2. Create Database for your project

Very important thing is database. You should design it first. Before writing any
code. When this is done, you can generate models, views and controllers
automatically (using command line or GII webpage). I generate only models
because I want to make it my way.

See this. It’s 4th part of a [Yii
tutorial](http://blog.dmcinsights.com/2009/11/05/creating-models-views-and-controllers-in-yii
"").

In this tutorial is said, how you should name tables and columns to be able to
generate relations among tables automatically. But names are not so important.
More useful is to declare relations in DB when designing it. If you use
PhpMyAdmin, just create a table with foreign keys (FKs) and go to the
“Structure” tab and under the list of columns you will find link to
relations creation. When you click it a new screen appears and you can set
foreign keys (FKs) relations. Or use software mentioned bellow to design whole
DB (I recommend).
When SQL relations are defined, Yii will recognize them and will automatically
create relations among Models. Otherwise you would have to declare these
relations manually. Which is not impossible, but more comfortable is to have it
in DB definition.

### 5.2.1. DB design tool

Very interesting thing is that relations will be created automatically when you
define foreign keys using SQL relations. I recommend for example software [MySQL
Workbench](http://dev.mysql.com/downloads/workbench/5.2.html "") which
is freeware. It allows you to design your DB including SQL relations using
graphical tool (ER diagram). You can also enter default data to your tables.
It’s very comfortable mainly when you need to delete DB and create it again,
or when it has to be redesigned. You see everything on one screen.

<center>
![MySQL Workbench screenshot](http://racky.wz.cz/yii_manual/imgs/workbench.gif
"MySQL Workbench screenshot")


Image 2) MySQL Workbench in action - ER creation
</center>


To create relation between 2 tables, create first the tables. Then you will need
only 1 button from the toolbar that’s on the left side of the screen. It’s
the one on the bottom. Its caption is “Place relation using existing
columns”. No other relations will be needed. Click this button and you will be
asked to select FK column in any table. Select it and then click appropriate PK
column in another table and you’re done with this relation.

<center>
![MySQL Workbench
toolbar](http://racky.wz.cz/yii_manual/imgs/mysqlWorkbenchRelationButton.bmp
"MySQL Workbench Toolbar")
![MySQL Workbench "Pick relation"
msgbox](http://racky.wz.cz/yii_manual/imgs/mysqlWorkbenchRelationButton2.bmp
"MySQL Workbench "Pick relation" msgbox")
</center>

When you’re done with DB design, you just have to press Ctrl+G and DB will be
exported to your MySQL server.

I recommend that you go to menu Tools / Options and set “History size” to ca
10-30 steps. Default value is 0, which means unlimited number of undo steps. But
it slows down the application very very much.

In versions released in year 2011 I noticed their instability under Win XP SP3.
So be patient it crashes very often. But luckily, work is not lost.

<center>
![MySQL Workbench screenshot](http://racky.wz.cz/yii_manual/imgs/workbench1.jpg
"MySQL Workbench screenshot")
</center>

### 5.2.2. Run Yiic shell or Gii

**Yiic shell - console**

When your DB is ready, set the DB connection in file
yourProject/protected/config/main.php.  Than go to your web-project folder using
Command line and write command: yiic shell. It will enable the Yii console and
you will be able to create model for 1 table like this: model tableName, or for
all tables at once like this: model *

You can use command: “crud TableName” to generate administration for our
tables. Than you can, of course, change generated forms and web pages to fit
your requirements.

**Gii**

Models, controllers etc. can also be generated using Gii website (without
commandline) if it is allowed. I haven't used it but you can. Gii is webpage
that comes with Yii framework. In protected/config/main.php you have to
uncomment it and enter password for Gii. Than go to you localhost website and
run controller gii like this:
~~~
[php]
localhost/myproject/index.php?r=gii
~~~
I think this is all you have to do.


### 5.2.3. Define relations in models manually

Now, when you created models for all tables, it may be necessary to define
relations (if they were not generated automatically or when you need more of
them). This can be done using function relations() in model file. See the
[video](http://www.youtube.com/watch?v=BvJjCsidunM "Yii Framework - Blog
Tutorial (by Pelle ten Cate) "), time 12:15 or
[manual](http://www.yiiframework.com/doc/guide/database.arr ""). 

And what is the relation? As I wrote above, it’s an SQL Join. If you specify
Primary key (PK), foreign key (FK) and SQL relations between them, than Yii can
then “tunnel” from Employee to his job description using Jobs FK in the
Employees table.

When you make relation from list of employees to their jobs and name this
relation ‘job’, you can then write this in Controller to get employee’s
job: 
~~~
[php]
$Employee = Employees::model()->findByPk($employeeId);
$myJobName = $Employee->job->jobName;

/*
Where:
Employees = model of table created using yiic shell. 
jobName = column in Jobs table. 
job = relation name.
$Employee = 1 returned record from table Employees - only one because we were
searching by PK. If we searched using findAll() it would return list of records
and it would be necessary to walk through them using foreach.

In your model should be cca this function:
*/

public function relations()
{
  return array(
	           'job' => array(self::BELONGS_TO, 'JobsTableName', 'id_job'),
           );
}
/*
But I’m not sure about the BELONGS_TO. See links and explanations. And as I am
never sure, I recommend to specify relations in DB a generate them using command
line or Gii.
*/
~~~

## 5.3. How to create your first controller

You just need one file in folder: protected/controllers. The file must be named
like this: “NameController.php”. First letter of the Name is upper case as
same as the first letter of Controller. It’s necessary for Linux servers.
Example. You want to create controller named “My first”. The filename will
be “MyfirstController.php”. 
And what’s inside?
~~~
[php]
<?php
class MyfirstController extends Controller
{
  public function actionIndex()
  {
    // here is your code for this action
  }

  public function actionMyaction()
  {
    // here is your code for this action
    $this->render(‘myview’);
  }

  public function getEmployeeName()
  { 

  }

}
?>
~~~
As you can see, controller is a Class and contains definitions of action and
non-action functions. Default and important action is actionIndex(); It’s used
when you don’t specify any action in “r” parameter (as mentioned above).
You can add any action you want. For example “My action”. The “r”
parameter of “actionMyaction” would look like this: 
~~~
[php]
“?r=Myfirst/Myaction”.
~~~

What does mean this row?
~~~
[php]
$this->render(‘myview’);
~~~

It tells the action to run a view. View is the part of your application, where
you use HTML, CSS formatting etc. and it’s used to show anything to user. (You
can also try function renderPartial() – can be usefull)

Yii will look for this view in folder Views/Myfirst. Where “Myfirst” is name
of controller. Yes, every controller has its own set (folder) of views.

In Yii the view is actually a part of Controller. You can call it in any action
and when you write "$this" in view, you are refering to current
Controller, its methods and properties. So if there is something that will be
common for all views, you can add it to file
"protected/components/Controller.php" because all controllers are
based on this class.

### 5.3.1. Controller - Notes from praxis

#### 5.3.1.1. SESSION

In controller (or View), you may want to use a Session so you can send data
among scripts without using forms, POST or GET. (Session is a PHP term, use
Google to understand) If you want to use session in Yii, you just write this: 
~~~
[php]
Yii::app()->session[“varName”] = $value; 
~~~
That’s it. Session variable will be automatically registered, session will be
started, etc.

#### 5.3.1.2. USING RELATIONS

If you use relations among models, you can access one table from another one
using command like this: 
~~~
[php]
$employees = $department->get_employees; //(get_employees = relation name)
~~~
You can also specify which employees you want to get - by DB column name:
~~~
[php]
$employees =
$department->get_employees(array('condition'=>'born<1950'))
~~~
Or you can join tables and order it by any column:
~~~
[php]
$subMenuItems =
MainMenu::model()->with('relation1.relation2')->findAll(array('condition'=>'id>21
and relation2.tableColumnName = 3', 'order'=>'relation1.tableColumnName'));
~~~

Explanation:  Model named MainMenu has relation named “relation1” which is
pointing to another model (to another table in DB). The target model has
relation named “relation2” referring to a third table. Using following
command we join 3 tables:
~~~
[php]
MainMenu::model()->with('relation1.relation2') 
~~~

#### 5.3.1.3. SETTING HTML PAGE TITLE 

Every action in every controller does something different. So it’s good to set
page title in every action. You can do this by this command: 
~~~
[php]
$this->pageTitle = ‘My page title’
~~~
If you want to use your project name in this title or anywhere else, you can use
this system variable:
~~~
[php]
Yii::app()->name
~~~
It’s value is set in file: protected/config/main.php

### 5.4. View

View is a very simple thing so I will just show some "tricks". Html
code can be generated semi-automatically using static class CHtml.

### 5.4.1. Grouped drop down list

![Grouped drop down
list](http://racky.wz.cz/yii_manual/imgs/grouped_dropdownlist.png "Grouped
drop down list")

In view you can create drop-down-list using standard HTML:
~~~
[php]
<select name="selectName" id="selectName">
<option value="1">item1</option>
<option value="2">item2</option>
…
</select> 
~~~
Or you can use class CHtml:
~~~
[php]
echo CHtml::dropDownList($name, $select, $data, $htmlOptions);
~~~

- $name = name that will be used in $_POST when form is send
- $select = string with selected value
- $data = content - interesting think, see bellow
- $htmlOptions = classical array of attributes: 
~~~
[php]
$htmlOptions  = array('width'=>'100','style'='color:red;')
~~~

**$data** is basically a simple array with “name=>value” pairs. This
Array can be created automatically using function:
~~~
[php]
$data = CHtml::listData( Model::model()->findAll(),'id_item','item_descr' )
~~~
Method listData() just generates following array:
~~~
[php]
array(‘value1’=>’caption1’, ‘value2’=>’caption2’ … )
~~~

~~~
[php]
CHtml::listData(array $models, string $valueField, string $textField, string
$groupField='')
~~~
- $models = list of items. It’s clear, you use for example:
MyModel::model()->findAll(array(‘condition’=>’id>4’))
- $valueField = what column will be used to fill the value of <option> tag
- $textField = what column will be used to fill the caption of <option>
tag
- groupField = what column will be used for grouping items in drop down list

If you put these things together a drop down list will be drawn. And if you want
to group items in it by specified column, it is very easy. Let’s say you have
a table of countries and table of continents. Each country belongs to 1
continent = you have relation 1:N from continent to countries and back. In your
drop down list you want to see all the countries. But not mixed together. You
want them to be grouped by continents like on the picture above.

To do this, you have to join both tables and than specify the grouping column.
~~~
[php]
// first we create the join and in $record you have complete table of countries
and their continents.
$records = Country::model()->with('getContinent')->findAll(); 
$data =
CHtml::listData($records,'id_country','country_name','getContinent.continent_name');
echo CHtml::dropDownList('myDropDown','',$data); 
~~~
Note that to specify the "group column" you have to use the relation
name to tell YII which column from the joined tables you want. In joined tables
are used aliases. 
~~~
[php]
getContinent.continent_name
~~~
If you were refering to the "home model" table, you would write only
"t.columnName" - in our case to get data from Country table.


### 5.4.2. Creating links

Here I Will just recommend to use function CHtml::link() to create hypertext
links. Otherwise you can experience some problems with www links. To create URLs
always use the method like this:
~~~
[php]
echo CHtml::link("text",array('controller/action'));
// or
echo CHtml::link("text",$this->createUrl('controller/action'));

// and whenever you want to create URL leading to a page on your site, use:
$this->createUrl('controller/action');
~~~

Because URLs can have more formats in Yii and if you change the format (in
protected/config/main.php) and use this method, links will be automatically
changed too. If you enter them manually, they will stop working.

If you do not specify controller, the current controller will be automatically
used.

#### 5.4.3. Sending variables to view

When you want to send something from Controller to a View, you just add 1
parameter to $this->render() method. Like this:
~~~
[php]
$this->render(‘myview’, array(‘variableName’=>$value));
~~~
In the View you can start using variable $variableName.

### 5.4.4. Send Form using hyperlink + confirm
~~~
[php]
<a onclick="javascript: if(confirm('Really delete?')){
self.document.forms.**formName**.submit()}"
onmouseover="style.cursor='Pointer' "  >
Delete
</a>
~~~

This will show ordinary hyperlink **Delete**. When it’s clicked, a JavaScript
confirm-box appears. When you click YES, it does what is written in
“onclick” section. In this case, a form named **“formName”** is send to
the server. When you put mouse on the Delete caption, your cursor will be
changed to classical “hand”.

Don’t forget to use escape characters when writing javascript using php echo.
JS requires apostrophes instead of quotes. You can't write this:
~~~
[php]
<?php echo ‘ ’word-in-apostrophes’ ‘;?>
~~~
Apostrophe can be written like this:  
~~~
[php]
<php echo ‘ \' word-in-apostrophes\' ‘; ?>
~~~


### 5.4.5. AJAX - operations on background

On background means doing something without reloading the page. It’s used
(e.g.) for checking password difficulty (web page changes the difficulty status
as you write longer and longer word into the password textbox). Or Google uses
it to whisper you while entering searched phrase.

You can use Ajax via jQuery, which is very very good JavaScript framework. I
strongly recommend it to everyone.

Second possibility is to use Yii's integrated Ajax. (It also uses jQuery, but
you do not have to know JavaScript)

I will show 3 examples I understand now. The first one changes content of a
dropDownList based on what you enter into textbox, the second one changes
dropDownList based on what you enter into another dropDownList and the 3rd one
changes textbox based on what you enter to another textbox.

PS: Sometimes Yii's Ajax does not work in combination with your own JavaScript.
Than I use jQuery instead.


#### 5.4.5.1. Textbox → Dropdownlist

Below you can see an example of code in your View. There is a textField which is
waiting for you to enter a text. Second item is a dropDownList. It’s empty
now. It will be filled when you enter a text into the textField and click
somewhere else. Important is the action mentioned in the URL section. This
action must be in current controller. It’s the controller you used to draw
this view.

View:
~~~
[php]
echo CHtml::form();
     // CHtml::textField($name, $value, $htmlOptions)
echo CHtml::textField('myTextField','',
array(
'ajax' =>
array(
'type'=>'POST', //request type
'url'=>CController::createUrl('myActionName'), //action to call
'update'=>'#updatedDropDownList', // which HTML element to update
)
));

     // CHtml::dropDownList($name, $select, $data, $htmlOptions)
echo CHtml::dropDownList('updatedDropDownList','',array(), array());

echo CHtml::endForm();
~~~

What’s also important is the word **update**. It says that referred
dropDownList will be **extended**. In our case we will add some option values
(rows).
And here is the code of the underlying action:
~~~
[php]
public function actionMyActionName()
{
// CHtml::tag($tagName, $htmlOptions, $content, $closeTag)
echo CHtml::tag('option',
array('value'=>'1'),         // html params of tag
CHtml::encode('hello'), // caption, string may be enough. CHtml::encode() may
not be necessary.
true                                   // close tag
); 
}
~~~
As you can see, this function only prints some text. In our case it’s the new
option for dropDownList. Because we told Yii tu update the dropDownList, this
printed option will be added to it. Action can of course be more complex. You
can access DB via MyModel::model() and check something.. It’s up to you. The
only rule is that you have to echo something. You can echo more records
(options) for example using “for” cycle.

How to work in the action with data you entered in the first field will be shown
bellow. 

#### 5.4.5.2. Dropdownlist → Dropdownlist

Typical example of using this is a situation, when you need to select country in
first dropDownList and in the second one you want to see appropriate cities.
Both the view and action part are much the same as before.
~~~
[php]
**echo CHtml::form();**
     // CHtml::dropDownList($name, $selected, $values, $htmlOptions)
echo CHtml::dropDownList('country','',array(1=>'has value I',2=>'has value
II'),
array(
'ajax' =>
array(
'type'=>'POST', //request type
'url'=>CController::createUrl('myActionName'), //action to call
'update'=>'#updatedDropDownList', // which HTML element to update
)
));

     // CHtml::dropDownList($name, $select, $data, $htmlOptions)
echo CHtml::dropDownList('updatedDropDownList','',array(), array());

**echo CHtml::endForm();**

~~~

Tha main difference here is that drop down boxes have to be in a **FORM** !!
Otherwise their vales won't be accessible via POST in action !!

Below is appropriate action.

~~~
[php]

public function actionMyActionName()
{
$countryID = $_POST[‘country’]; // IMPORTANT .. this is how you access
previously entered data
$listOfCities = getCitiesOfState($countryID);
foreach ($listOfCities as $city)
{
echo CHtml::tag('option',         // tagname
array('value'=>$cityID),         // html params of tag
$cityName, // value from the item selected in the first dropdown is in the POST
array
true                                           // close tag
);
} 
}
~~~

#### 5.4.5.3. Textbox → Textbox

If we do not want to add values (as shown in case of dropdowns), but replace the
whole form item,  we will change only 1 word in the view. This is in the case
that we want to show some text in a textbox according to what we enter into the
first textbox. We then need to replace the whole textbox with a new one
containing the text we need.
~~~
[php]

echo CHtml::form();
echo CHtml::textField('myTextField','',
array(
'ajax' =>
array(
'type'=>'POST', //request type
'url'=>CController::createUrl('myActionName'), //action to call
'replace'=>'#statusTextBox’, // which HTML element to update
)
));

echo CHtml::textField(‘statusTextBox’,'',array());

echo CHtml::endForm();

~~~
In this case is important the **replace ** option. It sais that the original
textField named statusTextBox will be replaced with a new one with different
properties (text).
~~~
[php]
public function actionMyActionName()
{
$status = '';
if (strlen($_POST[‘myTextField’])<5)
{
$status = 'too small';
}
else
{
$status = 'size is OK';
}
echo CHtml::textField('statusTextBox', $status,array());
}
~~~
Notice that the name of the new textbox created in Action must be the same as
the name of the deleted textbox. Otherwise this action will be done only once.

If something doesn’t work repeatedly (only once per page refresh), try to
generate the HTML FORM ITEM (textbox, dropdownlist ... ) in Action in a
different way.

Read more at: [here](http://www.yiiframework.com/doc/api/CHtml#ajax-detail
"") and [here](http://www.yiiframework.com/doc/cookbook/24/
"").


## 5.5. Models and using them

### 5.5.1. Basic overview od model's code

As I mentioned earlier, model is something that enables you to work with
database. More exactly it is a class that extends class CActiveRecord from Yii
core. Each model is declared as follows and contains a few default methods –
if it was generated automatically.
~~~
[php]
class MyModel extends CActiveRecord
{
}
~~~
Class is saved in file: protected\models\MyModel.php
If you want to read data from DB, you use model for example like this:
~~~
[php]
$dataFromDb = MyModel::model()->findAll(); 
// this returns all rows from table that is controlled using model MyModel.
~~~
And what means the double-colon :: and arrow ->? Double-colon means that our
class MyModel contains static method model(). If you access static methods and
static properties, you use :: and if you access methods of instance or property
of instance, you do it via arrow ->
Example:
~~~
[php]
$myVariable = new MyClass()
$myVariable::myStaticMethod();
$myVariable->myMethodOfInstance();
~~~
The static function model() is in the model class and looks like this. (Word
“parent” refers to CActiveRecord class - your Model is derived from it) You
do not need to understand it, just use it.
~~~
[php]
public static function model($className=__CLASS__)
{
	return parent::model($className);
}
~~~
Another function of your model must be tableName(). It only returns table name
that is managed via this model:
~~~
[php]
public function tableName()
{
	return 'nameOfDbTable';
}
~~~
Third method is [function
rules()](http://www.yiiframework.com/doc/guide/1.1/en/form.model "").
It is very important function in case that you want to check data entered into a
HTML form (for example when editing goods details, filling contact forms etc.) 
If user enters something wrong he will be warned and no data will be saved or
processed. For example if user should enter his email and forgets @ sign,
nothing happens if you specify rules well. Rules are automatically created if
you generate model class using command line. Yii takes these rules from DB
definition. That is why you should create DB before programming. 
To be more specific – rules just say which attribute should be validated using
specified validator. If you have a look bellow, you will see that for example
attribute (or column in DB) “user_email” has to be in form of “email”.
Attribute “age” has to be integer = without decimal numbers. So now you know
2 validators: email and numerical. But there are [more of
them](http://www.yiiframework.com/doc/guide/1.1/en/form.model ""). 
~~~
[php]
public function rules()
{
	return array(
		array('users_email', 'email'),
		array('age', 'numerical', 'integerOnly'=>true),
		…
	);
}
~~~
You can of course create your own validator and use it in a rule. If you want to
add rule with name “myrule” than in your model-class create function
“myrule()” and to rules enter this:
array('my_tested_column', 'myrule'),
In demo project you can find this in praxis in file
protected/models/LoginForm.php.
 Next function is relations(). It defines connections to other tables. It is
created automatically  if you specify PK-FK relations. That’s why I recommend
MySQL Workbench for designing DB. See other chapter.
Each relation begins with its name than you have to specify “cardinality”
(relation 1:1, 1:N, M:N), target model, target PK. See text about
[relations](http://www.yiiframework.com/doc/guide/database.arr "")
~~~
[php]
public function relations()
{
     return array(
            'getUsersPosts'=>array(self::HAS_MANY, 'Posts',' author_id '),
    );
}
~~~
And finally last default function attributeLabels() defines labels
(descriptions) for table columns.
~~~
[php]
public function attributeLabels()
{
	return array(
		'id_user => 'Users ID',
		'user_name' => 'Name of user',
	);
}
~~~
If you change this function so that it doesn’t return just array but also
takes into consideration desired language, it can be used to translate captions
in forms based on this model. Example:
~~~
[php]
public function attributeLabels()
{
  If (Yii::app()->session[“lang”] == 1)
  {
	return array(
		'id_user => 'Users ID',
		'user_name' => 'Name of user',
	);
  } 
…

}
~~~
And the best thing is that if you use console (yiic.bat) to generate models than
this class will be created automatically for each of your tables.
The whole MyModel class will look cca like this:
~~~
[php]
class MyModel extends CActiveRecord
{
	public static function model($className=__CLASS__)
	{
		return parent::model($className);
	}
	
	public function tableName()
	{
		return 'nameOfDbTable';
	}
	
	public function rules()
	{
		return array(
			array('users_email', 'email'),
			array('age', 'numerical', 'integerOnly'=>true),
		);
	}
	
	public function relations()
	{
	     return array(
	            'getUsersPosts'=>array(self::HAS_MANY, 'Posts',' author_id '),
	    );
	}
	
	public function attributeLabels()
	{
		return array(
			'id_user => 'Users ID',
			'user_name' => 'Name of user',
		);
	}

}
~~~
.. And you can add (override) much more usable functions like scopes(),
defaultScope(), afterSave(), beforeValidate()
 
### 5.5.2. Another usefull methods

#### 5.5.2.1. Scope()

Scopes are very helpful. If I simplify it they allow you to save an SQL command
and use it as a function in connection with particular model. Example:
~~~
[php]
$dataFromDb = MyModel::model()->getOnlySomeRows()->findAll(); 
// this returns all rows from table that is controlled by model MyModel and that
comply with criteria specified by scope getOnlySomeRows.
~~~
GetOnlySomeRows() is the scope.
[Scope](http://www.yiiframework.com/doc/guide/1.1/en/database.ar "")
is defined like this:
~~~
[php]
public function scopes()
    {
        return array(
            'getOnlySomeRows'=>array( 'condition'=>'status=1' ),
            'getOtherRows'=>array( 'condition'=>'status=2' ),
        );
    }
~~~
And now my experience from praxis: Let’s imagine that you have 2 tables. Table
Suppliers and table Users. Each supplier or user can be signed as enabled or
disabled. We want to show all enabled suppliers and their enabled users.
First we will add scopes to Suppliers and Users models like this. In both models
the scope will look the same if there is column “status”. Let’s say that
user or supplier is enabled when status is 1.
~~~
[php]
public function scopes()
    {
        return array(
          'getEnabled'=>array( 'condition'=>'status=1' ),
          'getSupplier'=>array(self::BELONGS_TO, 'Supplier','id_supplier'),
// this will be in Users model
          'getUsers=>array(self::HAS_MANY, 'Users’,'id_user'), // this will
be in Suppliers model
        );
    }
~~~
Now we can write this:
~~~
[php]
$enabledUsers = Users::model()->getEnabled();
$enabledSuppliers = Suppliers::model()->getEnabled();
~~~
But if we wanted to get all enabled suppliers and their enabled users, we would
have to use inner join with conditions. In Yii this can be done by command
with() like this:
~~~
[php]
$ourJoin =
Suppliers::model()->getEnabled()->with(array('getUsers:getEnabled'=>array('joinType'=>'INNER
JOIN')))->findAll();
~~~
I was showing this just because of the colon. If you want to specify
relation:scope you use colon. It took me long hours to find this out so I am
mentioning it here. And also notice how to force the inner join.

#### 5.5.2.2. Default scope

This is the very the same function as scopes(). But in default scope you can
define only one scope - without name (not array of scopes). This scope will be
used in every query you will make. It is useful for example if you want to add
some calculated attribute to your model or if you want users to see only visible
goods etc.
~~~
[php]
public function defaultScope() 
{
 return array(
      'select'=>array('*','CONCAT(user_firstname,user_surname) as
user_complete_name'),
  );
}
~~~
This default scope adds to each query-result counted column
“user_complete_name”. You than only have to add this column to your model as
a property:
public $ user_complete_name';
You could of course use also a JOIN in the default scope like this: (probably
useless example, just to show that it is possible and how to use it)
~~~
[php]
public function defaultScope()
{
   return array(
  'with'=>array('getSupplier'),  // relation defined in User model
  'select'=>array('*',
'CONCAT(getSupplier.supplier_username_prefix,user_username) as                  
                             user_username_with_prefix'
                             ),
            );
}
~~~
In scopes you can use everything from [CDbCriteria]
(http://www.yiiframework.com/doc/api/1.1/CDbCriteria ""). I guess that
you could also use scopes in the related tables like this:
'getSupplier:scopeName.supplier_username_prefix'
But I am just guessing. And of course everything mentioned here, for default
scope, can be used for ordinary scopes too.

#### 5.5.2.3.  Other things

1) If you write a part of sql query manually (in “where” parts for example)
you will probably want to tell Yii which column belongs to which table. Example
of a “where” part:
~~~
[php]
$something = User::model()->findAll(array(‘where’=>’t.id = 4 and
relationName.column = ‘\Paul‘\’))
// t = the home table of current model (User model)
// relationName = name of relation in your home model
~~~
The important thing to remember is the “t” that refers to the “home
table”.

2) You can use following command to get current name of table. Usable inside a
model class – for example in scopes to specify THIS table.
$this->_alias
~~~
[php]
// can be used in a scope like this:
'getEnabled'=>array('condition'=>$this->_alias.'.id_status=1'),
~~~

3) If you want to see sql query, write something wrong into it. Yii will write
the query on the screen:
~~~
[php]
$something = User::model()->findAll(array(‘where’=>’t.id = a4 and
relationName.column = ‘\Paul‘\’))
~~~

4) If you use an alias for a column and want to filter records by a condition,
do not use “where”, but “having” clause.

## 5.6. jQuery + Ajax + Fancybox
In chapter 5.4 I wrote about Ajax calls that are integrated into Yii. Now I want
to show you how to make them by your self just by jQuery, because it's more
flexible. And have you heard of Fancybox? It's a cool thing I wanna show you
too.

Note:
As far as I know Yii offers only a few simple ajax methods in CHtml class that
doesn't have to work in Fancybox (ajax, ajaxLink, ajaxButton, ajaxSubmitButton -
I haven't mentioned these yet, but I will add them to chapter 5.4) plus
possibility of defining ajaxOptionsArray in htmlOptionsArray (see chapter 5.4)

### 5.6.1. jQuery + Ajax
If you don't know what it is jQuery, first have a look at jquery.com. It is a
JavaScript framework, that makes work with DOM, HTML events or Ajax easier and
allows you to create some effects or to make GUI more user friendly.
One kind of it's functions are Ajax functions: get(), getJSON(), post(), load()
and Ajax(). 
They are very the same. Ajax() method is the core method that is used by the
other methods and you can use it directly. But I don't. I use only get() or
post(). I like POST better than GET as it seems to me to be more secure. Data
isn't part of URL so it can't be abused so easily. For example
"detele.php?id=5" can be dangerous if stored in browser's history or
ajax logs.

Now let's imagine that you have an icon that should be clickable. If user clicks
it, it connects to server, receives string "Hello World" and alert's
it.

First, you have to create an action that will print the text. It has to be an
action as it is called externally just like if you enter it's URL to browser.
~~~
[php]
public function actionGetHelloWorldByAjax()
{
  echo "Hello World";
  Yii::app()->end(); // this ends Yii application in case of Ajax requests.
  return;
}
~~~
That's all. If you are replying to an Ajax call, you just echo something.
JavaScript (jQuery) can parse it and can work with it further. In this case,
there is nothing to parse, it's just a simple text. 

So the server part is done. Now the client side - JavaScript (jQuery in our
case) and HTML.

To include jQuery type to header this: (I recommend to download current version
and use it locally)    
~~~
[php]
<script type="text/javascript"
src="http://code.jquery.com/jquery-latest.min.js"></script>
 
<script type="text/javascript">
$(document).ready(function(){
  $("img.myAjaxImgButton").click(function()
  {
    // If we click an image that has class "myAjaxImgButton", this
code will be run
     $.get('url2action', function(data){
      // This will be executed when ajax call finishes
      alert(data);
    }); 

    // Code written here can be executed "before" the ajax call!
    // Why? Ajax = Asynchronous JavaScript and XML = method $.get() is called,
browser doesn't wait for it to finish and processes next rows of code. If it
takes 10minutes to process the $.get(), nobody waits for it. It's just running
ond the background and when it finishes, internal function(data) is called. 
   });
});
  
</script>

<img class="myAjaxImgButton" src="imp.png" />
~~~

### 5.6.2. Fancybox + displaying HTML received by Ajax
Now, I hope, you can receive and show to user a string received via Ajax. Cool,
isn't it :)
But what if you need to show for example a HTML table? Alert() won't make it.
But Fancybox will!

Fancybox is something like alert() but milion times better. It can show
information in modal window. Modal = it is above web site and the rest is not
available while modal "window" is visible. It is again a JavaScript
library, just like jQuery. Check it out at fancybox.com.

To include Fancybox, go to their website, download it and put cca this in your
header: 
~~~
[php]
  <link rel="stylesheet"
href="/fancybox/source/jquery.fancybox.css" type="text/css"
media="screen" />
  <script type="text/javascript"
src="/fancybox/source/jquery.fancybox.pack.js"></script>
~~~  
And now evertyhing will be the same as in the previous example. Except for one
row in JS code. Instead of alert(data) we will call the Fancybox like this:
~~~
[php]
  $.get('url2action', function(data){
      $.fancybox({content:data});
    });
~~~
Note that data received from the Action are saved in variable with name
"data". But you can use any name you want of course. For example:
~~~
[php]
  $.get('url2action', function(html){
      $.fancybox({content:html});
    });
~~~    
If data contains HTML code, it will be displayed as HTML web page in the modal
window. If the data is a Form, it can contain another Ajax button that will send
the form to controller where it will be validated and OK, or list of errors will
be returned.

Note to Fancybox: When we initialized it, we used: {content:html}.
"Content" is just one of public properties that are available in
Fancybox. See it's documentation.

### 5.6.3. Sending variables to action via Ajax
As you can see in documentation for jQuery and it's ajax methods, you do not
need a form to send data via Ajax to Controller. You can add data to $.get()
method like this:
~~~
[php]

 $.get('url2action', { name: "John", time: "2pm" }, 
function(html){
      $.fancybox({content:html});
    });
~~~   
   In Action, your data will be available via $_GET variable. And if we are
using GET method (not POST), our action can have the same input parameters that
are used in $.get() and these will be automatically assigned. Example:
~~~
[php]
   public function actionGetHelloWorldByAjax($name,$time)
  {
    echo $name; // is the same as echo $_GET["name"] in case that GET
parameters had the same names as parameters of our action
    Yii::app()->end(); // this ends Yii application in case of Ajax requests.
    return;
  }
~~~

If you want to send the whole form to a controller via Ajax, you have to
serialize it. (See method [serialize](http://api.jquery.com/serialize/
"jQuery.serialize()") on jQuery web). But it can't be done by Yii's
CHtml::ajaxSubmitButton() if this form is in Fancybox (I don't know exactly why)
so I will show you how to do it.

Again, it's easy:
~~~
[php]
$(document).ready(function(){
  // As ajaxSubmitButton can by used anything that has class
"myAjaxSubmitButton" and is inside any form.
  // Important!
  // There are more ways how to define the click-event
  // 1) $(".myAjaxSubmitButton").click(function(){});
  // 2) $(document.body).on('click', '.myAjaxSubmitButton', function() {});
  // 3) $(".myAjaxSubmitButton").on("click",
function(event){});
  // 4) $('.myAjaxSubmitButton').live('click', function(){});
  // Number 2-4 should work always. Method 1 will work only for objects that
were on our page from the beginning and weren't dynamically added or changed by
Ajax or aren't displayed in Fancybox. So if you define a button that will send
FORM from Fancybox to controller because of validation, use option 2 or 4. See
section 5.6.7.

  $(".myAjaxSubmitButton").click(function(){});
  {
     var serializedForm = $(this).closest('form').serialize();
     // And you can add any variable you want like this:
     // var serializedForm = $(this).closest('form').serialize() +
'&ajax=1&x=2';
     // Serialized will be all form elements with not-empty name-attribute
     $.get('url2action', serializedForm, function(data){
      alert(data);
    }); 

   });
});
~~~
In the target action all variables will be available via $_GET array without any
unserialization. If we used $.post() method, they would be in $_POST array. Just
try it :)



### 5.6.4. Debuging ajax
As Ajax calls run on background, you can't see any logs or messsages in case of
error. To see them, you have to add something like Firebug to your browser and
than even these "hidden" processes will be debugable so you will see
all errors that occure.

### 5.6.5. Rendering a view as a responce to Ajax Call
If you want to render a view and send it back, you have to use renderPartial(),
not render() method. Example:
~~~
[php]
 public function actionGetHelloWorldByAjax($name,$time)
  {
    $myHtml = $this->renderPartial('view',$parameterArray,true); //true = do
not send to browser, but save the output to a variable 
    echo $myHtml;
    Yii::app()->end(); // this ends Yii application in case of Ajax requests.
                                 
    return;
  }
~~~


### 5.6.6.  Changing an item on screen via Ajax and it's updating
Let's say you have a list of users (HTML table with columns: username, name,
surname) where on each row there is an "edit icon". If you click it,
you are presented with it's edit-form in Fancybox. If you click "save"
button, user is saved and Fancybox disappeares. But what if surname was changed?
The overall HTML table won't be correct anymore, because it will contain old
surname of the user. But how to update the HTML table?

The easies way is to create a view that renders each row of your table separetly
based on ID of particular user. This view returns:
~~~
[php]
<tr> .. </tr>
~~~
... including the edit button. Simply complete row.
Once you save the update-form via ajax and close the Fancybox, HTML code of
currently updated row can be also returned and used to replace the original row
in list of users.

JS code would look like this:
~~~
[php]
 $.get('editUser', { userId: 1 },  function(html){  // html variable contains
code of updated <tr>
      $.fancybox.close();                       // closes Fancybox
      $.(this).closest('tr').replaceWith(html); // replaces current <tr>
.. </tr> with new HTML code                    
    });
~~~
And action:
~~~
[php]
 public function actionGetHelloWorldByAjax($userId)
  {
    $myHtml = $this->renderPartial('userRow',array('id'=>$userId),true); 
    echo $myHtml;
    Yii::app()->end(); // this ends Yii application in case of Ajax requests.
                                 
    return;
  }
~~~
You can also generate the JS code in action and just evaluate it in browser. You
will need JSON object:
~~~
[php]

 $.getJSON('editUser', { userId: 1 },  function(result){  // result variable
contains JSON object
      eval(result.js) // runs JS code, see action code below                    
                                                           
    });
~~~
And action:
~~~
[php]
 public function actionGetHelloWorldByAjax($userId)
  {
    echo JSON::encode(array(
              'newRow'=>
$this->renderPartial('userRow',array('id'=>$userId),true),
              'js'=>'$.fancybox.close();
$.(this).closest('tr').replaceWith(result.newRow);',  // this is the
"js" used in javascript above.
      );
      // array(variable=>$value) will be encoded into JSON object and than it
can be used in jQUery as "set of variables".
    Yii::app()->end();                                  
    return;
  }
~~~

### 5.6.7 Important for events
If items are dynamically added/changed (for example our row updated by Ajax),
they do not respond to previously defined events because they didn't exist when
$(document).ready(function(){}) was called. They have to be registered again or
I recommend to use following kind of event definition. It will work always.
~~~
[php]
$(document.body).on('change', 'img.myAjaxImgButton', function() {
    alert("Dynamically added img button was clicked!");
});

  // Other possibilities are:

  $(".myAjaxSubmitButton").on("click", function(event){});
  $('.myAjaxSubmitButton').live('click', function(){});

~~~
### 5.6.8 Post method in Ajax

POST is used in the same way:
~~~
[php]
$.post("editUser",{ userId: 1 },function(html){
  alert("POST done: " + html); 
});  
~~~
If you wanted to receive JSON object, you would have to specify it in $.post()
method with 4th parameter:
~~~
[php]
$.post("editUser",{ userId: 1 },function(html){
  alert("POST done: " + html); 
}, 'json' );
~~~
But remember. If you use CSRF validation of POST requests, also ajax post
requests have to contain CSRF string:

In PHP you can create this variable like this:
~~~
[php]
$csrfVar =
'YII_CSRF_TOKEN:"'.Yii::app()->request->csrfToken.'"';
~~~
And than you just have to paste it among $.post() variables, plus you can add
"ajax" variable just for your needs:
~~~
[php]
$.post("editUser",{ YII_CSRF_TOKEN:"12345678", ajax:1,
userId:1 },function(html){
  alert("POST done: " + html); 
}, 'json' ); 
~~~

### 5.6.9 Are you AJax or non-Ajax call?

And how to find out in an action whether it is called via Ajax or in a commmon
way? You can write this method in PHP:
~~~
[php]
function isAjax()
{
  return ( Yii::app()->request->isAjaxRequest() or
isset($_POST["ajax"]) or isset($_GET["ajax"]) );
  // Yii::app()->request->isAjaxRequest() should be enought, but people
say it's not reliable. 
} 
~~~ 

... Let me know if everyting works or suggest enhancements, I will love to learn
something new :) 

                                    
## 5.7. Table row as a FORM
I guess that everybody has experienced a situation when it would be great to
display list of records to user as a table where each row would be a an active
form that would allow user to directly change the record via ajax. 

Imagine that you have an eshop with pencils and you want user to confirm
all items that are in his cart. You want him to specify color, quantity and
material of all pencils he wants to buy. 

Basically there are 2 possibilities.

1. On the end of each row you can place an edit-icon. If user clicks it a new
screen with usual form will be shown. Each row will be edited separetly.
2. The same but via Fancybox and Ajax. It's faster for user and more
user-friendly.

But you can also place on each row a html select (with list of colours),
radio-button group (with list of materials) and one textbox for quantity, plus
"save" button that will instantly save the record via Ajax.

In this case your html table will look cca like this:

~~~
[php]
<table>
  <tr>
    <td>
      <input type="text" name="quantity"
value="a">
    </td>
    <td>
      <select name="colour">
        <option value="red">RED</option>
        <option value="blue">BLUE</option>
      </select>
      <input type="radio" name="material"
value="wood" checked="checked">wood
      <input type="radio" name="material"
value="plastic">plastic
      <input type="radio" name="material"
value="glass">glass
    </td>
    <td>
      <a href="#" class="rowSubmit">Save</a>
    </td>
  </tr>
</table>
~~~

But where to place the FORM that would make the function? Form can't be used,
because of HTML validity. It has to be faked in jQuery cca like this:

~~~
[php]
<script type="text/javascript">
$(document).ready(function(){
  $(".rowSubmit").click(function()
  {
     var serialized =
$(this).closest('tr').wrap('<form>').parent().serialize();
      
     $.get('url2action', serialized, function(data){
       // ... can be empty
       // $.fancybox({content:data});
     }); 
   });
});        
</script>
~~~

First we place the whole TR into a fictive FORM and than it can be serialized.

And a tip/trick for you. If you write $("my html code") or
$(myStringVariableWithHtml) it will be turned into "jQuery object" and
you can append next jQuery functions. For example .serialize(), .html()
etc.

**I'm sorry, I had to split this article into more parts.** Next is [**Yii for
beginners 2**](http://www.yiiframework.com/wiki/462/yii-for-beginners-2/
"Yii for beginners 2")