剖析ECMALL的登陸機制

在ecmall.php文件中實例化控制器類,每個控制器類,必須繼承(extends)upload\admin\app\backend.base.php文件。在繼承中調用方法是誰先被繼承誰的方法被先調用。php

以default爲例,首先在公共入口文件index.php文件中包含eccore/ecmall.php文件,調用startup方法並把includes/global.lib.php,includes/libraries/time.lib.php,includes/ecapp.base.php,includes/plugin.base.php,app/backend.base.php,以數據方式傳遞。在ECMAall類中的startup()方法中包含了eccore/controller/app.base.php和eccore/model/model.base.php文件。html

得到控制器默認爲[upload\admin\app\default.app.php文件,並繼承BackendApp(app/backend.base.php)類,並繼承ECBaseApp(includes/ecapp.base.ph)類,並繼承BaseApp(eccore/controller/app.base.php),並繼承Object(eccore/ecmall.php)]。而後調用ECBaseApp中的do_action()方法在調用其實父類BaseApp中的do_action()並判斷$act(index)方法在默認控制器中是否存在,若是存在並符合條件,調用本對像是最先繼承文件(app/backend.base.php)他中的_run_action()方法。數組

01 /**
02  *    後臺的須要權限驗證機制
03  *
04  *    @author    Garbin
05  *    @return    void
06  */
07 function _run_action()
08 {
09     /* 先判斷是否登陸 */
10     if (!$this->visitor->has_login)
11     {
12         $this->login();
13  
14         return;
15     }
16  
17     /* 登陸後判斷是否有權限 */
18     if (!$this->visitor->i_can('do_action'$this->visitor->get('privs')))
19     {
20         $this->show_warning('no_permission');
21  
22         return;
23     }
24  
25     /* 運行 */
26     parent::_run_action();
27 }

在此要判斷當前用戶是否登陸。緩存

若是沒有登陸,調用(app/backend.base.php)他中的login()方法。app

01 function login()
02 {
03     if ($this->visitor->has_login)
04     {
05         $this->show_warning('has_login');
06  
07         return;
08     }
09     if (!IS_POST)
10     {
11         if (Conf::get('captcha_status.backend'))
12         {
13             $this->assign('captcha', 1);
14         }
15         $this->display('login.html');
16     }
17     else
18     {
19         if (Conf::get('captcha_status.backend') && base64_decode($_SESSION['captcha']) !=strtolower($_POST['captcha']))
20         {
21             $this->show_warning('captcha_faild');
22  
23             return;
24         }
25  
26         $user_name = trim($_POST['user_name']);
27         $password  $_POST['password'];
28  
29         $ms =& ms();
30         $user_id $ms->user->auth($user_name$password);
31         if (!$user_id)
32         {
33             /* 未經過驗證,提示錯誤信息 */
34             $this->show_warning($ms->user->get_error());
35  
36             return;
37         }
38  
39         /* 經過驗證,執行登錄操做 */
40         if (!$this->_do_login($user_id))
41         {
42             return;
43         }
44  
45         $this->show_message('login_successed',
46             'go_to_admin''index.php');
47     }
48 }

而後調用includes/ecapp.base.php文件中的display()方法加載頁面模板,在加載過程當中須要給視圖傳遞變量,調用eccore/controller/app.base.php中的assign()方法,在這個方法中還須要調用eccore/controller/app.base.php中的_init_view()方法,在這個過程當中很重要由於他要引用返回eccore/ecmall.php文件中的& v()方法所引用的變量(引用eccore/view/template.php)文件,相似於加載,而後在eccore/controller/app.base.php中的assign()方法調用(eccore/view/template.php)文件assign()方法,以,鍵·值,形式賦值給_var數組中。dom

display()函數:async

01 function display($f)
02 {
03     if ($this->_hook('on_display'array('display_file' => & $f)))
04     {
05         return;
06     }
07     $this->assign('site_url', SITE_URL);
08     $this->assign('ecmall_version', VERSION);
09     $this->assign('random_number', rand());
10  
11     /* 語言項 */
12     $this->assign('lang', Lang::get());
13  
14     /* 用戶信息 */
15     $this->assign('visitor', isset($this->visitor) ? $this->visitor->info : array());
16  
17     /* 新消息 */
18     $this->assign('new_message', isset($this->visitor) ? $this->_get_new_message() : '');
19     $this->assign('charset', CHARSET);
20     $this->assign('price_format', Conf::get('price_format'));
21     $this->assign('async_sendmail'$this->_async_sendmail());
22     $this->_assign_query_info();
23  
24     parent::display($f);
25  
26     if ($this->_hook('end_display'array('display_file' => & $f)))
27     {
28         return;
29     }
30 }

assign()函數:函數

