Active Record (AR) 類及實現

Active Record (AR) 是一個流行的 對象-關係映射 (ORM) 技術。 每一個 AR 類表明一個數據表(或視圖),數據表(或視圖)的列在 AR 類中體現爲類的屬性,一個 AR 實例則表示表中的一行。 常見的 CRUD 操做做爲 AR 的方法實現。所以,咱們能夠以一種更加面向對象的方式訪問數據。 例如,咱們可使用如下代碼向 tbl_post 表中插入一個新行。php

yii 表單驗證規則html

<?php
classContactFormextendsCFormModel
{
    public$_id;
    public$contact;//聯繫人
    public$tel;//電話
    public$fax;//傳真
    public$zipcode;//郵編
    public$addr;//地址
    public$mobile;//手機
    public$email;//郵箱
    public$website;//網址
    public$qq;//QQ
    public$msn;//MSN
    publicfunctionrules()
    {
        returnarray(
            array('contact','required','on'=>'edit','message'=>'聯繫人必須填寫.'),
            array('contact','length','on'=>'edit','min'=>2,'max'=>10,'tooShort'=>'聯繫人長度請控制在2-10個字符.','tooLong'=>'聯繫人長度請控制在2-10個字符.'),
             
            array('tel','match','pattern'=>'/^(\d{3}-|\d{4}-)(\d{8}|\d{7})?$/','message'=>'請輸入正確的電話號碼.'),
            array('fax','match','pattern'=>'/^(\d{3}-|\d{4}-)(\d{8}|\d{7})?$/','message'=>'請輸入正確的傳真號碼.'),
            array('mobile','match','pattern'=>'/^13[0-9]{1}[0-9]{8}$|15[0189]{1}[0-9]{8}$|189[0-9]{8}$/','message'=>'請輸入正確的手機號碼.'),
 
            array('email','email','on'=>'edit','message'=>'郵箱輸入有誤.'),
             
            array('zipcode','required','on'=>'edit','message'=>'郵編必須填寫.'),
            array('zipcode','numerical','on'=>'edit','message'=>'郵編是6位數字.'),
            array('zipcode','length','on'=>'edit','min'=>6,'max'=>6,'tooShort'=>'郵編長度爲6位數.','tooLong'=>'郵編長度爲6位數.'),
             
            array('website','url','on'=>'edit','message'=>'網址輸入有誤.'),
            array('qq','match','pattern'=>'/^[1-9]{1}[0-9]{4,11}$/','message'=>'請輸入正確的QQ號碼.'),
            array('msn','email','on'=>'edit','message'=>'MSN輸入有誤.'),
        );
    }
 
}


$post=Post::model()->find(array(
    'select'=>'title',
    'condition'=>'postID=:postID',
    'params'=>array(':postID'=>10),
));
// 查找 postID=10 的那一行
$post=Post::model()->find('postID=:postID', array(':postID'=>10));
$criteria = new CDbCriteria();
$criteria->select = 'table_name,model_id,sum(amount) total';
$criteria->group = 'table_name,model_id';
$criteria->addCondition("$nIdcId=4");//也能夠$criteria->condition = "$nIdcId=4";
$aResult = accessory_info::model()->findAll($criteria);


$c = new CDbCriteria();
$c->select = 't.id, t.created_at, t.outsource_id, t.user_id, t.operate, t.content';
$c->join = 'LEFT JOIN outsource ON outsource.id=t.outsource_id';
$c->condition = 'outsource.idc_id IN(' . implode(',', $idc_ids)  . ')';

if($last_log_id) {
$c->condition .= " AND t.id > $last_log_id";
}

$c->limit = 20;
$c->order = 't.id DESC';

$logs = OutsourceProcessLog::model()->findAll($c);

array(
'header'=>'支付渠道',
'name'=>'buy_method_id',
'value'=>'$data->buyMethod->title',
'filter'=>CHtml::listData(CoinBuyMethod::model()->findAll(), 'id', 'title'),//filter過濾篩選
),
array(
'name' => 'admin.username',
'filter' => CHtml::activeDropDownList($model, 'admin_id', CHtml::listData(Admin::model()->findAll(), 'id', 'username'), array('empty' => '-所有管理員-')),
),


