Loving Coding & Visual Design

yii框架快速入门

Layouts

This is a magic line as it pulls in the page-specific content. If the site you’re looking at now used Yii, the value of $content would be all the HTML that makes up this post you’re reading.

自定义layout
public function actionAbout() {
$this->layout = 'somewhere';
$this->render('about');
}

指定sub路径
# protected/controllers/SiteController.php
public function actions() {
return array(
'page' => array('class' => 'CViewAction')
);
}

# protected/controllers/SomeController.php
public function actionAbout() {
$this->render('about');
}

http://www.example.com/index.php?r=site/page&view=about or,
http://www.example.com/index.php/site/page/view/about,

指定静态路径
# protected/controllers/SiteController.php
public function actions() {
return array(
'page' => array(
'class' => 'CViewAction',
'basePath' => 'static'
)
);
}

/site/page/view/company.board would display the protected/views/site/pages/company/board.php page

By default, if no $_GET['view'] value is provided, CViewAction will attempt to display an index.php static file.
# protected/controllers/SiteController.php
public function actions() {
return array(
'page' => array(
'class' => 'CViewAction',
'defaultView' => 'about' //index as default
)
);
}


其他页调用$content
beginContent('//directory/file.php'); ?>
// Content.
endContent(); ?>

======Model Events
afterConstruct()
afterDelete()
afterFind()
afterSave()
afterValidate()
beforeDelete()
beforeFind()
beforeSave()
beforeValidate()

The CComponent class provides three main tools:

The ability to get and set attributes
Event handling
Behaviors

# protected/models/SomeModel.php
protected function afterSave() {
// Do relation Model method()
return parent::afterSave();
}

# protected/models/Page.php
protected function beforeValidate() {
if(empty($this->user_id)) { // Set to current user:
$this->user_id = Yii::app()->user->id;
}
return parent::beforeValidate();
}

# protected/models/AnyModel.php::rules()
array('date_entered', 'default', 'value'=>new CDbExpression('NOW()'), 'on'=>'insert'),
array('date_updated', 'default', 'value'=>new CDbExpression('NOW()'), 'on'=>'update'),

or

# protected/models/AnyModel.php
public function beforeSave() {
if ($this->isNewRecord) {
$this->created = new CDbExpression('NOW()');
} else {
$this->modified = new CDbExpression('NOW()');
}
return parent::beforeSave();
}



These are the default rules set in the configuration file:

'rules'=>array(
'/' => '/view',
'//' => '/',
'/' => '/',
),

So page/42 is associated with the route “page/view”.
# protected/controllers/PageController.php
public function actionView($id) {
// Etc.
}

# protected/config/main.php
'verify//' => 'user/verify',
# protected/controllers/UserController.php
public function actionVerify($x, $y) {
// Etc.
}

Case Sensitivity
the regular expression w+ will match Post, post, or pOsT, only post will match a controller in your application.


Routes

$this->createUrl('') returns the URL for the current page.
# protected/controllers/PageController.php
public function actionDummy() {
$url = $this->createUrl('user/index'); // user/index
}
$url = $this->createUrl('view', array('id' => 42)); // page/view id=42
$url = Yii::app()->createUrl('page/view', array('id' => 42));
The main difference between the two versions of the createUrl() method is that the CController version can be used without referencing a controller ID, whereas the Yii::app() version (i.e., that defined in CApplication) requires a controller ID be provided.


Cookies
Yii::app()->request->cookies array
Yii::app()->session

Yii::app()->request->cookies['name'] = new CHttpCookie('name', 'value');
Yii::app()->request->cookies['name']->value
To test if a cookie exists, just use isset() on Yii::app()->request->cookies['name'],
Delete: unset(Yii::app()->request->cookies['name']);
Yii::app()->request->cookies->clear();

$cookie = new CHttpCookie('name', 'value');
Then adjust the expire attribute:

$cookie->expire = time() + (60*60*24); // 24 hours
Then add the cookie to the application:

Yii::app()->request->cookies['name'] = $cookie;

You can also improve the security of your cookies by setting Yii’s enableCookieValidation to true, in the Yii configuration file:

return array(
'components'=>array(
'request'=>array(
'enableCookieValidation'=>true,
),
),
);

To prevent a CSRF attack on your site, first make sure that all significant form submissions use POST instead of GET. You should be using POST for any form that changes server content anyway, but a CSRF POST attack is a bit harder to pull off than a GET attack.

Second, set enableCsrfValidation to true in your configuration file:

return array(
'components'=>array(
'request'=>array(
'enableCsrfValidation'=>true,
),
),
);


Sessions
you don’t have to invoke session_start()

Yii::app()->session['var'] = 'value';
echo Yii::app()->session['var']; // Prints "value"
unset(Yii::app()->session['var']);

Within that, you would add a “session” element to the “components” array, wherein you customize how the sessions behave. The key attributes are:

autoStart, which defaults to true (i.e., always start sessions)
cookieMode, with acceptable values of none, allow, and only, equating to: don’t use cookies, use cookies if possible, and only use cookies; defaults to allow
cookieParams, for adjusting the session cookie’s arguments, such as its lifetime, path, domain, and HTTPS-only
gCProbability, for setting the probability of garbage collection being performance, with a default of 1, as in a 1% chance
savePath, for setting the directory on the server used as the session directory, with a default of /tmp
sessionName, for setting the session’s, um, name, which defaults to PHPSESSID
timeout, for setting after how many seconds a session is considered idle, which defaults to 1440

protected/config/main.php:

'session' => array (
'autoStart' => false,
),

If you are using sessions, for security purposes, you may want to change the session’s name, always require cookies, and change the save path:

'session' => array (
'sessionName' => 'Site Access',
'cookieMode' => 'only',
'savePath' => '/path/to/new/directory',
),


For this reason, changing the save path to a directory within your own site can be a security improvement. Alternatively, you can store the session data in a database. To do that, add this code to the “components” section of protected/config/main.php:

'session' => array (
'class' => 'system.web.CDbHttpSession',
'connectionID' => 'db',
'sessionTableName' => 'actual_table_name',
),

Yii::app()->session->sessionID.

To do so, call Yii::app()->session->clear() to remove all of the session variables. Then call Yii::app()->session->destroy() to get rid of the actual data stored on the server.



Rendering

public function actionUpdate($id) {
$data=$this->loadModel($id);

$this->render('update',array(
'model'=>$data
));
}
The render() method takes an optional third argument, which is a Boolean indicating if the rendered result should be returned to the Controller instead of sent to the Web browser

renderPartial('_form', array('model'=>$model)); ?>

Then indicate the subdirectory and file, still omitting the extension:

renderPartial('//search/_form'); ?>


Forms

beginWidget('CActiveForm', array(
'id'=>'user-form',
'enableAjaxValidation'=>true,
'focus'=>array($model,'firstName'),
)); ?>

endWidget(); ?>


Validation scenarios


Now when you wish to run validation under a specific scenario you must define it in when calling CModel::validate(), as so


//in user model
public function rules() {
return array(
//Set required fields
//Applies to 'register' scenario
//Note 'on' property
array('username, password, password_repeat, email', 'required', 'on' => 'register'),

//Applies to 'recover' scenario
array('email', 'required', 'on' => 'recover'),

//Applies to all scenarios
array('username, password', 'length', 'max'=>35, 'min'=>3),

//This rule checks if the username is unique in the database in
//the 'register' scenario (we don't want it to check for uniqueness
//on the login page for instance)
array('username', 'unique', 'on' => 'register'),

//This rule applies to 'register' and 'update' scenarios
//Compares 'password' field to 'password_repeat' to make sure they are the same
array('password', 'compare', 'on' => 'register, update'),
);
}

$user->validate(''); //runs validation under the given scenario

//example:
if ($user->validate('register')) {
$user->save(false);
}

Console Application

Related Models
a foreign key (FK)

// protected/models/Posts
public function relations() {
return array(
'categories' => array(self::HAS_MANY, 'Categories', 'postId')
);
}


Now Posts has a categories attribute, meaning that the following form code will work.


labelEx($model,'categories'); ?>
dropDownList($model, 'categories', CHtml::listData(
Categories::model()->findAll(), 'id', 'category'), array('multiple'=>'multiple', 'size'=>5)
); ?>
error($model,'categories'); ?>

when you create a relation, that relation becomes an attribute of the Model.

