Top Banner
Version 0.7 (8 th September 2011) 1 & MVC architecture ... Practically, in examples … A brief introduction for greenhorns …. By a Yii greenhorn:
32

Yii Version 07

Dec 02, 2014

Download

Documents

bdxpert
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Yii Version 07

Version 0.7 (8th

September 2011)

1

&

MVC architecture

... Practically, in examples …

A brief introduction for greenhorns

…. By a Yii greenhorn:

Page 2: Yii Version 07

2

Content

1. Prerequisites .................................................................................................................................... 4

2. MVC - Architecture description ....................................................................................................... 4

2.1. Controller..................................................................................................................................... 5

2.1.1. Action ...................................................................................................................................... 5

2.2. Model .......................................................................................................................................... 6

2.3. View ............................................................................................................................................. 6

3. What is it a Framework (and why to use it) .................................................................................... 7

4. Yii framework .................................................................................................................................. 7

4.1. The demo project in Yii (why and how to use it)......................................................................... 7

5. Using Yii in praxis ............................................................................................................................. 9

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

5.2. Create database for your project ................................................................................................ 9

5.2.1. DB design tool ....................................................................................................................... 10

5.2.1. Run yiic shell .......................................................................................................................... 12

5.2.2. Define relations in Models manually..................................................................................... 12

5.3. How to create your first Controller ........................................................................................... 13

5.3.1. Controller - notes from praxis .............................................................................................. 14

5.3.1.1. Session ............................................................................................................................... 14

5.3.1.2. Using relations ................................................................................................................... 14

5.3.1.3. Setting HTML page title ..................................................................................................... 14

5.4. View ........................................................................................................................................... 15

5.4.1. Grouped drop down list ........................................................................................................ 15

5.4.2. Creating links: ........................................................................................................................ 16

5.4.3. Sending variables to View from Controller ........................................................................... 17

5.4.4. Send form using hyperlink (not button) + confirm ............................................................... 17

5.4.5. Ajax (operations on background, real time form validation) ................................................ 18

5.4.5.1. textBox → dropDownList .................................................................................................. 19

5.4.5.2. dropDownList → dropDownList ........................................................................................ 20

5.4.5.3. textBox → textbox ............................................................................................................. 21

5.5. Models and using them - in praxis (new!) ................................................................................. 22

5.5.1. basic overview of model’s code ............................................................................................ 22

5.5.2. overview of another useful methods .................................................................................... 26

Page 3: Yii Version 07

3

5.5.2.1. Scope() ............................................................................................................................... 26

5.5.2.2. defaultScope() ................................................................................................................... 27

5.5.2.3. Other things ....................................................................................................................... 29

6. Themes (new!) ............................................................................................................................... 30

7. Used links ...................................................................................................................................... 31

Page 4: Yii Version 07

4

1. PREREQUISITES

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# …

2. MVC - ARCHITECTURE DESCRIPTION

First of all, we will generally look at the MVC abbreviation used above. 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 do 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 and

decides, counts, thinks … It simply acts.

DB Model ViewController

Image 1) MVC schema

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.)

Page 5: Yii Version 07

5

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 whenever you enter any address in browser. When you use

MVC architecture (in Yii framework), addresses have special format. They include parameter

that specifies which controller will be used.

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?

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 edits users than his one sub-controller can delete users, another one can add

users, third one changes 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:

www.myweb.com/index.php?r=myController/myAction

We can rewrite this address for example like this:

www.myweb.com/index.php?r=users/edit

Page 6: Yii Version 07

6

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 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:

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: $employee->department. Where the word

“department” is name of the relation.

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, JavaScripts 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 much easier not to send

data from Controller to it, but to read data from DB in View (using model) and show then.

Page 7: Yii Version 07

7

3. WHAT IS IT A 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 CHtml::beginForm(); and it creates this html

code: <form method=”post” action=”thisScriptName”>.

And why to use frameworks? It makes your work easier. You don’t have to program 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 [1] and documentation [2].

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: [3]. 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 IN YII (WHY AND HOW TO USE IT)

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.

Page 8: Yii Version 07

8

These [4] [5] [6] could help you. Manuals describe basic work with Yii like creating demo

project, relations among tables etc …

Important think 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 relations between tables), 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)

C:\Program Files\wamp\www\yii\framework ; C:\Program Files\wamp\bin\php\php5.3.0

Page 9: Yii Version 07

9

5. USING YII IN PRAXIS

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

be figured out just so. I will paste here everything I have discovered so far.

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 to your DB

[7] 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 will use command line to generate part of your application automatically. Command line

can generate models, views and controllers. (I generate only models because I want to make it my

way)

See this. It’s 4th part of a Yii tutorial [8].

In this tutorial [8] 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’s console 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.

Page 10: Yii Version 07

10

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” [10] 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.

Image 2) MySQL Workbench in action - ER creation

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 name 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 click the button in the black box that appeared few seconds ago. Then you click

appropriate PK column in another table and you’re done

with this relation

Page 11: Yii Version 07

