ECMALL的登录过程机制解析

这个过程程序执行效果非常的好
服务器君一共花费了324.465 ms进行了4次数据库查询,努力地为您提供了这个页面。
试试阅读模式?希望听取您的建议

在ecmall.php文件中实例化控制器类,每一个控制器类,必须继承(extends)upload\admin\app\backend.base.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文件。

获得控制器默认为[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()方法。

    /**
     *    后台的需要权限验证机制
     *
     *    @author    Garbin
     *    @return    void
     */
    function _run_action()
    {
        /* 先判断是否登录 */
        if (!$this->visitor->has_login)
        {
            $this->login();
            return;
        }
        /* 登录后判断是否有权限 */
        if (!$this->visitor->i_can('do_action', $this->visitor->get('privs')))
        {
            $this->show_warning('no_permission');
            return;
        }
        /* 运行 */
        parent::_run_action();
    }

在此要判断当前用户是否登录。

如果没有登录,调用(app/backend.base.php)他中的login()方法。

    function login()
    {
        if ($this->visitor->has_login)
        {
            $this->show_warning('has_login');
            return;
        }
        if (!IS_POST)
        {
            if (Conf::get('captcha_status.backend'))
            {
                $this->assign('captcha', 1);
            }
            $this->display('login.html');
        }
        else
        {
            if (Conf::get('captcha_status.backend') && base64_decode($_SESSION['captcha']) != strtolower($_POST['captcha']))
            {
                $this->show_warning('captcha_faild');
                return;
            }
            $user_name = trim($_POST['user_name']);
            $password  = $_POST['password'];
            $ms =& ms();
            $user_id = $ms->user->auth($user_name, $password);
            if (!$user_id)
            {
                /* 未通过验证,提示错误信息 */
                $this->show_warning($ms->user->get_error());
                return;
            }
            /* 通过验证,执行登陆操作 */
            if (!$this->_do_login($user_id))
            {
                return;
            }
            $this->show_message('login_successed',
                'go_to_admin', 'index.php');
        }
    }

然后调用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数组中。

display()函数:

    function display($f)
    {
        if ($this->_hook('on_display', array('display_file' => & $f)))
        {
            return;
        }
        $this->assign('site_url', SITE_URL);
        $this->assign('ecmall_version', VERSION);
        $this->assign('random_number', rand());
        /* 语言项 */
        $this->assign('lang', Lang::get());
        /* 用户信息 */
        $this->assign('visitor', isset($this->visitor) ? $this->visitor->info : array());
        /* 新消息 */
        $this->assign('new_message', isset($this->visitor) ? $this->_get_new_message() : '');
        $this->assign('charset', CHARSET);
        $this->assign('price_format', Conf::get('price_format'));
        $this->assign('async_sendmail', $this->_async_sendmail());
        $this->_assign_query_info();
        parent::display($f);
        if ($this->_hook('end_display', array('display_file' => & $f)))
        {
            return;
        }
    }

assign()函数:

    /**
     *    给视图传递变量
     *
     *    @author    Garbin
     *    @param     string $k
     *    @param     mixed  $v
     *    @return    void
     */
    function assign($k, $v = null)
    {
        $this->_init_view();
        if (is_array($k))
        {
            $args  = func_get_args();
            foreach ($args as $arg)     //遍历参数
            {
                foreach ($arg as $key => $value)    //遍历数据并传给视图
                {
                    $this->_view->assign($key, $value);
                }
            }
        }
        else
        {
            $this->_view->assign($k, $v);
        }
    }

_init_view()函数:

    /**
     *    初始化视图连接
     *
     *    @author    Garbin
     *    @param    none
     *    @return    void
     */
    function _init_view()
    {
        if ($this->_view === null)
        {
            $this->_view =& v();
            $this->_config_view();  //配置
        }
    }

在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()方法把其替换为空。

在页面提交中用到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)

/**
 *    连接会员系统
 *
 *    @author    Garbin
 *    @return    Passport 会员系统连接接口
 */
function &ms()
{
    static $ms = null;
    if ($ms === null)
    {
        include(ROOT_PATH . '/includes/passport.base.php');
        include(ROOT_PATH . '/includes/passports/' . MEMBER_TYPE . '.passport.php');
        $class_name  = ucfirst(MEMBER_TYPE) . 'Passport';
        $ms = new $class_name();
    }
    return $ms;
}

在这个过程中,把若干类实例化,所以调用auth(&username,&password)判断用户是不是存在正确,如果正确获得用户ID执行登陆操作调用_do_login方法,在这里我们的回到刚加载文件时候的初始化中因为在includes/ecapp.base.php文件初始化的时候执行了$this->_init_visitor();方法引用了AdminVisitor他类并继承了BaseVisitor类,所以可以在_do_login()方法中应用$this->visitor->assign()方法,其实就是BaseVisitor类中的

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

这样就把用户信息用SESSION保存,在执行操作的时候就可以对$this->has_login进行改变了。

好了这就是登录了。

其实他应用到"引用"和"继承"比较多所以会让初学者都感觉到很乱,没有头绪。引用就是不同的名字访问同一个变量内容,引用作为函数参数可以避免参数对象的额外拷贝。

如果程序比较大,引用同一个对象的变量比较多,并且希望用完该对象后手工清除它,个人建议用 "&" 方式,然后用$var=null的方式清除.另外, php5中对于大数组的传递,建议用 "&" 方式, 毕竟节省内存空间使用。

function qev(&$array)
{
     Var_export($array);
}
$array_qev = array(
'1'=>'a','2'=>'b'
)
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();

这些只是一点程序走向结构,具体内容结构还没有研究。程序结构给人感觉似乎挺乱的,但是如果细心研究执行效果非常的好。

本文地址:http://www.nowamagic.net/librarys/veda/detail/1078,欢迎访问原出处。

不打个分吗?

转载随意,但请带上本文地址:

http://www.nowamagic.net/librarys/veda/detail/1078

如果你认为这篇文章值得更多人阅读,欢迎使用下面的分享功能。
小提示:您可以按快捷键 Ctrl + D,或点此 加入收藏

大家都在看

阅读一百本计算机著作吧,少年

很多人觉得自己技术进步很慢,学习效率低,我觉得一个重要原因是看的书少了。多少是多呢?起码得看3、4、5、6米吧。给个具体的数量,那就100本书吧。很多人知识结构不好而且不系统,因为在特定领域有一个足够量的知识量+足够良好的知识结构,系统化以后就足以应对大量未曾遇到过的问题。

奉劝自学者:构建特定领域的知识结构体系的路径中再也没有比学习该专业的专业课程更好的了。如果我的知识结构体系足以囊括面试官的大部分甚至吞并他的知识结构体系的话,读到他言语中的一个词我们就已经知道他要表达什么,我们可以让他坐“上位”毕竟他是面试官,但是在知识结构体系以及心理上我们就居高临下。

所以,阅读一百本计算机著作吧,少年!

《编程之美:微软技术面试心得》 《编程之美》小组 (作者)

《编程之美:微软技术面试心得》是一本让人着迷的书!阅读起来。有些题目的内容会引起强烈的共鸣,尤其是那些自己非常熟悉并且又深知解答的题目;也有一些题目让我异常惊诧,原来除了我所知道的解答思路之外,还有更好的解答以及更深层次的原因。还有一些题目是从来没想到过的。阅读过程是一次愉快的享受,也是脑细胞持续活跃的过程。

更多计算机宝库...