更好的解决方法现行的方法有什么问题? 我喜欢把所有认证代码放到控制器里,这样不能很好的重用代码 它应该是User model的一部分,因为直接关系到User model 存放User 记录的变量$u ,不是全局变量,其它控制器无法访问它。 我们不想用session保存user object,因为Doctrine model含有很多的数据,可能会使session迅速膨胀。我们只会在session中存储user_id 单例模式它是十分流行的一种设计模式,我会告诉你如何使用它。在新的类里,我们将设计更好的验证,并且使User model可以在我们程序的全局作用域里使用 当前User的单例模式首先建立框架: 创建:system/application/models/current_user.php <?php class Current_User {
private static $user;
private function __construct() {}
public static function user() {
if(!isset(self:user)) {
// 把User record 放入 $this->user
// ...
}
return self:user;
}
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
} 解读代码: l
为什么这个类叫Current_User,因为这个静态类总会返回一个当前已经登录用户的类实例。 l
这个类不是继承自Doctrine_Record,因为我们没有真正建立一个Doctrine model l
$user变量包含已登录user的User object。我们可以这样访问它:Current_User::user(),这是调用类的静态方法的语法。 l
我们不会实例化Curren_User类,所以构造函数为private l
我们也不会允许克隆这个类,所以__clone()函数触发一个错误。 现在我要补充一些代码,使他产生作用。 编辑 system/application/models/current_user.php <?php class Current_User {
private static $user;
private function __construct() {}
public static function user() {
if(!isset(self:user)) {//检查user 对象是否已经存在,如果不存在
$CI =& get_instance();
$CI->load->library('session');
if (!$user_id = $CI->session->userdata('user_id')) {
return FALSE;
}
if (!$u = Doctrine::getTable('User')->find($user_id)) {
return FALSE;
}
self:user = $u;//user对象保存到静态变量$user
}
return self:user;
}
public static function login($username, $password) {
// 得到 User object 从 username
if ($u = Doctrine::getTable('User')->findOneByUsername($username)) {
// 这个变异 (加密) 输入的password
$u_input = new User();
$u_input->password = $password;
// password匹配(加密过的密码)
if ($u->password == $u_input->password) {
unset($u_input);
$CI =& get_instance();
$CI->load->library('session');
$CI->session->set_userdata('user_id',$u->id);
self:user = $u;
return TRUE;
}
unset($u_input);
}
// 登录失败
return FALSE;
}
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
} 先看看user()方法。 使用方法是Current::user(),它返回已登录用户的User 对象。 现在,当我们调用Current_User::user(),我们可以得到User对象在一个全局变量中,如果返回false,说明用户没有登录。 再来看看login()方法: 我从login控制器复制了大部分代码,是复制的authenticate()方法的代码。 一旦用户登录进来,静态变量$user被设置,以后可以用user()方法返回它。 我们只是学习了如何使用codeigniter的session。这不是很复杂。你所要做的就是加载library,你可以用userdata()和set_userdata()方法读取和设置变量。 现在我们只需调用静态方法:Current_User::login($username,$password),他会完成登录验证的工作的。 我希望这不是很复杂,我相信你很快就会明白为什么我们要这样做了。 简化登录控制器编辑:system/application/controllers/login.php 只要编辑authenticate()函数: <?php class Login extends Controller {
// ...
public function authenticate() {
return Current_User::login($this->input->post('username'),$this->input->post('password'));
}
} 看看现在是多么的简单。 一旦用户登录,可以在User对象中检索登录用户:在应用程序的任何地方,简单的调用Current_User::user()即可。 请注意,我们不会用$this->load->model(‘Current_User’)方式调用。Current_User类是全局作用域的,因为Doctrine在system/application/plugins/doctrine_pi.php中已经设置自动加载 |