11

When you’re done with DB design, you just export the whole DB into an SQL script and paste it

to your DB editor (for example PhpMyAdmin), or in new version you can export DB directly to MySQL

using shortcut Ctrl+G I think. Finally you run the command “yiic shell” and create models. Simple and

quick.

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.

Image 3) Workbench in action - DB overview

Page 12: Yii Version 07

12

5.2.1. RUN YIIC SHELL

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 table. Than you

can, of course, change generated forms and web pages to fit your requirements.

5.2.2. 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 [5], time 12:15 or manual [9].

What is the relation? As I wrote above, it’s an SQL Join. You specify Primary key (PK) and

foreign key (FK) using these relations and Yii can then “tunnel” from Employee to his job description

via 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:

$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 with the BELONGS_TO. Second possibility is HAS_ONE. See links and explanations. And as I am

never sure, I recommend to specify relations in DB a generate them using command line.

Page 13: Yii Version 07

13

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”. Blue is common for all controllers. Green is name of your controller. 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

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”

as shown above. The “r” parameter of “actionMyaction” would look like this: “?r=Myfirst/Myaction”.

What does mean the row where is written: $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. Vide infra. (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 of views.

Page 14: Yii Version 07

14

5.3.1. CONTROLLER - NOTES FROM PRAXIS

5.3.1.1. SESSION

In controller, 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: 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, you can access one table from another one using command like this:

$employees = $department->get_employees; (get_employees = relation name)

You can also specify which employees you want to get - by DB column name:

$employees = $department->get_employees(array('condition'=>'born<1950'))

Or you can join tables and order it by any column:

$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 command MainMenu::model()->with('relation1.relation2') we join 3 tables.

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: $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: Yii::app()->name. It’s

value is set in file: protected/config/main.php

Page 15: Yii Version 07

15

5.4. VIEW

View is a very simple thing so I will just show some tricks.

5.4.1. GROUPED DROP DOWN LIST Html code can be generated semi-automatically using static class CHtml. You can create for

example drop-down-list like this:

Instead of this:

<select name="selectName" id="selectName">

<option value="1">item1</option>

<option value="2">item2</option>

</select>

You can write this:

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 string containing ca this: width=”100” style=”color:red;”

$data = CHtml::listData( Model::model()->findAll(),'id_item','item_descr' )

Method listData() just generates following array:

array(‘value1’=>’caption1’, ‘value2’=>’caption2’ … )

Explanation:

$data is a set of <option> tags. Basically it’s simple mixed Array with “name=>value” pairs. This

Array can be created automatically using function:

listData($listOfItems, $valueColumn, $captionColumn)

• $listOfItems = it’s clear, you use for example: findAll(array(‘condition’=>’id>4’))

• $valueColumn = what column will be used to fill the value of <option> tag

• $captionColumn = what column will be used to fill the caption of <option> tag

Page 16: Yii Version 07

16

• 4th (now not used) parameter is name of a column that is used to group items in drop-

down-list.

How works the 4th parameter?

Let’s say you have a list of countries. Each country belongs to 1 continent. 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 this:

How to do this?

If you have 2 tables – 1st for countries, 2nd for continents – you should create an SQL VIEW that

will put these tables together using JOIN. This View will be the source model for your drop-down-list.

(SQL Views appear like tables and you can create model for them)

Now you can use the 4th parameter in dataList() and set its value to ‘Continent’.

Your view should look like this:

Continent ID Continent Country ID Country

1 Europe 1 Germany

1 Europe 2 England

1 Europe 3 Spain

2 South America 4 Brasilia

… … … …

5.4.2. CREATING LINKS:

Here I Will just recommend to use function CHtml::link(). It can solve some problems with

www links. To create urls always use method $this->createUrl(‘controller/action’) or

$this->createUrl(‘action’) !

<optgroup label="Europe">

<option value = „2“>England</option>

<option value = „1“>Germany</option>

<option value = „3“>Spain</option>

</optgroup>

Page 17: Yii Version 07

17

5.4.3. SENDING VARIABLES TO VIEW FROM CONTROLLER

When you want to send something from Controller to a View, you just add 1 parameter to

$this->render() method. Like this:

$this->render(‘myview’, array(‘variableName’=>$value));

‘Variable name’ = In the View you can start using variable of this name.

$value = vale of previously introduced variable. It can be integer, string, array, mixed array.

Whatever.

5.4.4. SEND FORM USING HYPERLINK (NOT BUTTON) + CONFIRM

<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 cannot write this: <?php echo ‘ ’word-in-apostrophes’ ‘;?>

Apostrophe can be written like this: <php echo ‘ \' word-in-apostrophes\' ‘; ?>

Page 18: Yii Version 07

18

5.4.5. AJAX (OPERATIONS ON BACKGROUND, REAL TIME FORM VALIDATION)

When I say “real-time” I mean that this “real-time” operation is done without reloading 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.

If you search the internet for an advice how to work with Ajax, how to create real-time form

validation, real-time textbox whispering… you find just difficult and uncomfortable solutions. Yii is

different. It offers really simple and quick solution. 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.

Page 19: Yii Version 07

19

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 thing is the action mentioned in the URL

section. This action must be written in actual controller. It’s the controller you used to draw this

view.

// 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());

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:

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 Model::model() and check

something.. It’s up to you. The only rule is that you 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.

Page 20: Yii Version 07

20

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 pretty the same.

// 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());

Only the first line is changed in comparison with the first example. Below is appropriate action.

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

);

}

}