$post=new Post;
$post->title='sample post';
$post->content='post body content';
$post->save();

$User = User::model();
$User->setIsNewRecord(true);
$User->name='wangliweid';
$User->sex=1;
$User->insert(); 

$User = new User;
$User->name='wangdsdfliweid';
$User->insert(); 

$User = User::model()->findByPk(1);
$User->name='wangliwei';
$User->sex=1;
$User->save();

public function tableName()
{
    return '{{post}}'; //使用表前綴功能
}

$post=Post::model()->findByPk(10); // 假設有一個帖子,其 ID 爲 10
$post->delete(); // 從數據表中刪除此行

AR 依靠表中良好定義的主鍵。若是一個表沒有主鍵,則必須在相應的 AR 類中經過以下方式覆蓋 primaryKey() 方法指定哪一列或哪幾列做爲主鍵。

public function primaryKey()
{
    return 'id';
    // 對於複合主鍵,要返回一個相似以下的數組
    // return array('pk1', 'pk2');
}

3. 建立記錄 
要向數據表中插入新行,咱們要建立一個相應 AR 類的實例,設置其與表的列相關的屬性,而後調用 save() 方法完成插入:

$post=new Post;
$post->title='sample post';
$post->content='content for the sample post';
$post->create_time=time();
$post->save();


記錄在保存(插入或更新)到數據庫以前,其屬性能夠賦值爲 CDbExpression 類型。 例如,爲保存一個由 MySQL 的 NOW() 函數返回的時間戳,咱們可使用以下代碼:

$post=new Post;
$post->create_time=new CDbExpression('NOW()');
// $post->create_time='NOW()'; 不會起做用,由於
// 'NOW()' 將會被做爲一個字符串處理。
$post->save();
提示: 因爲 AR 容許咱們無需寫一大堆 SQL 語句就能執行數據庫操做, 咱們常常會想知道 AR 在背後到底執行了什麼 SQL 語句。這能夠經過開啓 Yii 的 日誌功能 實現。例如,咱們在應用配置中開啓了 CWebLogRoute ,咱們將會在每一個網頁的最後看到執行過的 SQL 語句。

4. 讀取記錄 
要讀取數據表中的數據,咱們能夠經過以下方式調用 find 系列方法中的一種:

// 查找知足指定條件的結果中的第一行
$post=Post::model()->find($condition,$params);
// 查找具備指定主鍵值的那一行
$post=Post::model()->findByPk($postID,$condition,$params);
// 查找具備指定屬性值的行
$post=Post::model()->findByAttributes($attributes,$condition,$params);
// 經過指定的 SQL 語句查找結果中的第一行
$post=Post::model()->findBySql($sql,$params);


$criteria=new CDbCriteria;
$criteria->select='title';  // 只選擇 'title' 列
$criteria->condition='postID=:postID';
$criteria->params=array(':postID'=>10);
$post=Post::model()->find($criteria); // $params 不須要了
注意,當使用 CDbCriteria 做爲查詢條件時,$params 參數再也不須要了,由於它能夠在 CDbCriteria 中指定,就像上面那樣。

一種替代 CDbCriteria 的方法是給 find 方法傳遞一個數組。 數組的鍵和值各自對應標準(criterion)的屬性名和值,上面的例子能夠重寫爲以下:

$post=Post::model()->find(array(
    'select'=>'title',
    'condition'=>'postID=:postID',
    'params'=>array(':postID'=>10),
));



// 獲取知足指定條件的行數
$n=Post::model()->count($condition,$params);
// 經過指定的 SQL 獲取結果行數
$n=Post::model()->countBySql($sql,$params);
// 檢查是否至少有一行復合指定的條件
$exists=Post::model()->exists($condition,$params);

直接更新數據表中的一行或多行而不首先載入也是可行的。 AR 提供了以下方便的類級別方法實現此目的:

