用户
 找回密码
 入住 CI 中国社区
搜索
查看: 6810|回复: 2
收起左侧

[中级] CodeIgniter 和 Doctrine 从零开始 第四天 用户登录 中

[复制链接]
发表于 2010-1-26 09:06:17 | 显示全部楼层 |阅读模式
更好的解决方法现行的方法有什么问题?

我喜欢把所有认证代码放到控制器里,这样不能很好的重用代码

它应该是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变量包含已登录userUser 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()方法返回它。

我们只是学习了如何使用codeignitersession。这不是很复杂。你所要做的就是加载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类是全局作用域的,因为Doctrinesystem/application/plugins/doctrine_pi.php中已经设置自动加载

发表于 2010-7-15 11:22:47 | 显示全部楼层
我头晕呀
发表于 2011-7-27 09:44:09 | 显示全部楼层
好贴。。。跟rails有点相似。。

本版积分规则