在TP中,我们只要在模型类中定义一个
protected $_map = array(
'name' =>'username', // 把表单中name映射到数据表的username字段
'mail' =>'email', // 把表单中的mail映射到数据表的email字段
);
在模型收集表单数据时会自动将值同时映射到username字段上。
好处是避免数据库字段直接暴露。
但很遗憾,我在学习Yii过程中没有找到类似的机制,而Yii的类库很多,我又不敢贸然自己扩展,总觉得在某个角落里有某个类可能已经提供了解决方案,怕自己做重复无意义之举。
经过一系列的思想斗争,楼主还是决定自己动手啦。。
方法很简单,请先看代码:
<?php
class CustomModel extends CActiveRecord {
//定义所需要收集的属性
public $username;
public $email;
public $passwd;
public $password;
public $password1;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return '{{custom}}';
}
public function rules(){
return array(
array("username,password,email,password1","safe")
);
}
//字段映射配置
protected $_alias_ = array(
"passwd" => "password"
);
//通过引用传递处理映射
protected function afterConstruct(){
parent::afterConstruct();
//字段映射处理
if(!empty($this->_alias_)){
foreach($this->_alias_ as $a => $b){
if(property_exists($this,$a) && property_exists($this,$b)){
$this->$a = &$this->$b;
}
}
}
}
}
<?php defined("APP_NAME") or exit;?>
<form action="" method="post">
<table>
<tr>
<th>用户名:</th>
<td><input type="text" name="username" placeholder="请设置您的账号名" value=""/></td>
</tr>
<tr>
<th>邮箱:</th>
<td><input type="email" name="email" placeholder="example@website" value=""/></td>
</tr>
<tr>
<th>密码:</th>
<td><input type="password" name="password" value=""/></td>
</tr>
<tr>
<th>重复密码:</th>
<td><input type="password" name="password1" value=""/></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交"/></td>
</tr>
</table>
</form>
所以我在模型类中定义了1个方法:
afterConstruct()
一个属性
protected $_alias_
我们在$_alias_这个属性里面定义映射,比如我定义了 "passwd"=>"password"的映射。
afterConstruct()这个方法是在你实例化模型类之后执行的,可以看成在 $model = new CustomModel()的时候触发,这里面主要做了一个工作,就是检测$_alias_有没有定义映射,如果有的话,我们使用php的引用传递特性来使两个字段指向同一个值。
最后,为了可以全局使用,建议在components/目录下建立一个 CommonModel类,将afterConstruct()方法放在这个类里,其他模型继承这个类就可以了,这样只要在各自的模型中定义_alias_属性即可。
/////////基于事件的处理方法
<?php
class CommonAR extends CActiveRecord{
function init(){
$this->onAfterConstruct = array($this,"autoMap");
}
//字段映射配置
protected $_alias_ = array(
);
function autoMap($event){
//字段映射处理
if(!empty($this->_alias_)){
foreach($this->_alias_ as $a => $b){
if(property_exists($this,$a) && property_exists($this,$b)){
$this->$a = &$this->$b;
}
}
}
}
}
$this->onAfterConstruct = array($this,"autoMap");
对应的事件方法就是类里面的autoMap()
然后创建具体模型的时候继承CommonAR类,定义$_alias_即可。