// 更新符合指定條件的行
Post::model()->updateAll($attributes,$condition,$params);
// 更新符合指定條件和主鍵的行
Post::model()->updateByPk($pk,$attributes,$condition,$params);
// 更新知足指定條件的行的計數列
Post::model()->updateCounters($counters,$condition,$params);
在上面的代碼中, $attributes 是一個含有以 列名做索引的列值的數組; $counters 是一個由列名索引的可增長的值的數組;$condition 和 $params 在前面的段落中已有描述。

若是一個 AR 實例被一行數據填充,咱們也能夠刪除此行數據。

$post=Post::model()->findByPk(10); // 假設有一個帖子,其 ID 爲 10
$post->delete(); // 從數據表中刪除此行
注意,刪除以後, AR 實例仍然不變,但數據表中相應的行已經沒了。

使用下面的類級別代碼,能夠無需首先加載行就能夠刪除它。

// 刪除符合指定條件的行
Post::model()->deleteAll($condition,$params);
// 刪除符合指定條件和主鍵的行
Post::model()->deleteByPk($pk,$condition,$params);



當調用 save() 時, AR 會自動執行數據驗證。 驗證是基於在 AR 類的 rules() 方法中指定的規則進行的。 關於驗證規則的更多詳情,請參考 聲明驗證規則 一節。 下面是保存記錄時所需的典型的工做流。

if($post->save())
{
    // 數據有效且成功插入/更新
}
else
{
    // 數據無效,調用  getErrors() 提取錯誤信息
}
當要插入或更新的數據由最終用戶在一個 HTML 表單中提交時,咱們須要將其賦給相應的 AR 屬性。 咱們能夠經過相似以下的方式實現:

$post->title=$_POST['title'];
$post->content=$_POST['content'];
$post->save();

若是有不少列,咱們能夠看到一個用於這種複製的很長的列表。 這能夠經過使用以下所示的 attributes 屬性簡化操做。 更多信息能夠在 安全的特性賦值 一節和 建立動做 一節找到。

// 假設 $_POST['Post'] 是一個以列名索引列值爲值的數組
$post->attributes=$_POST['Post'];
$post->save();


CActiveRecord 提供了幾個佔位符方法,它們能夠在子類中被覆蓋以自定義其工做流。

beforeValidate 和
beforeSave 和 afterSave: 這兩個將在保存 AR 實例以前和以後被調用。
beforeDelete 和 afterDelete: 這兩個將在一個 AR 實例被刪除以前和以後被調用。
afterConstruct: 這個將在每一個使用 new 操做符建立 AR 實例後被調用。
beforeFind: 這個將在一個 AR 查找器被用於執行查詢(例如 find(), findAll())以前被調用。 1.0.9 版本開始可用。
afterFind: 這個將在每一個 AR 實例做爲一個查詢結果建立時被調用。

10. 使用 AR 處理事務 
每一個 AR 實例都含有一個屬性名叫 dbConnection ,是一個 CDbConnection 的實例,這樣咱們能夠在須要時配合 AR 使用由 Yii DAO 提供的 事務 功能:

$model=Post::model();
$transaction=$model->dbConnection->beginTransaction();
try
{
    // 查找和保存是可能由另外一個請求干預的兩個步驟
    // 這樣咱們使用一個事務以確保其一致性和完整性
    $post=$model->findByPk(10);
    $post->title='new post title';
    $post->save();
    $transaction->commit();
}
catch(Exception $e)
{
    $transaction->rollBack();
}

$url=$this->createUrl($route,$params);
$this指的是控制器實例; $route指定請求的route 的要求;$params 列出了附加在網址中的GET參數。

默認狀況下,URL以get格式使用createUrl 建立。例如,提供$route='post/read'和$params=array('id'=>100) ,咱們將得到如下網址:

/index.php?r=post/read&id=100

$user = Yii::app()->db->createCommand()->select('id, username, profile')->from('tbl_user u')->join('tbl_profile p', 'u.id=p.user_id')->where('id=:id', array(':id'=>$id))->queryRow();

