PHP MVC框架之加载器学习笔记

 更新时间:2016年11月25日 15:03  点击:1968
本文章来给各位介绍PHP MVC框架之加载器学习笔记,有需要了解的朋友可进入参考。

上节说了MVC的路由原理,这节我们来说说MVC框架的loader,也称为加载器。

虽然不同的框架,加载器的用法不同,但是其原理都是相通的。。。都是通过单例模式加载文件,而且把已加载的文件cache起来,避免重复加载。。。因为在开发业务的过程中,常常需要加载不同的模块,不同的类库等,MVC的loader可以帮助我们实现单例模式,更加符合开发需求。

下面我们开始动手,利用其原理,做一个简单的loader。


首先,我们设计的加载器,要满足可以全局使用,无论在controller里还是在model、library里都可以使用。

其次,加载器要有缓存能力,即相同的文件只加载一次,相同的类只实例化一次。

最后,要能加载多种文件,model、library、helper。

先解决第一步,怎么全局使用,最简单的办法就是定义一个全局的function,这样,在后面的不同类库,不同function里都可以调用这个全局function,进行加载文件。

第二步和第三步,要一起解决,定义一个单例模式的loader类,因为是单例模式,可以保证全局只有一份内容,这样的话,就可以利用数组把这些已加载的内容和对象cache起来,这样就可以避免了重复加载的问题。。。

 代码如下 复制代码
