ThinkPHP3.2.3的钩子方法使用
在Library/Think/Model.class.php 这个基础model类中在添加add,修改save,和删除delete 时各自回调用两个回调函数. 使用这两个回调函数会给开发带来方便.
1 . add()方法回调函数
// 插入数据前的回调方法
protected function _before_insert(&$data,$options) {}
// 插入成功后的回调方法
protected function _after_insert($data,$options) {}
2 . save()方法回调函数
// 更新数据前的回调方法
protected function _before_update(&$data,$options) {}
// 更新成功后的回调方法
protected function _after_update($data,$options) {}
3 .delete()方法回调方法
// 删除数据前的回调方法
protected function _before_delete($options) {}
// 删除成功后的回调方法
protected function _after_delete($data,$options) {}
4.使用场景是什么?
1 ._before_insert()
//添加前
protected function _before_insert(&$data, $option)
{
// 添加管理员之前先加密
$data['password'] = md5($data['password'] . C('MD5_KEY'));
}
上面就是我们在插入数据库之前,对password字段进行md5加密.格式必须是 $data[‘字段名’] . 这个字段名就是你要插入到数据表中的字段.
2 ._after_insert()
// 添加后
protected function _after_insert($data, $option)
{
// 处理管理员所在角色
$roleId = I('post.role_id');
if($roleId)
{
$raModel = M('RoleAdmin');
foreach ($roleId as $k => $v)
{
$raModel->add(array(
'admin_id' => $data['id'], // 添加之后的管理员的ID
'role_id' => $v,
));
}
}
}
上面是定义在管理员模型中的方法 . 它的html页面是添加管理员的同时给管理员分配角色 . 所以收集到的表单中有 有admin表的信息以及role_id . 上面代码实现的是 向 admin_role 这个中间表中插入数据, 此时role_id 可以通过表单提交收集到, 但是缺少admin_id .这个admin_id 就是 $data[‘admin表的主键’]
3 ._before_update()
// 修改前
protected function _before_update(&$data, $option)
{
// 处理管理员所在角色
// 先删除中间表中原来的数据
$raModel = M('RoleAdmin');
$raModel->where(array(
'admin_id' => $option['where']['id'],
))->delete();
// 重新把新选择的添加一遍
$roleId = I('post.role_id');
if($roleId)
{
foreach ($roleId as $k => $v)
{
$raModel->add(array(
'admin_id' => $option['where']['id'], // 添加之后的管理员的ID
'role_id' => $v,
));
}
}
// 判断如果密码为空就不修改密码【从表单数组中把这一项删除】
if(empty($data['password']))
unset($data['password']);
else
$data['password'] = md5($data['password'] . C('MD5_KEY'));
}
这里有两点.第一:如果你需要在修改前对数据进行处理.格式 仍然是 $data[‘字段’]
$data['password'] = md5($data['password'] . C('MD5_KEY'));
第二:如果你要先中间表中插入数据,缺少的admin_id 此时是$options[‘where’][‘主键’]
4 ._after_update()
$options[‘where’][‘主键’]
5 . _before_delete()
// 删除前
protected function _before_delete($option)
{
if($option['where']['id'] == 1)
{
$this->error = '超级管理员不能被删除!';
return FALSE;
}
// 把中间表中对应的数据也删除
$raModel = M('RoleAdmin');
$raModel->where(array(
'admin_id' => array('eq', $option['where']['id']),
))->delete();
}
$option[‘where’][‘主键’]
总结:
1 . 在insert 中如果想要获得主键,就是
data[′主键′],例如
data[‘id’]
2 .在update,delete 想要获得主键就是$options[‘where’][‘主键’]
如果在这些回调方法中出现错误,怎们处理
protected function _before_delete($option)
{
if($option['where']['id'] == 1)
{
$this->error = '超级管理员不能被删除!';
return FALSE;
}
将错误赋值给 模型中的error变量, 同时返回false. 这样这个错误,就可以用模型的getError()方法获取了.Model.class.php中的getError()方法
/**
* 返回模型的错误信息
* @access public
* @return string
*/
public function getError(){
return $this->error;
}
5.查看Model.class.php中的源码.
add()方法
public function add($data='',$options=array(),$replace=false) {
if(empty($data)) {
// 没有传递数据,获取当前数据对象的值
if(!empty($this->data)) {
$data = $this->data;
// 重置数据
$this->data = array();
}else{
$this->error = L('_DATA_TYPE_INVALID_');
return false;
}
}
// 分析表达式
$options = $this->_parseOptions($options);
// 数据处理
$data = $this->_facade($data);
A处: if(false === $this->_before_insert($data,$options)) {
return false;
}
// 写入数据到数据库
$result = $this->db->insert($data,$options,$replace);
if(false !== $result ) {
$insertId = $this->getLastInsID();
if($insertId) {
// 自增主键返回插入ID
$data[$this->getPk()] = $insertId;
B处: $this->_after_insert($data,$options);
return $insertId;
}
$this->_after_insert($data,$options);
}
return $result;
}
上面A处时调用_before_insert. 这里是判断是否是false, 如果是false ,add()方法也返回false . 所以这就就是我们在_before_insert中出现错误的时候要返回false的原因
B处前一行代码,可以看出在插入数据后,将最新的主键保存到了$data[‘主键’]中.
save()方法:
public function save($data='',$options=array()) {
if(empty($data)) {
// 没有传递数据,获取当前数据对象的值
if(!empty($this->data)) {
$data = $this->data;
// 重置数据
$this->data = array();
}else{
$this->error = L('_DATA_TYPE_INVALID_');
return false;
}
}
// 数据处理
$data = $this->_facade($data);
// 分析表达式
$options = $this->_parseOptions($options);
$pk = $this->getPk();
if(!isset($options['where']) ) {
// 如果存在主键数据 则自动作为更新条件
if(isset($data[$pk])) {
A处: $where[$pk] = $data[$pk];
$options['where'] = $where;
unset($data[$pk]);
}else{
// 如果没有任何更新条件则不执行
$this->error = L('_OPERATION_WRONG_');
return false;
}
}
B处: if(is_array($options['where']) && isset($options['where'][$pk])){
$pkValue = $options['where'][$pk];
}
if(false === $this->_before_update($data,$options)) {
return false;
}
$result = $this->db->update($data,$options);
if(false !== $result) {
if(isset($pkValue)) $data[$pk] = $pkValue;
$this->_after_update($data,$options);
}
return $result;
}
如果你使用了连贯操作,直接到B处.
如果没有使用连贯操作,从A处,将主键保存到
option[′where′][′主键′],同时删除了
data[‘主键’]