$command = Yii::app()->db->createCommand('SELECT * FROM tbl_user');
$user = $command->queryRow();

$command = Yii::app()->db->createCommand();
$users = $command->select('*')->from('tbl_users')->queryAll();
$command->reset();  // clean up the previous query
$posts = $command->select('*')->from('tbl_posts')->queryAll();

// build and execute the following SQL:
// INSERT INTO `tbl_user` (`name`, `email`) VALUES (:name, :email)
$command->insert('tbl_user', array(
    'name'=>'Tester',
    'email'=>'tester@example.com',
));

// UPDATE `tbl_user` SET `name`=:name WHERE id=:id
$command->update('tbl_user', array(
    'name'=>'Tester',
), 'id=:id', array(':id'=>1));

4. Building Schema Manipulation Queries 
Besides normal data retrieval and manipulation queries, the query builder also offers a set of methods for building and executing SQL queries that can manipulate the schema of a database. In particular, it supports the following queries:

createTable(): creates a table
renameTable(): renames a table
dropTable(): drops a table
truncateTable(): truncates a table
addColumn(): adds a table column
renameColumn(): renames a table column
alterColumn(): alters a table column
dropColumn(): drops a table column
createIndex(): creates an index
dropIndex(): drops an index

若是瀏覽器重定位到登陸頁面,並且登陸成功,咱們將重定位瀏覽器到引發驗證失敗的頁面。咱們怎麼知道這個值呢?咱們能夠經過用戶部件的returnUrl 屬性得到。咱們所以能夠用以下執行重定向:

Yii::app()->request->redirect(Yii::app()->user->returnUrl);




$this->preinit();
$this->init();

self::$classMap 能夠在這裏定義類的路徑,在autoload裏調用

//頁面緩存控制器入口
可在main.php 中  設置catchAllRequest
$route=$this->catchAllRequest[0];

CModule 重載了 Ccomponent 的__get 方法

Yii::setApplication($this); 將app設置爲了application對象

先註冊component,這時並無加載他們,只有在getcomponet時才加載。


 var menuId = $("ul.nav").first().attr("id");var request = $.ajax({  url: "script.php",  type: "POST",  data: {id : menuId},  dataType: "html"}); request.done(function(msg) {  $("#log").html( msg );}); request.fail(function(jqXHR, textStatus) {  alert( "Request failed: " + textStatus );}); 

Example: Load and execute a JavaScript file.
 $.ajax({  type: "GET",  url: "test.js",  dataType: "script"}); 

設置cookie
$cookie = new CHttpCookie('mycookie','this is my cookie');
$cookie->expire = time()+60*60*24*30;  //有限期30天
Yii::app()->request->cookies['mycookie']=$cookie;
這裏的cookies 繼承了CCookieCollection ,他是CMap類型,重寫了add等等,在add中設置了cookie.
好比$cookie = Yii::app()->request->cookies;
$cookies['name'] = $cookie;
複製
讀取cookie:
$cookie = Yii::app()->request->getCookies();
echo $cookie['mycookie']->value;
複製
銷燬cookie:
$cookie = Yii::app()->request->getCookies();
unset($cookie[$name]);

//異步提交
$('#g').click(function(){
$.post('index.php',$('form').serialize());
}); 

//在控制器中都會先執行init 再執行beforeAction

過濾器
public function filterAccessAuth($filterChain) {  
echo 'a';
$filterChain->run();
}

public function filterAbc($filterChain) {  
$filterChain->run();
}
public function filters() {  
        return array(  
            'accessAuth  + session',  
'abc',
        );  
    }

Similar to .empty(), the .remove() method takes elements out of the DOM. Use .remove() when you want to remove the element itself, as well as everything inside it. In addition to the elements themselves, all bound events and jQuery data associated with the elements are removed. To remove the elements without removing data and events, use .detach() instead.

$.ajax({  url: "test.html",  context: document.body}).done(function() {  $(this).addClass("done");});

Deprecation Notice: The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks are deprecated as of jQuery 1.8. To prepare your code for their eventual removal, use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead.

