裏面水很深,還有很多不知道的特性,今天列舉一二,以後慢慢補充
1,對象轉數組
$model = new ActiveRecord();
$model.toArray();
由於ActiveRecord不是簡單數組,不能直接json_encode,否則信息不完整。
解決辦法:$model.toArray();這樣就變爲簡單數組了,可以進行json_encode了。
2,通過名字或其他字段直接獲取ActiveRecord的id。
$nIdcId = idc_info::model()->find('name like :name',array(':name'=>"%".$strIdcName."%"))->id;
我以前經常使用的辦法是(現在發現很土):
$idc = Idc::model()->find("...");
$id = $idc->id;
3,對model的理解
$accModel = call_user_func(array(ActiveRecordName, 'model'));
$model = $accModel->findByPk($id);
4. YII 返回數組方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 重寫findALL方法 * @params $condition 查詢條件,$params 參數,$return_array 是否返回數組 * * return 根據條件返回結果類型 */ public function findAll( $condition = '' , $params = array (), $return_array =false) { $result = CActiveRecord::findAll( $condition , $params ); if ( $return_array ) { $result = array_map (create_function( '$record' , 'return $record->attributes;' ), $this ->findAll( $condition , $params )); } return $result ; } |
在YII框架的使用過程中,我們可以使用foreach直接遍歷findAll等方法返回的對象的屬性
爲什麼呢?其實這與CModel實現的接口相關,接下來我們看下其實現的整個過程
對於一個我們定義的model,它會繼承虛類CActiveRecord,CActiveRecord類繼承於CModel,如下所示:
1 2 3 4
class special extends CActiveRecord { } abstract class CActiveRecord extends CModel{ }
最關鍵的地方是CModel類實現了IteratorAggregate接口。
而在CModel類中實現的getIterator方法返回的是這個model的所有屬性,使用的迭代器是Yii框架實現的CMapIterator,而CMapIterator實現了Iterator接口
1 2 3 4 5 6 7 8 9 10
public function getIterator() { $attributes=$this->getAttributes(); return new CMapIterator($attributes); }
這些就使得我們可以使用foreach直接遍歷findAll等方法返回的對象
關於此迭代器可以參看之前寫的關於迭代器的文章:
PHP源碼閱讀筆記二十四 :iterator實現中當值爲flase時無法完成迭代的原因分析
關於IteratorAggregate接口請移步
http://cn.php.net/manual/en/class.iteratoraggregate.php
關於Iterator接口請移步
http://cn.php.net/manual/en/class.iterator.php
同樣的道理,
因爲CModel實現了ArrayAccess接口,所以可以直接訪問以數組的方式訪問
關於ArrayAccess接口請移步
http://cn.php.net/manual/en/class.arrayaccess.php
關於Yii框架中不能直接給模型的attributes賦值的解決辦法
May 10th, 2013 by wangLeave a reply »先看一下源代碼:
01 |
$menuId =
isset( $_GET [ 'mId' ])
? $_GET [ 'mId' ]
: 0; |
02 |
if ( $menuId )
{ |
03 |
$menu =
MenuTree::model()->findByPk( $menuId ); |
04 |
if (isset( $_POST [ 'MenuTree' ])){ |
05 |
var_dump( $menu ->attributes); //在這裏跟蹤輸出的數據正常,跟表單中填寫的一致 |
06 |
$menu ->attributes
= $_POST [ 'MenuTree' ]; //對attributes進行賦值 |
07 |
var_dump( $menu ->attributes); //輸出$menu模型中的attributes,不正常,結果並不是POST接收到的值,而是數據庫原有的值 |
08 |
if ( $menu ->save()){ |
09 |
Yii::app()->user->setFlash( 'success' , "恭喜您,修改成功,請繼續!" ); |
10 |
$this ->redirect(Yii::app()->createUrl( 'menu/contentEdit' , array ( 'mId' => $menuId ))); |
11 |
} else { |
12 |
throw new CException( "修改失敗!" ); |
13 |
} |
14 |
} |
15 |
$this ->render( "contentEdit" , array ( 'menu' => $menu )); |
16 |
} else { |
17 |
throw new CHttpException( '404' ); |
18 |
} |
1 |
這是一個頁面的action代碼,看代碼中的註釋可以看到出現的錯誤,死活不接受POST的賦值,試過使用setAttributes函數也一樣不接受,輸出的還是原數據庫的值,但是用updateByPk操作就可以,跟蹤了一下setAttributes函數,發現函數定義如下: |
01 |
<pre> public function setAttributes( $values , $safeOnly =true) |
02 |
{ |
03 |
if (! is_array ( $values )) |
04 |
return ; |
05 |
$attributes = array_flip ( $safeOnly ? $this ->getSafeAttributeNames()
: $this ->attributeNames()); |
06 |
foreach ( $values as $name => $value ) |
07 |
{ |
08 |
if (isset( $attributes [ $name ])) |
09 |
$this -> $name = $value ; |
10 |
else if ( $safeOnly ) |
11 |
$this ->onUnsafeAttribute( $name , $value ); |
12 |
} |
13 |
}</pre> |
14 |
<pre></pre> |
15 |
<pre>分析setAttributes函數代碼可以看到,在對attributes賦值時進行的安全檢查,所以想到原因可能出現模型的rules沒有對那幾個表單中修改的字段設置爲安全,找到原因,解決方案就出來了,在model的rules中,把想要修改的字段的屬性置爲安全即可。</pre> |
16 |
<pre></pre> |
17 |
<pre><pre class = "brush:php" > public function rules() |
18 |
{ |
19 |
//
NOTE: you should only define rules for those attributes that |
20 |
//
will receive user inputs. |
21 |
return array ( |
22 |
//
more code... |
23 |
array ( 'field1
, field2 ,field3' , 'safe' ), //Modify
the fields in here |
24 |
//
more code... |
25 |
); |
26 |
}</pre> |
27 |
</pre> |