上次研究Yii框架寫到了要完成用戶登錄系統.此次接着上次的寫.php
參考官方權威指南和參考手冊,外加各類博客文章.歷盡千辛萬苦,數遍天上滴星星.完成了後臺用戶登陸.這裏用到了YII框架的前端
CUserIdentity類. -------實現基於用戶名和密碼的驗證.數據庫
CWebForm類 ---------登陸表單數組
CController類 ------控制器的基礎類cookie
CWebUser類 ------儲存用戶的持久身份信息session
第一步:分離用戶系統app
要想實現用戶登陸.先研究一下YII的登陸流程.YII框架提供和頗有用的登陸輔助類和用戶身份類供咱們使用.上次說到admin使用模塊來開發管理後臺.那麼要實現後臺與前臺的相對獨立.首先要實現先後臺兩套用戶系統.YII的CUserIdentity類是用來提供用戶身份相關的存儲,驗證等操做.這個類在默認的配置文件main.php裏面有配置.就是配置文件裏面components下面的user.查看手冊能夠看到這幾行配置就是配置的CUserIdentity的一個實例.之後能夠經過Yii::app()->user來訪問這個實例.調用其中的方法.可是我想要兩套用戶系統.一套用做網站的前臺登陸.一套用做管理的後臺登陸.那麼就要修改這個配置.用戶系統是基於CUserIdentity類.那麼若是我想要兩套用戶系統,就要有兩個CUserIdentity的實例.也能夠有兩個CUserIdentity的子類.這樣也可以實現用戶系統的分離.我把其中用做前臺登陸的類叫作WebUsers類.這個類放在網站根目錄下的components下面放置一個Webusers.php文件.裏面只寫明class WebUsers extends CWebUser{}就能夠了.當我之後想修改網站用戶的一些基礎屬性.只須要修改這個類就成了.另一個類我放在admin模塊下的components下面.同上面的同樣只寫明class AdminUsers extends CWebUser{}就能夠了.在最後我在main裏面配置一下.框架
修改原來user的聲明改爲如下的樣子yii
'components'=>array( 'user'=>array( 'class'=>'WebUsers', 'stateKeyPrefix'=>'user',//設置前臺session前綴 'allowAutoLogin'=>true, ), 'admin'=>array( // enable cookie-based authentication 'class'=>'AdminUsers', 'stateKeyPrefix'=>'admin',//設置後臺session前綴 'allowAutoLogin'=>false, 'loginUrl' =>array('/admin/adminuser/login'), ),
以前上文說過.這個配置數組是用來配置類的.也就是說我分別對前臺和後臺的兩個用於保存網站用戶的實例進行了配置.通過這樣的配置.我就可以經過Yii::app()->user訪問到網站用戶的相關屬性和調用相關的方法.而經過Yii::app()->admin來訪問網站後臺管理用戶的相關屬性,並調用相關的方法.網站
第二步:完成控制器.
分離完了用戶系統.就要寫控制器了.由於CMS系統須要驗證用戶身份.也就是說沒有正確的帳號密碼是不容許進行任何操做的.換個邏輯講就是說在模塊下的控制器的任何方法都應該在權限驗證經過的狀況下才能被執行.爲了可以實現這個目的.我寫了一個後臺控制器的基礎類,全部用做後臺操做的控制器都繼承自此控制器.這個控制器的名稱我給定義成了AdminController.它繼承自Ccontroller.我把這個類的文件存儲在components下面,這樣就會被模塊的init方法自動導入進來.我能夠經過手冊發如今Ccontroller裏面有一個方法叫作beforeAction().我只須要重寫這個方法.在全部action執行以前驗證用戶身份.若是用戶身份不合法.就直接引導到登陸頁面上去.這個是咱們的實現思想.
小插曲:驗證碼.
想作登陸,那麼驗證碼這個關鍵的東西是不可以少的.在YII的框架中有提供驗證碼.可是使用起來比較讓人費解.它說要實現驗證碼.咱們須要重寫控制器中的actions方法.完成一個繼承自CCaptchaAction的action而且要求這個繼承來的方法名字必須是captcha.這裏我沒有深刻的研究,參考yii框架自動生成的聯繫頁面上驗證碼的生成.我寫了驗證碼.固然.驗證碼能夠進行配置.只須要配置數組便可.
完成上述步驟後.個人後臺管理用到的基礎控制器就完成了.代碼是下面這個樣子的:
class AdminController extends CController { public $pageTitle="後臺管理"; /** * @var string the default layout for the controller view. Defaults to '//layouts/column1', * meaning using a single column layout. See 'protected/views/layouts/column1.php'. */ public $layout='application.modules.admin.views.layouts.admin'; /** * @var array context menu items. This property will be assigned to {@link CMenu::items}. */ public $menu=array(); /** * @var array the breadcrumbs of the current page. The value of this property will * be assigned to {@link CBreadcrumbs::links}. Please refer to {@link CBreadcrumbs::links} * for more details on how to specify this property. */ public $breadcrumbs=array(); public function actions(){ return array( 'captcha'=>array( 'class'=>'CCaptchaAction', 'backColor'=>0xFFFFFF, ),); } protected function beforeAction($action){ if(Yii::app()->admin->isGuest&&$action->getId()!='login'&&$action->getId()!='captcha'){ $this->redirect(Yii::app()->admin->loginUrl); } return parent::beforeAction($action); } }
說一下這個beforeAction 第一行.咱們判斷咱們以前聲明的後臺用戶體系中的當前用戶是否是來賓用戶.而且判斷當前的Action是否是爲login或者captcha,也就是當前是否是在登陸或者生成驗證碼.由於對於沒有登陸的用戶,若是不容許登陸操做和生成驗證碼操做就沒辦法完成登陸. 第二行.若是條件成立.也就是說當前的用戶沒有登陸.那麼咱們就調用控制器裏面的重定向方法,將訪問定向到咱們以前再用戶體系中聲明的loginUrl去.最後一行.若是咱們的用戶登陸了.那麼咱們就調用父類的這個方法.實際上父類的方法裏面是直接去執行action了.
好了,個人基礎控制器完成了,在這裏咱們定義了驗證碼,控制了用戶登陸.接下來我就要寫後臺用戶的第一個控制器了,用戶控制器.裏面要實現的方法大概有(還沒想好),用戶登陸,用戶基本信息獲取.用戶登出.顯示登陸後臺的首頁.再想到再添加.因而完成了第一個控制器.AdminUserController,具體代碼以下:
class AdminuserController extends AdminController { public function actionIndex() { $this->render('index'); } public function actionLogin() { $model=new AdminLoginForm; if(isset($_POST['AdminLoginForm'])) { $model->attributes=$_POST['AdminLoginForm'];//將用戶輸入塊賦值給AdminLoginForm的實例 if($r = $model->validate()) { // form inputs are valid, do something here $this->actionIndex();//若登錄成功則顯示首頁 //$this->renderPartial('login',array('model'=>$model)); return; } } $this->renderPartial('login',array('model'=>$model)); } public function actionLogout(){ Yii::app()->admin->logout(); $this->actionLogin(); } }
代碼貼出來了,先彆着急看.這裏面的actionLogin先不用去理解.我定義了三個動做.分別是login,logout,index,還有一個從父類繼承過來的captcha.分別用來登陸,登出,顯示首頁和顯示驗證碼.
第三步,創建模型.
yii有很好的抽象結構.將數據抽象成兩種模式,一種是用做表單的,這樣的數據不被持久化保存.因而有表單模型.另一種是用來抽象數據庫的模型.這種數據會被保存到數據庫裏面.第二種模型裏面封裝了數據庫的增刪改查的方法.官方叫作CActiveRecord,咱們能夠理解爲第二種模型爲數據模型.第一種模型爲表單模型.
表單模型,故名思議就是對錶單的一個抽象.這個模型裏面定義了表單的各個屬性和字段.定義了表單的驗證規則.等等.當渲染一個表單的時候其實是生成了一個表單模型的實例.當咱們填寫一個表單並提交的時候實際上完成的操做應該是把用戶輸入的數據用來填充這個模型.並保證用戶填充的數據可以知足這裏的驗證規則.也就是說咱們對錶單的操做實際上就是對這個表單模型實例的操做.按照Yii框架的設計原則,咱們的表單模型都應該集成自表單模型的基類.而數據模型都應該集成自數據模型的基類.這兩個基類分別是 CFormModel,CActiveRecord.
拿咱們的登陸表單來講.咱們的登陸表單繼承自CFormModel,裏面有幾個屬性.分別是用戶名.密碼.驗證碼.有一個方法,這個方法經過提交表單來收集用戶輸入並用已經定義的規則來比對用戶輸入.若是知足,就將用戶輸入賦值給表單模型實例的相應屬性上,若是不知足就寫入錯誤信息.(這個方法的名字叫作validate,是從CFormModel繼承過來的//是用來驗證的.)
數據模型.對應數據表的模型.能夠理解爲咱們把數據庫裏面某一張表抽象爲一個模型.這個表裏面的每一行就是這個模型的一個實例.當咱們執行這個數據模型的增刪改查操做的時候,實際上就是對這個表的操做.而轉換成面向對象的思想.咱們就是在操做着數據對象.還拿咱們的後臺管理用戶系統來講.咱們須要實現對於後臺用戶表的抽象.因而咱們有了一個後臺用戶表的數據模型類.繼承自CActiveRecord.(能夠用GII生成).我是用Gii生成的.
個人登錄表單模型以下:
<?php /** * ContactForm class. * ContactForm is the data structure for keeping * contact form data. It is used by the 'contact' action of 'SiteController'. */ class AdminLoginForm extends CFormModel { public $username; public $password; public $verifyCode;//驗證碼 private $_adminUserIdentity;//這個變量其實是基於用戶名和密碼驗證的類的實例 /** * Declares the validation rules. */ public function rules() { return array( array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements()), //當沒有開啓GD庫拓展的時候容許驗證碼爲空 array('username, password','required'), //用戶名密碼不能爲空 // verifyCode needs to be entered correctly array('password', 'check_user'),//定義password須要使用該模型中的check_user方法來驗證. ); } public function attributeLabels() { return array( 'username'=>'用戶名', 'password'=>'密碼', 'verifyCode'=>'驗證碼', ); } public function check_user($attribute,$params) { $this->_adminUserIdentity = new AdminUserIdentity($this->username,$this->password); $res = $this->_adminUserIdentity->authenticate();
//調用authenticate方法來驗證用戶提交的信息與數據庫裏面存儲的信息是否一致. if($res == true){ Yii::app()->admin->login($this->_adminUserIdentity); return true; }else{ return false; } } }
第四步,理清邏輯.
先看看咱們手裏有什麼,
有AdminuserController控制器.
有在main.php裏面聲明的admin用戶體系,其實是CWebUser的一個實例.
基於用戶密碼來驗證的AdminUserIdentity.
有loginform的表單模型.(能夠用gii來創建)
有admin_user數據表的數據模型.(能夠用gii來創建)
固然,咱們還要有一張存儲用戶數據的數據表.這個要本身在數據庫裏面創建了.這個就不寫出來了.
咱們須要一個可以渲染管理後臺首頁的視圖.可能還要寫一些layout.
還少什麼:
少一個登陸界面的視圖.
那就來創建一個登陸界面的視圖.在yii權威指南里面能夠找到使用表單那個章節.裏面介紹了表單助手類的使用.這裏我就再也不說了.想要在前端展現驗證碼.能夠參考例子程序.實際上<?php $this->widget('CCaptcha'); ?>就可以完成驗證碼的圖片輸出.this指的是控制器的實例,而widget值得是渲染一個掛件.當傳遞進入的參數爲CCaptcha時就可以直接生成一個驗證碼.
上面提到的還有個人後臺管理用戶的用戶體系文件,放上來以下:
<?php class AdminUserIdentity extends CUserIdentity { private $_id; public function authenticate() { $record = AdminUser::model()->findByAttributes(array('username'=>$this->username)); if($record===null) { $this->errorMessage = '用戶名不存在'; $this->errorCode=true; } else if($record->password!==md5($this->password)) { $this->errorMessage = '密碼不正確'; $this->errorCode=true; } else { $this->_id=$record->id; $this->setState('title', $record->username); $this->errorCode=false; } return !$this->errorCode; } public function getId() { return $this->_id; } }
到如今已經準備的差很少了,簡單畫了一下登陸的流程.以下:
寫到這裏,就完成了基本的登陸流程.當有用戶來訪問的時候咱們就能夠實現必須強制登陸.其實我上面所說的東西,在官方的文檔上也有不少描述,能夠多啃啃手冊.
上次我作了一個類比,把YII比做一個汽車工廠.此次.咱們能夠把後臺這個模塊比做一個大的生產車間.那麼咱們在main裏面聲明的AdminUsers類的實例就至關於一個管理這個生產車間的管理員,負責監管人員進入生產車間和離開生產車間,而AdminUserIdentity 這個基於用戶名密碼的驗證類就至關於一個基於用戶名密碼的開門器.若是你沒有相應的用戶名密碼.也不可以進入車間進行工做.
就寫到這裏.接下來要實現後臺用戶的管理.增刪改查功能.若是你耐心的看完了這篇博文並以爲有收貨的話,請幫忙贊一下.