原生js設置屬性
 this.style.color = "blue";
 js原生函數:decodeURIComponent()
最後爲了更好的區分attribute和property,基本能夠總結爲attribute節點都是在HTML代碼中可見的,而property只是一個普通的名值對屬性。

 Yii中有個場景的概念,咱們用到場景的地方主要是在model中定義rules規則的時候,能夠對不一樣的場景使用不一樣的校驗規則,因此,天然而然會認爲所謂的場景就是對應的action的名字。其實場景和action的名字是不一樣的概念來的,不能混爲一談。scenario則是M的一種屬性,理論上,scenario是獨立於action概念的,能夠在沒有action的場合下使用scenario。model的scenario是經過設置它的scenario屬性設置的,它和使用model的action沒有任何關係。

好比:

$model=new User;
$model->scenario = 'create';


$model=new User('create');

都是設置了執行一個action的時候對model進行校驗的場景

public function rules()
{
return array(
array('name','required'),
array('name', 'length', 'max'=>10,'min'=>5,'on'=>'a1 a2','except'=>'c1 c2'), on 用來設置場景,except用來排除場景
array('sex','required myvalitor'),
);
}

當model調用model->validate()時將加載rules中包含的類,每一個涉及到的屬性都會被被判斷。

public function myvalitor($name,$params){}

$loginType = Yii::app()->controller->module->loginType;
Yii::app()->controller //當前請求的controller對象
Yii::app()->controller->module//當前請求的controller對象所屬的module

在main的  'params' => include(dirname(__FILE__) . '/params.php'),裏設置一些其餘信息。

$this->redirect() //控制器的方法
$this->createUrl() //控制器的方法


public function run()
{
if($this->hasEventHandler('onBeginRequest'))
$this->onBeginRequest(new CEvent($this));
$this->processRequest();
if($this->hasEventHandler('onEndRequest'))
$this->onEndRequest(new CEvent($this));
}

public function run($actionID)
{
if(($action=$this->createAction($actionID))!==null)
{
if(($parent=$this->getModule())===null)
$parent=Yii::app();
if($parent->beforeControllerAction($this,$action))
{
$this->runActionWithFilters($action,$this->filters());
$parent->afterControllerAction($this,$action);
}
}
else
$this->missingAction($actionID);
}


//yii 執行流程
獲取控制器,init,filters ,beforeAction,

filter 的循環
filter 鏈經過調用自身的run($this) 造成一個循環,循環結束條件爲filter容器中的全部filter都執行完畢,若是一個filter沒有運行run,那麼action將不會執行,這樣就實現了過濾做用。


public function filter($filterChain)
{
if($this->preFilter($filterChain))
{
$filterChain->run();
$this->postFilter($filterChain);
}
}
從上邊能夠看出,以類實現的filter,將過濾函數通常寫在方法prefilter中

CActiveDataProvider provides data in terms of ActiveRecord objects which are of class modelClass. It uses the AR CActiveRecord::findAll method to retrieve the data from database. The criteria property can be used to specify various query options. 

$dataProvider=new CActiveDataProvider('Post', array(
    'criteria'=>array(
        'condition'=>'status=1',
        'order'=>'create_time DESC',
        'with'=>array('author'),
    ),
    'pagination'=>array(
        'pageSize'=>20,
    ),
));
// $dataProvider->getData() will return a list of Post objects

When data needs to be rendered in multiple pages, we can use CPagination to represent information such as total item count, page size, current page, etc. These information can be passed to pagers to render pagination buttons or links. 

Example: 

Controller action:
function actionIndex(){
    $criteria=new CDbCriteria();
    $count=Article::model()->count($criteria);
    $pages=new CPagination($count);

    // results per page
    $pages->pageSize=10;
    $pages->applyLimit($criteria);
    $models=Article::model()->findAll($criteria);

    $this->render('index', array(
    'models' => $models,
         'pages' => $pages
    ));
}


View:
<?php foreach($models as $model): ?>
    // display a model