01 /**
02  *    給視圖傳遞變量
03  *
04  *    @author    Garbin
05  *    @param     string $k
06  *    @param     mixed  $v
07  *    @return    void
08  */
09 function assign($k$v = null)
10 {
11     $this->_init_view();
12     if (is_array($k))
13     {
14         $args  = func_get_args();
15         foreach ($args as $arg)     //遍歷參數
16         {
17             foreach ($arg as $key => $value)    //遍歷數據並傳給視圖
18             {
19                 $this->_view->assign($key$value);
20             }
21         }
22     }
23     else
24     {
25         $this->_view->assign($k$v);
26     }
27 }

_init_view()函數:post

01 /**
02  *    初始化視圖鏈接
03  *
04  *    @author    Garbin
05  *    @param    none
06  *    @return    void
07  */
08 function _init_view()
09 {
10     if ($this->_view === null)
11     {
12         $this->_view =& v();
13         $this->_config_view();  //配置
14     }
15 }

在includes/ecapp.base.php文件中的display()中調用其父類eccore/controller/app.base.php中的display()方法,在display()方法中引用變量調用(eccore/view/template.php)文件中的display()方法,在display()方法中首先要判斷當前的頁面文件(upload\admin\templates)是否被修改若是有被修改從新緩存(upload\temp\compiled\admin),在模板緩存的時候首先要用strpos()方法判斷編碼頭部(\xEF\xBB\xBF)是否出現過,若是出如今用咱們最經常使用的str_replace()方法把其替換爲空。this

在頁面提交中用到define('IS_POST', (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST'))來判斷是否提交,由於在頁面提交的時候,$_SERVER['REQUEST_METHOD']默認爲GET。

在登陸頁面中用method="post"方法提交表單因此獲得IS_POST定義值爲TRUE,進入到執行SQL語句中,判斷是否登陸成功。

在這個過程當中要引用includes/global.lib.php文件中的&ms()方法(此方法中包含/includes/passport.base.php,/includes/passports/' . MEMBER_TYPE . '.passport.php,MEMBER_TYPE在data/config.inc.php中定義默認爲default),把變量值地址引用到/includes/passports/default.passport.php文件中DefaultPassport類,DefaultPassport(/includes/passports/default.passport.ph)繼承了BasePassport(/includes/passport.base.php)

01 /**
02  *    鏈接會員系統
03  *
04  *    @author    Garbin
05  *    @return    Passport 會員系統鏈接接口
06  */
07 function &ms()
08 {
09     static $ms = null;
10     if ($ms === null)
11     {
12         include(ROOT_PATH . '/includes/passport.base.php');
13         include(ROOT_PATH . '/includes/passports/' . MEMBER_TYPE . '.passport.php');
14         $class_name  = ucfirst(MEMBER_TYPE) . 'Passport';
15         $ms new $class_name();
16     }
17  
18     return $ms;
19 }

在這個過程當中,把若干類實例化,因此調用auth(&username,&password)判斷用戶是否是存在正確,若是正確得到用戶ID執行登錄操做調用_do_login方法,在這裏咱們的回到剛加載文件時候的初始化中由於在includes/ecapp.base.php文件初始化的時候執行了$this->_init_visitor();方法引用了AdminVisitor他類並繼承了BaseVisitor類,因此能夠在_do_login()方法中應用$this->visitor->assign()方法,其實就是BaseVisitor類中的

1 function assign($user_info)
2 {
3     $_SESSION[$this->_info_key]   =   $user_info;
4 }

這樣就把用戶信息用SESSION保存,在執行操做的時候就能夠對$this->has_login進行改變了。

好了這就是登陸了。

其實他應用到"引用"和"繼承"比較多因此會讓初學者都感受到很亂,沒有頭緒。引用就是不一樣的名字訪問同一個變量內容,引用做爲函數參數能夠避免參數對象的額外拷貝。

若是程序比較大,引用同一個對象的變量比較多,而且但願用完該對象後手工清除它,我的建議用 "&" 方式,而後用$var=null的方式清除.另外, php5中對於大數組的傳遞,建議用 "&" 方式, 畢竟節省內存空間使用。

01 function qev(&$array)
02 {
03      Var_export($array);
04 }
05  
06 $array_qev array(
07 '1'=>'a','2'=>'b'
08 )
09  
10 Qev($array_qev);

繼承其實結果就是爲增長代碼的可重用性,也就是你定義一個方法若是他有必定的共性能夠被多個新增長的效果所調用。

若是登陸,在(app/backend.base.php)他文件_run_action()他方法中調其父類includes/ecapp.base.php文件中的_run_action()方法,在調用其父類eccore/controller/app.base.php他文件中的_run_action()方法,在此方法中調用本身所在的控制器(默認default)也就是(upload\admin\app\default.app.php)文件中的方法(默認index)index();

這些只是一點程序走向結構,具體內容結構尚未研究。程序結構給人感受彷佛挺亂的,可是若是細心研究執行效果很是的好。

相關文章
相關標籤/搜索