public function actionCreate() {
$model=new Posts;
if(isset($_POST['Posts'])) {
$model->attributes=$_POST['Posts'];
if($model->save()) {
foreach ($_POST['Posts']['categories'] as $categoryId) {
$postCategory = new PostsCategories;
$postCategory->postId = $model->id;
$postCategory->categoryId = $categoryId;
if (!$postCategory->save()) print_r($postCategory->errors);
}
Now, when a new Post is created, one new record is created in PostsCategories for each selected category.

This method is called for the update, delete, and view actions and just returns a single Model. The Model is loaded using:

$this->_model=Posts::model()->findbyPk($_GET['id']);

After that, within the loadModel() method, you can add this code to fetch the associated PostsCategories:

$criteria=new CDbCriteria;
$criteria->condition='postId=:postId';
$criteria->select = 'categoryId';
$criteria->params=array(':postId'=>$_GET['id']);
$postCategories = PostsCategories::model()->findAll($criteria);

That code selects all of the categoryId values from PostsCategories where the postId value equals this post’s id. Next, we need to turn those results into an array:

$categories = array();
foreach ($postCategories as $category) {
$categories[] = $category->categoryId;
}
Now, $categories is an array of numeric values, one for each category associated with the post. Just add this to the loaded Model:

$this->_model->categories = $categories;

The easiest way to handle all possibilities is to clear out the existing values (for this post) in the PostsCategories table, and then add them in anew. To do that, in actionUpdate() of the PostsController, you would have:

if($model->save()) {
$criteria=new CDbCriteria;
$criteria->condition='postId=:postId';
$criteria->params=array(':postId'=>$model->id);
PostsCategories::model()->deleteAll($criteria);





Handling Checkboxe

checkBox($model,'attribute',array('value' => 'Y', 'uncheckValue'=>'N')); ?>

Forcing Login

'behaviors' => array(
'onBeginRequest' => array(
'class' => 'application.components.RequireLogin'
)
),
Next, create a file called RequireLogin.php and store it in the protected/components directory. That file needs to define the RequireLogin class
class RequireLogin extends CBehavior
{
public function attach($owner)
{
$owner->attachEventHandler('onBeginRequest', array($this, 'handleBeginRequest'));
}
public function handleBeginRequest($event)
{
if (Yii::app()->user->isGuest && !in_array($_GET['r'],array('site/login'))) {
Yii::app()->user->loginRequired();
}
}
//when the onBeginRequest event occurs, this class’s handleBeginRequest() method should be called.

public function handleBeginRequest($event)
{
if (Yii::app()->user->isGuest && !in_array($_GET['r'],array('site/login'))) {
Yii::app()->user->loginRequired();
}
}

}
?>

MemCached
'cache' => array (
'class' => 'CMemCache',
'servers'=>array(
array(
'host'=>'localhost',
'port'=>11211,
),
),
),

Access Control

a Controller’s accessRules() method dictates who can do what. In a very simple way, the “what” refers to the Controller’s action methods, like actionList() or actionDelete().

represented by * (anyone) and @ (logged-in users),
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'list' and 'show' actions
'actions'=>array('list','show'),
'users'=>array('*'),
),
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('create','update'),
'users'=>array('@'),
),
array('allow', // allow admin user to perform 'admin' and 'delete' actions
'actions'=>array('admin','delete'),
'users'=>array('admin'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}

Perhaps your users in the database would be registered by user type, or role, and that the permissions would be based upon these roles. In that case, you can add an expression element to the returned array in the access rules:

array('allow',
'actions'=>array('admin','delete'),
'users'=>array('@'),
'expression'=>'PHP code to be evaluated'
),

array('allow',
'actions'=>array('publish'),
'users'=>array('@'),
'expression'=>'isset($user->role) && ($user->role==="editor")'
),



public function actionDelete()
{
$event = $this->loadEvents(); // Fetch the specific event Model.
// Can only delete the events they created:
if ($event->ownerId == Yii::app()->user->id) {
$event->delete();
} else {
throw new CHttpException(403,'Invalid request. You are not allowed to delete this event.');
}
}

Custom Authentication
In this post, I want to change that behavior so that:

Authentication is performed against a database table
The user’s email address is used instead of their username
The user’s ID is stored for later reference
The user’s “role” is stored for later reference

'user'=>array(
// enable cookie-based authentication
'allowAutoLogin'=>true,
),
To disable cookie-based authentication, either remove that code entirely, or change allowAutoLogin to false.


ome/PHP/Configuring FCKEditor for Yii-Driven Sites


Configuring FCKEditor

To use the FCKEditor in a form, you’ll need to edit the _form.php file for the particular View. For example, on one site I edited protected/views/page/_form.php, as the admin created the site’s content through a Page Model. By default the form will have a standard textarea for every TEXT type MySQL column:

6, 'cols'=>50)); ?>
To use FCKEditor instead of the textarea, invoke the integration widget by replacing that code with this:

widget('application.extensions.fckeditor.FCKEditorWidget',array(
'model' => $model,
'attribute' => 'content',
'height' => '600px',
'width' => '100%',
'fckeditor' => dirname(Yii::app()->basePath).'/htdocs/fckeditor/fckeditor.php',
'fckBasePath' => Yii::app()->baseUrl.'/fckeditor/')
); ?>

open fckeditor/editor/filemanager/connectors/php/config.php in your text editor or IDE.
session_start();
$Config['Enabled'] = (isset($_COOKIE['PHPSESSID']) && (in_array('moderator', $_SESSION))) ;

A logical work-around is to use PHP’s strip_tags() instead, providing it with the optional second argument of allowable tags:

echo strip_tags($model->content, '



下一页


最 近 文 章

  1. Qunit测试用例 - Mon, 30 Nov -0001 00:00:00 +0000
  2. 前端开发环境搭建 - Mon, 30 Nov -0001 00:00:00 +0000
  3. centOs 安装 PyOt4 - Mon, 30 Nov -0001 00:00:00 +0000
  4. windows下安装ImageMagick - Mon, 30 Nov -0001 00:00:00 +0000
  5. 加密邮件 - Mon, 30 Nov -0001 00:00:00 +0000
  6. Centos mini常见问题 - Mon, 30 Nov -0001 00:00:00 +0000
  7. swift - Mon, 30 Nov -0001 00:00:00 +0000
  8. json_encode出错 Invalid UTF-8 sequence in argument - Mon, 30 Nov -0001 00:00:00 +0000
  9. Javascript循环的优先级 - Mon, 30 Nov -0001 00:00:00 +0000
  10. editplus 配置 yui 压缩 - Mon, 30 Nov -0001 00:00:00 +0000