<?php endforeach; ?>

// display pagination
<?php $this->widget('CLinkPager', array(
    'pages' => $pages,
)) ?>



/**
* Renders a view.
*
* The named view refers to a PHP script (resolved via {@link getViewFile})
* that is included by this method. If $data is an associative array,
* it will be extracted as PHP variables and made available to the script.
*
* This method differs from {@link render()} in that it does not
* apply a layout to the rendered result. It is thus mostly used
* in rendering a partial view, or an AJAX response.
*
* @param string $view name of the view to be rendered. See {@link getViewFile} for details
* about how the view script is resolved.
* @param array $data data to be extracted into PHP variables and made available to the view script
* @param boolean $return whether the rendering result should be returned instead of being displayed to end users
* @param boolean $processOutput whether the rendering result should be postprocessed using {@link processOutput}.
* @return string the rendering result. Null if the rendering result is not required.
* @throws CException if the view does not exist
* @see getViewFile
* @see processOutput
* @see render
*/
public function renderPartial($view,$data=null,$return=false,$processOutput=false)


/**
* Sends existing file to a browser as a download using x-sendfile.
*
* X-Sendfile is a feature allowing a web application to redirect the request for a file to the webserver
* that in turn processes the request, this way eliminating the need to perform tasks like reading the file
* and sending it to the user. When dealing with a lot of files (or very big files) this can lead to a great
* increase in performance as the web application is allowed to terminate earlier while the webserver is
* handling the request.
*
* The request is sent to the server through a special non-standard HTTP-header.
* When the web server encounters the presence of such header it will discard all output and send the file
* specified by that header using web server internals including all optimizations like caching-headers.
*
* As this header directive is non-standard different directives exists for different web servers applications:
* <ul>
* <li>Apache: {@link http://tn123.org/mod_xsendfile X-Sendfile}</li>
* <li>Lighttpd v1.4: {@link http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file X-LIGHTTPD-send-file}</li>
* <li>Lighttpd v1.5: {@link http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file X-Sendfile}</li>
* <li>Nginx: {@link http://wiki.nginx.org/XSendfile X-Accel-Redirect}</li>
* <li>Cherokee: {@link http://www.cherokee-project.com/doc/other_goodies.html#x-sendfile X-Sendfile and X-Accel-Redirect}</li>
* </ul>
* So for this method to work the X-SENDFILE option/module should be enabled by the web server and
* a proper xHeader should be sent.
*
* <b>Note:</b>
* This option allows to download files that are not under web folders, and even files that are otherwise protected (deny from all) like .htaccess
*
* <b>Side effects</b>:
* If this option is disabled by the web server, when this method is called a download configuration dialog
* will open but the downloaded file will have 0 bytes.
*
* <b>Known issues</b>:
* There is a Bug with Internet Explorer 6, 7 and 8 when X-SENDFILE is used over an SSL connection, it will show
* an error message like this: "Internet Explorer was not able to open this Internet site. The requested site is either unavailable or cannot be found.".
* You can work around this problem by removing the <code>Pragma</code>-header.
//須要加載這個模塊
LoadModule xsendfile_module modules/mod_xsendfile.so
XSendFile on
XSendFilePath D:/

* <b>Example</b>:
* <pre>
* <?php
*    Yii::app()->request->xSendFile('/home/user/Pictures/picture1.jpg',array(
*        'saveName'=>'image1.jpg',
*        'mimeType'=>'image/jpeg',
*        'terminate'=>false,
*    ));
* ?>
 

* </pre>
* @param string $filePath file name with full path
* @param array $options additional options:
* <ul>
* <li>saveName: file name shown to the user, if not set real file name will be used</li>
* <li>mimeType: mime type of the file, if not set it will be guessed automatically based on the file name, if set to null no content-type header will be sent.</li>
* <li>xHeader: appropriate x-sendfile header, defaults to "X-Sendfile"</li>
* <li>terminate: whether to terminate the current application after calling this method, defaults to true</li>
* <li>forceDownload: specifies whether the file will be downloaded or shown inline, defaults to true. (Since version 1.1.9.)</li>
* <li>addHeaders: an array of additional http headers in header-value pairs (available since version 1.1.10)</li>
* </ul>
*/
public function xSendFile($filePath, $options=array())