Page 21: Yii Version 07

21

5.4.5.3. TEXTBOX → TEXTBOX

If we do not want to add values to something (as for example shown in case of dropdowns) 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.

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());

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).

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 in Action in a different way.

Read more at: [12], [13]

Page 22: Yii Version 07

22

5.5. MODELS AND USING THEM - IN PRAXIS (NEW!)

5.5.1. BASIC OVERVIEW OF 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.

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:

$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:

$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.

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:

public function tableName()

{

return 'nameOfDbTable';

}

Page 23: Yii Version 07

23

Third method is function rules()[14]. 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, see [14].

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. [9]

public function relations()

{

return array(

'getUsersPosts'=>array(self::HAS_MANY, 'Posts',' author_id '),

);

}

Page 24: Yii Version 07

24

And finally last default function attributeLabels() defines labels (descriptions) for table

columns.

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:

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:

Page 25: Yii Version 07

25

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()

Page 26: Yii Version 07

26

5.5.2. OVERVIEW OF ANOTHER USEFUL METHODS

5.5.2.1. SCOPE()

Scopes are very useful. If I simplify it they allow you to save an SQL command and use it as a

function in connection with particular model. Example:

$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 [15] is defined like this:

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.

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:

$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:

Page 27: Yii Version 07

27

$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. DEFAULTSCOPE()

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.

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)

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'

),

);

}

Page 28: Yii Version 07

28

In scopes you can use everything from CDbCriteria [16]. 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.

Page 29: Yii Version 07

29

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:

$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

// 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:

$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.

Page 30: Yii Version 07

30

6. THEMES (NEW!)

You may want to skin your web and allow users (or yourself) to change the skins on demand.

It’s very easy. In default state (in automatically created demo project) no theme is set or used. Is

used some default appearance. This was the first thing that I did not understand

To turn a theme on, you have to specify it in file “protected/config/main.php” by adding the

red line:

return array(

'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..',

'name'=>'Hello World !!',

'theme'=>'theme1',

);

It means that this variable is readable using Yii::app()->theme->getName(). You can set it

programmatically in an ACTION (not in view!!) like this:

Yii::app()->theme = 'theme1'; // = each user can have (select) different theme

If theme is not set (using config file, or programmatically) then method getName() will throw

error!

Yii::app()->theme->baseUrl will contain your theme path = you can use it in layout file to

address your css files, images etc.

To use your theme1, you will have to create a new subfolder in “themes” folder and name it

“theme1”. The “themes” folder is placed in the root of your project. In folder “theme1” will be the

same structure as in “protected” folder. Create there views and CSS folders.

If a theme is set, views and controllers will be taken from your theme folder. If Yii do not find

them, tries to look for them in ordinary “views” and “controllers” folders.

But controllers and actions can be the same for all themes. There does not have to be a reason

to change them.

On the other hand, CSS files will be probably different, so create CSS folder in folder of your

new theme and put new CSS files in it.

Page 31: Yii Version 07

31

7. USED LINKS

[1] Yii homepage:

http://www.yiiframework.com/

[2] Yii documentation:

http://www.yiiframework.com/doc/

[3] Wamp server:

http://www.wampserver.com/en/

[4] Hello World tutorial:

http://code.google.com/p/yii/issues/detail?id=86

[5] First project video:

http://www.yiiframework.com/screencast/blog/

[6] How to create a blog:

http://www.yiiframework.com/files/yii-blog-1.1.0.pdf

[7] Configure Yii:

http://blog.dmcinsights.com/2009/11/03/configuring-yii/

[8] Tables in DB:

http://blog.dmcinsights.com/2009/11/05/creating-models-views-and-controllers-in-yii/

[9] Relations between models:

http://www.yiiframework.com/doc/guide/database.arr

[10] MySQL Workbench

http://dev.mysql.com/downloads/workbench/5.2.html

[11]

http://www.sterlingsavvy.com/tutorials/index.php?t=1&l=10

[12] Ajax Yii documentation

http://www.yiiframework.com/doc/api/CHtml#ajax-detail

[13] Ajax Yii coockbock + discussion !

http://www.yiiframework.com/doc/cookbook/24/

Page 32: Yii Version 07

32

[14] Mode: method rules()

http://www.yiiframework.com/doc/guide/1.1/en/form.model

[15] Active Record

http://www.yiiframework.com/doc/guide/1.1/en/database.ar

[16] CDbCriteria

http://www.yiiframework.com/doc/api/1.1/CDbCriteria