if ( ! function_exists(‘load’))  
{  
    function load($name, $type=’model’, $data=array())  
    {  
        static $loader = NULL;  
        if (is_null($loader))  
        {  
            include (ROOT.’/system/core/loader.php’);  
            $loader = Loader::get_instance();  
        }  
 
        return $loader->$type($name, $data);  
    }  

上面这个,就是我写的一个简单的全局函数 load,这个函数的作用就是为了可以全局调用,然后通过这个load函数,去调用loader类,由loader类负责加载文件,实例化,和缓存对象。。。下面我把loader的代码放出来给大家看看。

 代码如下 复制代码
<?php  
 
class Loader  
{  
    private $_loaded_models = array();  
    private $_loaded_librarys = array();  
    private static $OBJ;  
 
    # 单例模式,不允许new对象  
    private function __construct()  
    {  
 
    }  
 
 
    public static function get_instance()  
    {  
        if (is_null(self::$OBJ))  
        {  
            $class = __CLASS__;  
            self::$OBJ = new $class;  
        }  
          
        return self::$OBJ;  
    }  
 
    public function model($model, $data=array())  
    {  
        $model = strtolower($model);  
 
        # 如果已经加载,则返回对象,避免重复加载  
        if (isset($this->_loaded_models[$model]))  
        {  
            return $this->_loaded_models[$model];  
        }  
 
        # 否则加载文件  
        include ROOT.“/application/models/{$model}.php”;  
 
        $class = ucfirst($model);  
        # 实例化对象  
        if (emptyempty($data))  
        {  
            $instance = new $class;  
        }  
        else 
        {  
            $instance = new $class($data);  
        }  
        # 把对象cache起来  
        $this->_loaded_models[$model] = $instance;  
 
        return $instance;  
    }  
 
 
    public function library($library, $data=array())  
    {  
        $library = strtolower($library);  
 
        # 如果已经加载,则返回对象,避免重复加载  
        if (isset($this->_loaded_librarys[$library]))  
        {  
            return $this->_loaded_librarys[$library];  
        }  
 
        # 否则加载文件  
        include ROOT.“/application/librarys/{$library}.php”;  
 
        $class = ucfirst($library);  
        # 实例化对象  
        if (emptyempty($data))  
        {  
            $instance = new $class;  
        }  
        else 
        {  
            $instance = new $class($data);  
        }  
          
        # 把对象cache起来  
        $this->_loaded_librarys[$library] = $instance;  
 
        return $instance;  
    }  
 
 
}  
 
 
 
?> 

大家看到了没有,这个loader采用的是单例模式,虽然前面的function的设计已经可以保证不会重复实例化loader这个对象,但是为了真正可以保证全局只有一份loader对象,设计成单例模式是最保险的。。。

具体的测试例子请看代码。。。我把代码打包上传上来,有需要的就下载回去看看吧。。。下载后,解压,把lesson2文件夹放到你的www目录下,然后访问yourdomain/MVC/lesson2/index.php/index/test  试试看吧。。。

文章主要讲到了关于PHP MVC框架路由使用方法,有需要了解的同学可进入参考。


说到PHP开发web,自然离不开开发框架,开发框架为我们提供了灵活的开发方式,MVC层分离,业务解耦等。。。

第一篇先来简单点的,说说MVC框架的路由功能。。。

一般的单入口框架路由都是这样的结构:

domain/index.php/classname/functionname/var1/var2

这里的index.php 就被称为入口文件。。。对于服务器而言,你这里访问的就只有index.php 后面调用的controller 和里面的方法,甚至传值都是在框架内部基于PHP层面实现的。

Talk is cheap, show you the code !!


首先,先建立好下面的文件结构

 

我们来动手试试,怎么才能访问到controllers里面的文件。。。

在index.php里面输入以下内容

print_r($_SERVER);

然后访问 以下地址试试。

yourdomain/index.php/class/function/var1

这里作者我是用本地环境的,我访问的地址是localhost/MVC/index.php/class/function/var1

我贴出最重要的2个变量

[REQUEST_URI] => /MVC/index.php/class/function/var1

[SCRIPT_NAME] => /MVC/index.php

其实路由最基本的原理就在这里:

通过这2个变量来提取url地址里的class 和 function,参数等,然后把class include进来,通过PHP的回调函数  call_user_func_array 调用对应的function和传递相应的参数。

接下来上代码,读代码应该比我写的易懂。哈哈~~

index.php 的内容如下

 代码如下 复制代码

 
<?php  
 
# 定义application路径  
define(‘APPPATH’, trim(__DIR__,’/'));  
 
# 获得请求地址  
$root = $_SERVER['SCRIPT_NAME'];  
$request = $_SERVER['REQUEST_URI'];  
 
$URI = array();  
 
# 获得index.php 后面的地址  
$url = trim(str_replace($root, ”, $request), ‘/’);  
 
# 如果为空,则是访问根地址  
if (empty($url))  
{  
    # 默认控制器和默认方法  
    $class = ‘index’;  
    $func = ‘welcome’;  
}  
else 
{  
    $URI = explode(‘/’, $url);  
 
    # 如果function为空 则默认访问index  
    if (count($URI) < 2)  
    {  
        $class = $URI[0];  
        $func = ‘index’;  
    }  
    else 
    {  
        $class = $URI[0];  
        $func = $URI[1];  
    }  
}  
 
 
# 把class加载进来  
include(APPPATH . ‘/’ . ‘application/controllers/’ . $class . ‘.php’);  
 
#实例化  
$obj = new ucfirst($class);  
 
call_user_func_array(  
    # 调用内部function  
    array($obj,$func),   
    # 传递参数  
    array_slice($URI, 2)  
);  
 

在application/controllers 里面添加下面2个文件

index.php   用于作为默认控制器

 

 代码如下 复制代码


<?php  
 
class Index  
{  
 
    function welcome()  
    {  
        echo ‘I am default controller’;  
    }  
 
}  
 
 
?> 
 

hello.php

 
<?php  
class Hello  
{  
    public function index()  
    {  
        echo ‘hello world’;  
    }  
 
    public function name($name)  
    {  
        echo ‘hello ‘ . $name;  
    }  
}  
 
?> 
 

测试一下看看,能不能访问了。根据上面的路由结构。我们来试试

 

这个访问正常,正确调用了hello这个class内部的name方法,然后把参数barbery传递过去了。。。

再试试不输入function name,看看能不能默认调用index。。

 

答案也是可以的。。。

最后一个,访问root地址看看

 

也正确的映射到了默认控制器上。。。

ok,一个简单的MVC路由功能就完成了。。。

本文章来给大家介绍PHP MVC框架视图学习笔记,以方便以后需要参考。

今天来讲讲view,视图。。。没了解之前,你可能觉得模板引擎很神奇,了解了之后你会觉得,原来是如此简单。。。

对于模板引擎而言,它的原理一般是这样,把模板引擎的语言替换成可执行的语言,然后把变量输出。。。

因为PHP本身就是一个良好了模板引擎,所以用原生的模板引擎是灰常方便和容易做到的。。。


index.html

 代码如下 复制代码
 
<html>  
<head>  
    <title><?php echo $title ?></title>  
</head>  
<body>  
<h1><?php echo $content ?></h1>  
 
<?php if( ! empty($arr)) { ?>  
<ul>  
    <?php foreach($arr as $value) { ?>  
    <li><?php echo $value ?></li>  
    <?php } ?>  
</ul>  
<?php } ?>  
 
</body>  
</html> 

想上面这样一个html页面,采用的就是原生的php模板引擎,服务器在你include这个页面时,会处理html中的PHP代码。

你也许会问,要是我想定制模板语言可以吗?答案当然是可以的,像我上面说的,用模板引擎的语言,只需要多做一步,就是把模板引擎的语言替换成标准的PHP语言。。。

 index_2.html

 

 代码如下 复制代码
<html> 
<head> 
    <title><?php echo $title ?></title> 
</head> 
<body> 
<h1><?php echo $content ?></h1> 
 
<ifexist arr> 
<ul> 
    <for value = arr> 
    <li><echo value></li> 
    <endfor> 
</ul> 
<endexist> 
 
</body> 
</html> 

看看这个页面,发现和index.html 有什么不同吗,没错,就是在循环那里,我们用的不是标准的php语言,而是,按照自己的喜好,定义了几个模板语言,一个是<ifexist xxx>这个是判断xxx变量是否存在,而且不为空,后面那个<for xx1=xx2>是循环迭代xx2变量,中间的<echo xx> 是输出xx变量

怎么替换成标准语言呢?这个可以使用正则替换,因为字符串替换无法满足我们需求了。

 代码如下 复制代码
 
$pattern = array(  
    ‘/<ifexists+(w+)>/i’,  
    ‘/<fors+(w+)s=s(w+)>/’,  
    ‘/<echos+(w+)>/’  
);  
 
$replacement = array(  
    ‘<?php if( ! empty($\1)){ ?>’,  
    ‘<?php foreach($\2 as $\1){ ?>’,  
    ‘<?php echo $\1 ?>’  
);  
 
$content = preg_replace($pattern, $replacement, $content);  
 
$search = array(‘<endexist>’, ‘<endfor>’);  
 
 
$content = str_replace($search, ‘<?php } ?>’, $content); 

 

上面的正则就可以帮我们把刚刚定义的标签,转换成标准p hp语言。。。

转换之后是这样,请看图。

 

转换之后可以输出了吗?答案是不行的,因为你获取到html文件的内容的时候,php就已经解释了,那时候你还没替换成标准的php语言,所以,你现在输出的话,其中的php代码就没有执行。。。不过我们可以利用 php eval 这个函数,来强制要求执行其中的代码。

 代码如下 复制代码

$content = eval(‘ ?>’.$content);

注意哦,要 ?>.$content 要不,php会把其中的html当成是php代码的执行,这样就会出错了。。。

刷新一下,ok,已经可以执行了~~~

文章主要讲到关于php中慎用isset来判断数组是否存在key一些举例说明。

接上代码,  不知道是php5.4版本的问题, 还是本来就这样…

 代码如下 复制代码

$a['hello'] = ’123‘; 
$a['xx'] = NULL; 
 
var_dump(isset($a['hello'])); //bool(true) 
 
var_dump(isset($a['xx'])); //bool(false) 
 
# 应该使用这个来判断 
var_dump(array_key_exists(‘xx’, $a)); //bool(true)

PHP 5.3 加入了闭包语法,也就是匿名函数,允许开发者申明行内函数和在变量中保存。虽然这个语法和JavaScript的闭包相比有点怪异,但是对于PHP语言来说,这是一个良好的补充
 代码如下 复制代码
<?php
/**
* 下面提到的代码在PHP5.3以上版本运行通过.
*/
function callback($callback) {
$callback();
}
//输出: This is a anonymous function.<br />/n
//这里是直接定义一个匿名函数进行传递, 在以往的版本中, 这是不可用的.
//现在, 这种语法非常舒服, 和javascript语法基本一致, 之所以说基本呢, 需要继续向下看
//结论: 一个舒服的语法必然会受欢迎的.
callback(function() {
print "This is a anonymous function.<br />/n";
});
//输出: This is a closure use string value, msg is: Hello, everyone.<br />/n
//这里首先定义了一个闭包, 这次户口本上有名字了...
//use, 一个新鲜的家伙...
//众所周知, 闭包: 内部函数使用了外部函数中定义的变量.
//在PHP新开放的闭包语法中, 我们就是用use来使用闭包外部定义的变量的.
//这里我们使用了外部变量$msg, 定义完之后, 又对其值进行了改变, 闭包被执行后输出的是原始值
//结论: 以传值方式传递的基础类型参数, 闭包use的值在闭包创建是就确定了.
$msg = "Hello, everyone";
$callback = function () use ($msg) {
print "This is a closure use string value, msg is: $msg. <br />/n";
};
$msg = "Hello, everybody";
callback($callback);
//输出: This is a closure use string value lazy bind, msg is: Hello, everybody.<br />/n
//换一种引用方式, 我们使用引用的方式来use
//可以发现这次输出是闭包定义后的值...
//这个其实不难理解, 我们以引用方式use, 那闭包use的是$msg这个变量的地址
//当后面对$msg这个地址上的值进行了改变之后, 闭包内再输出这个地址的值时, 自然改变了.
$msg = "Hello, everyone";
$callback = function () use (&$msg) {
print "This is a closure use string value lazy bind, msg is: $msg. <br />/n";
};
$msg = "Hello, everybody";
callback($callback);
//输出: This is a closure use object, msg is: Hello, everyone.<br />/n
//闭包中输出的是之前被拷贝的值为Hello, everyone的对象, 后面是对$obj这个名字的一个重新赋值.
//可以这样考虑
//1. obj是对象Hello, everyone的名字
//2. 对象Hello, everyone被闭包use, 闭包产生了一个对Hello, everyone对象的引用
//3. obj被修改为Hello, everybody这个对象的名字
//4. 注意, 是名字obj代表的实体变了, 而不是Hello, everyone对象, 那自然闭包的输出还是前面的Hello, everyone
$obj = (object) "Hello, everyone";
$callback = function () use ($obj) {
print "This is a closure use object, msg is: {$obj->scalar}. <br />/n";
};
$obj = (object) "Hello, everybody";
callback($callback);
//输出: This is a closure use object, msg is: Hello, everybody.<br />/n
//还是按照上面的步骤, 按部就班的来吧:
//1. obj名字指向Hello, everyone对象
//2. 闭包产生一个引用指向Hello, everyone对象
//3. 修改obj名字指向的对象(即Hello, everyone对象)的scalar值
//4. 执行闭包, 输出的自然是Hello, everybody, 因为其实只有一个真正的对象
$obj = (object) "Hello, everyone";
$callback = function () use ($obj) {
print "This is a closure use object, msg is: {$obj->scalar}. <br />/n";
};
$obj->scalar = "Hello, everybody";
callback($callback);
//输出: This is a closure use object lazy bind, msg is: Hello, everybody.<br />/n
//闭包引用的是什么呢? &$obj, 闭包产生的引用指向$obj这个名字所指向的地址.
//因此, 无论obj怎么变化, 都是逃不脱的....
//所以, 输出的就是改变后的值
$obj = (object) "Hello, everyone";
$callback = function () use (&$obj) {
print "This is a closure use object lazy bind, msg is: {$obj->scalar}. <br />/n";
};
$obj = (object) "Hello, everybody";
callback($callback);
/**
* 一个利用闭包的计数器产生器
* 这里其实借鉴的是python中介绍闭包时的例子...
* 我们可以这样考虑:
*         1. counter函数每次调用, 创建一个局部变量$counter, 初始化为1.
*         2. 然后创建一个闭包, 闭包产生了对局部变量$counter的引用.
*         3. 函数counter返回创建的闭包, 并销毁局部变量, 但此时有闭包对$counter的引用,
*             它并不会被回收, 因此, 我们可以这样理解, 被函数counter返回的闭包, 携带了一个游离态的
*             变量.
*         4. 由于每次调用counter都会创建独立的$counter和闭包, 因此返回的闭包相互之间是独立的.
*         5. 执行被返回的闭包, 对其携带的游离态变量自增并返回, 得到的就是一个计数器.
* 结论: 此函数可以用来生成相互独立的计数器.
*/
function counter() {
$counter = 1;
return function() use(&$counter) {return $counter ++;};
}
$counter1 = counter();
$counter2 = counter();
echo "counter1: " . $counter1() . "<br />/n";
echo "counter1: " . $counter1() . "<br />/n";
echo "counter1: " . $counter1() . "<br />/n";
echo "counter1: " . $counter1() . "<br />/n";
echo "counter2: " . $counter2() . "<br />/n";
echo "counter2: " . $counter2() . "<br />/n";
echo "counter2: " . $counter2() . "<br />/n";
echo "counter2: " . $counter2() . "<br />/n";
?>
[!--infotagslink--]

相关文章

  • 用js的document.write输出的广告无阻塞加载的方法

    一、广告代码分析很多第三方的广告系统都是使用document.write来加载广告,如下面的一个javascript的广告链接。复制代码 代码如下:<script type="text/javascript" src="http://gg.5173.com/adpolestar/5173/;ap=2EBE5...2014-06-07
  • 基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍

    这篇文章主要介绍了基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍 的相关资料,需要的朋友可以参考下...2016-05-14
  • jQuery页面加载初始化常用的三种方法

    当页面打开时我们需要执行一些操作,这个时候如果我们选择使用jquery的话,需要重写他的3中方法,自我感觉没什么区 别,看个人喜好了,第二种感觉比较简单明了: 第一种: 复制代码 代码如下: <script type="text/javas...2014-06-07
  • 解决IDEA插件市场Plugins无法加载的问题

    这篇文章主要介绍了解决IDEA插件市场Plugins无法加载的问题,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-10-21
  • Android WebView加载html5页面实例教程

    如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
  • .net数据库操作框架SqlSugar的简单入门

    这篇文章主要介绍了.net数据库操作框架SqlSugar的简单入门,帮助大家更好的理解和学习使用.net技术,感兴趣的朋友可以了解下...2021-09-22
  • CI框架开发新浪微博登录接口源码完整版

    首先来看下流程:流程原理: 1.通过code获得access_token通过授权,并获取用户的信息(包括用户u_id)(这个u_id在后面的第三方登录表里面叫sina_id,那个表是需要自己建的) 2.查询第三方登录表,如果不存在用户sina_id,分2...2014-05-31
  • 记一次EFCore类型转换错误及解决方案

    这篇文章主要介绍了记一次EFCore类型转换错误及解决方案,帮助大家更好的理解和学习使用asp.net core,感兴趣的朋友可以了解下...2021-09-22
  • Angular性能优化之第三方组件和懒加载技术

    这篇文章主要介绍了Angular性能优化之第三方组件和懒加载技术,对性能优化感兴趣的同学,可以参考下...2021-05-11
  • 解决vue动态路由异步加载import组件,加载不到module的问题

    这篇文章主要介绍了解决vue动态路由异步加载import组件,加载不到module的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-27
  • vue3如何按需加载第三方组件库详解

    距离 Vue 3.0 正式版发布已经有一段时间了,关于vue3组件库相关的问题还是挺多人感兴趣的,这篇文章主要给大家介绍了关于vue3如何按需加载第三方组件库的相关资料,需要的朋友可以参考下...2021-06-02
  • 几种延迟加载JS代码的方法加快网页的访问速度

    本文介绍了如何延迟javascript代码的加载,加快网页的访问速度。 当一个网站有很多js代码要加载,js代码放置的位置在一定程度上将会影像网页的加载速度,为了让我们的网页加载速度更快,本文总结了一下几个注意点...2013-10-13
  • ThinkPHP+jquery实现“加载更多”功能代码

    本篇文章主要介绍了ThinkPHP+jquery实现“加载更多”功能代码,以实例代码讲诉了加载更多的代码实现,非常具有实用价值,需要的朋友可以参考下 ...2017-03-13
  • AngularJS 实现按需异步加载实例代码

    AngularJS 通过路由支持多视图应用, 可以根据路由动态加载所需的视图, 在 AngularJS 的文档中有详细的介绍, 网上也有不少教程, 就不用介绍了!随着视图的不断增加,js文件会越来越多,而 AngularJS 默认需要把全部的js都一次性...2015-10-21
  • php上传图片学习笔记与心得

    我们在php中上传文件就必须使用#_FILE变量了,这个自动全局变量 $_FILES 从 PHP 4.1.0 版本开始被支持。在这之前,从 4.0.0 版本开始,PHP 支持 $HTTP_POST_FILES 数组。这...2016-11-25
  • Smarty模板学习笔记之Smarty简介

    1、简介Smarty是一个使用PHP写出来的模板PHP模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目...2014-05-31
  • c# 常用框架汇总

    这篇文章主要介绍了c# 常用框架汇总,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...2021-04-24
  • 用C++面向对象的方式动态加载so的方法

    下面小编就为大家带来一篇用C++面向对象的方式动态加载so的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25
  • jQuery Easyui使用(二)之可折叠面板动态加载无效果的解决方法

    这篇文章主要介绍了jQuery Easyui使用之可折叠面板动态加载无效果的解决方案,非常不错,具有参考借鉴价值,感兴趣的朋友一起看下吧...2016-08-24
  • 基于Pycharm加载多个项目过程图解

    这篇文章主要介绍了基于Pycharm加载多个项目过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-04-22