CAction is the base class for all controller action classes. 
CAction provides a way to divide a complex controller into smaller actions in separate class files. 
Derived classes must implement run() which is invoked by controller when the action is requested.

 
CViewAction represents an action that displays a view according to a user-specified parameter.
By default, the view being displayed is specified via the view GET parameter. The name of the GET parameter can be customized via viewParam. If the user doesn't provide the GET parameter, the default view specified by defaultView will be displayed. 
Users specify a view in the format of path.to.view, which translates to the view name BasePath/path/to/view where BasePath is given by basePath. 

CForm represents a form object that contains form input specifications.

The main purpose of introducing the abstraction of form objects is to enhance the reusability of forms. In particular, we can divide a form in two parts: those that specify each individual form inputs, and those that decorate the form inputs. A CForm object represents the former part. It relies on the rendering process to accomplish form input decoration. Reusability is mainly achieved in the rendering process. That is, a rendering process can be reused to render different CForm objects. 

A form can be rendered in different ways. One can call the render method to get a quick form rendering without writing any HTML code; one can also override render to render the form in a different layout; and one can use an external view template to render each form element explicitly. In these ways, the render method can be applied to all kinds of forms and thus achieves maximum reusability; while the external view template keeps maximum flexibility in rendering complex forms. 

Form input specifications are organized in terms of a form element hierarchy. At the root of the hierarchy, it is the root CForm object. The root form object maintains its children in two collections: elements and buttons. The former contains non-button form elements (CFormStringElement, CFormInputElement and CForm); while the latter mainly contains button elements (CFormButtonElement). When a CForm object is embedded in the elements collection, it is called a sub-form which can have its own elements and buttons collections and thus form the whole form hierarchy. 

Sub-forms are mainly used to handle multiple models. For example, in a user registration form, we can have the root form to collect input for the user table while a sub-form to collect input for the profile table. Sub-form is also a good way to partition a lengthy form into shorter ones, even though all inputs may belong to the same model. 


$components=array(
'coreMessages'=>array(
'class'=>'CPhpMessageSource',
'language'=>'en_us',
'basePath'=>YII_PATH.DIRECTORY_SEPARATOR.'messages',
),
'db'=>array(
'class'=>'CDbConnection',
),
'messages'=>array(
'class'=>'CPhpMessageSource',
),
'errorHandler'=>array(
'class'=>'CErrorHandler',
),
'securityManager'=>array(
'class'=>'CSecurityManager',
),
'statePersister'=>array(
'class'=>'CStatePersister',
),
'urlManager'=>array(
'class'=>'CUrlManager',
),
'request'=>array(
'class'=>'CHttpRequest',
),
'format'=>array(
'class'=>'CFormatter',
),
)

$components=array(
'session'=>array(
'class'=>'CHttpSession',
),
'assetManager'=>array( 
'class'=>'CAssetManager',
),
'user'=>array(
'class'=>'CWebUser',
),
'themeManager'=>array(
'class'=>'CThemeManager',
),
'authManager'=>array(
'class'=>'CPhpAuthManager',
),
'clientScript'=>array(
'class'=>'CClientScript',
),
'widgetFactory'=>array(
'class'=>'CWidgetFactory',
),
);

<script>
jQuery.validator.addMethod('username',function(value, element, param) {
return false;
},'ni {0} ming zhi shu cuo le');

jQuery.validator.addMethod('cardNum',function(value,element,param){
return CardNumber.check(value,true);
},'請輸入正確的身份證號碼');

$('form').validate({
  keyup:false,
        rules: {
username : {
cardNum : true
}
}
})
</script>


jQuery.validator.addMethod('anoy',function(value,element,func){
return func;
});


$('form').validate({
rules:{
pass1 : {
anoy : function(){ console.log(arguments);return false;}
}
}
});

$(element).parentsUntil('table').find('input[name="pass2"]').val();

jQuery.validator.addClassRules('pas', {
        pass1: true 
    });


jQuery.validator.addMethod('username',function(value, element, param) {
return false;
},'ni {0} ming zhi shu cuo le');

jQuery.validator.addMethod('cardNum',function(value,element,param){
return CardNumber.check(value,true);
},'請輸入正確的身份證號碼');

jQuery.validator.addMethod('pass1',function(value,element,param){
return value == $(element).parentsUntil('table').find('input[name="pass2"]').val();
},'error');

jQuery.validator.addClassRules('pas', {
        pass1: true 
    });
$('form').validate({
rules:{
'pass1' : {
pass1 : true
}
}
});
if($(':input[name="isWrite"][checked]').val() == 1 )

A typical authentication process using CWebUser is as follows:
The user provides information needed for authentication.
An {@link IUserIdentity identity instance} is created with the user-provided information.
Call {@link IUserIdentity::authenticate} to check if the identity is valid.
If valid, call {@link CWebUser::login} to login the user, and Redirect the user browser to {@link returnUrl}.
If not valid, retrieve the error code or message from the identity instance and display it.


Yii::app()->user->setFlash('success', "Data1 saved!");
Yii::app()->user->setFlash('error', "Data2 failed!");
Yii::app()->user->setFlash('notice', "Data3 ignored.");
Display them in your view:

<?php
    foreach(Yii::app()->user->getFlashes() as $key => $message) {
        echo '<div class="flash-' . $key . '">' . $message . "</div>\n";
    }
?>
Setting flash messages 
A flash message is used in order to keep a message in session through one or several requests of the same user. By default, it is removed from session after it has been displayed to the user. Flash messages are usually used in combination with HTTP redirections, because in this case there is no view, so messages can only be displayed in the request that follows redirection.

www.ixuesi.com


CWebUser 和 CUserIdentity 的關係
CUserIdentity 經過用戶名和密碼驗證用戶,獲取用戶id,CWebUser可根據Id獲取用戶信息,保存在session中。
也可在CUserIdentity中獲取信息到stats中,而後傳遞到CWebUser中

CAccessControlFilter 內部也是經過調用user->checkAccess()來判斷權限
user裏邊經過CauthManager來提供checkAccess()方法。
能夠利用filter 和 User->checkAccess()來使用yii的權限系統。固然也能夠直接調用AuthManager來使用,這時須要手動傳遞User了。

能夠再model的自定義rule中使用addError($attribute,$value)來添加一個錯誤,必須使用adderror,返回false是不起做用的。

keepalive="true": To conserve battery power and cpu usage, Paper.js normally stops all animation events when the window is not focused. If you want it to keep playing animations, even if the window is in the background, set keepalive="true" in your canvas tag. And again for validation, data-paper-keepalive="true" works as well.

CController中已經定義了三個filter:filterAccessControl,filterAjaxOnly,filterPostOnly,filterAccessControl須要和accessRules配合使用,
public function filterAccessControl($filterChain)
{
$filter=new CAccessControlFilter;
$filter->setRules($this->accessRules());
$filter->filter($filterChain);
}
public function filters()
    {
        return array(
            'accessControl',
        );
    }
public function accessRules()
    {
        return array(
            array('deny',
                'actions'=>array('create', 'edit'),
                'users'=>array('?'),
            ),
            array('allow',
                'actions'=>array('delete'),
                'roles'=>array('admin'),
            ),
            array('deny',
                'actions'=>array('delete'),
                'users'=>array('*'),
            ),
        );
    }

Yii::import()註冊一個類路徑

module裏的一個函數 
public function init()
{
$this->setImport(array(
'application.modules.user.models.*',
'application.modules.user.components.*',
));
}

public function filters() {  
return array(  
'accessControl', //本地函數一個簡單的字符串,外部類要寫在數組中
array(
'COutputCache + list',
'duration'=>300,
),
);  
}

##python  
shutil — High-level file operationspython

相關文章
相關標籤/搜索