文档章节

怎么一步步编写简单的PHP的Framework(五)

阳光test
 阳光test
发布于 2012/11/18 18:12
字数 1250
阅读 1888
收藏 16

       上一次我讲到使用自动导入可以实现一个类的延迟加载,这一次我想讲一下配置文件。

       不知道大家注意了没有,前几篇文章我都没有涉及到配置文件,可是在一个项目中,配置文件又是比不可少的。

       现在假设将Route.php中的默认控制器和Action变为可配置的,怎么弄呢?

       我们使用最简单的方式:

 

<?php
 $defaultController = 'Index';
 $defaultAction = 'index';


      然后在Route.php中include这个文件:


<?php
include APP_PATH . '/config.php';
$controller = empty($_GET['c']) ? $defaultController : trim($_GET['c']); //设置了默认的控制器
$action = empty($_GET['a']) ? $defaultAction : trim($_GET['a']); //设置了默认的Action
当然也可以使用这种方式:



<?php
return array(
       'defaultController' => 'Index',
       'defaultAction' => 'index'
);
     还是在Route.php中include:



<?php
$config = include APP_PATH . '/config.php';
$controller = empty($_GET['c']) ? $config['defaultController'] : trim($_GET['c']); //设置了默认的控制器
$action = empty($_GET['a']) ? $config['defaultAction'] : trim($_GET['a']); //设置了默认的Action


      但是由于配置文件很有可能在整个框架运行过程的各个类都有用到,而前两种方式都只能在某一个类里面的某一个方法中使用,怎么让它在各个类都可以使用呢?

      我们可以可以使用一个static方法来解决,比如专门定义一个Config类来存放配置信息,Config::get来读取配置信息,Config::set来设置配置信息,具体做法读者可以自己去尝试一下。

      当然我不准备采用这种方式,可能当时我看Thinkphp源码的时候被它优雅的特殊函数C迷住了吧,后面我在写Toper的时候也使用了一些特殊的函数,而C主要是负责设置和读取配置信息,个人观点,面向对象是必要的,但是不是什么都要面向对象,所以我准备定义一个function.php来存放一些公有的函数,我把它称为公有函数库。

      由于有了公有函数库,我们可以将上一篇里面的自动导入(__autoload)也转移到这个文件中,因为在Route.php出现一段__autoload的代码还是挺诡异的!!

      好了,怎么实现刚才我们说的通过一个函数来实现配置信息的设置和读取呢?

      好了,先展示我在Toper中的实现吧:

      

function C($name = null,$val = null) {
	static $_config = array();
	if(empty($name)) {
		return $_config;
	} elseif(is_string($name)) {
		if(empty($val)) {
			if(!strpos($name,'=>')) {
				//一维
				return isset($_config[$name]) ? $_config[$name] : null;
			} else {
				//目前只支持二维
				$name = explode('=>',$name);
				return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : null;
			}
		} else {
			if(!strpos($name,'=>')) {
				//直接设置
				$_config[$name] = $val;
			} else {
				//设置二维
				$name = explode('=>',$name);
				$_config[$name[0]][$name[1]] = $val;
			}
		}
	} elseif(is_array($name)) {
		foreach($name as $key=>$value) {
			$_config[$key] = $value;
		}
		return ;
	} else {
		throw new Exception('参数类型出错');
		return ;
	}
}


         看着代码挺长的,实际上原理很简单,如果传递的参数只有一个,那么第二个参数就调用默认参数,即NULL,再识别是否第一个参数是否是字符串,那么这个函数就识别为读取,如果第二个参数不为空或第一个参数为数组,那么就识别为设置!!

         由于我自己现在比较懒,而且我用这个函数用的函数蛮顺手的,所以在这儿我就直接用这个函数来作为例子了,更多内容可以查看Toper的/Library/Toper/function.php。

         比如现在要读取defaultController,那么只要使用C('defaultController')即可,如果要设置,那么使用C('defaultController','Index')!!!

          现在我们只需要在入口文件中导入这个function.php即可:


<?php
defined('APP_PATH') || define('APP_PATH',dirname(__FILE__) . '/..');
defined('FRAMEWORK_PATH') || define('FRAMEWORK_PATH',APP_PATH . '/Library/Test');
defined('MODULES_PATH') || define('MODULES_PATH',APP_PATH . '/UserApps/Modules');
include FRAMEWORK_PATH . '/function.php';
include FRAMEWORK_PATH . '/Route.php';
Route::run();
         大家可能注意到了,C函数最开始的时候,里面没有存放任何元素,那么我们怎么样进行初始化,将配置文件的内容写入C函数呢?


          之前我们将配置文件存放在项目根目录,这样实际上是不符合之前我们的约定的规范,所以现在讲这个配置文件剪切到/UserApps/Configs目录下面,为了更方便的使用这个路径,我们定义一个CONFIGS_PATH来指向配置文件的路径。

        现在我们看看入口文件变成了什么样了:


<?php
defined('APP_PATH') || define('APP_PATH',dirname(__FILE__) . '/..');
defined('FRAMEWORK_PATH') || define('FRAMEWORK_PATH',APP_PATH . '/Library/Test');
defined('MODULES_PATH') || define('MODULES_PATH',APP_PATH . '/UserApps/Modules');
defined('CONFIGS_PATH') || define('CONFIGS_PATH',APP_PATH . '/UserApps/Configs');
include FRAMEWORK_PATH . '/function.php';
C(include CONFIGS_PATH . '/config.php'); //写入配置信息
include FRAMEWORK_PATH . '/Route.php';
Route::run();
      然后我们修改一下Route.php



<?php
class Route {
	public static function run() {
		$controller = empty($_GET['c']) ? C('defaultController') : trim($_GET['c']); //设置了默认的控制器
		$action = empty($_GET['a']) ? C('defaultAction') : trim($_GET['a']); //设置了默认的Action
		$controllerBasePath = APP_PATH . '/UserApps/Modules/Controllers/';
		$controllerFilePath = $controllerBasePath . $controller . 'Controller.php';
		if(is_file($controllerFilePath)) {
			include $controllerFilePath;
			$controllerName = $controller . 'Controller';
			if(class_exists($controllerName)) {
				$controllerHandler = new $controllerName();
				if(method_exists($controllerHandler,$action)) {
					$controllerHandler->$action();
				} else {
					echo 'the method does not exists';
				}
			} else {
				echo 'the class does not exists';
			}
		} else {
			echo 'controller not exists';
		}
	}
}
      今天的例子 点此下载



© 著作权归作者所有

阳光test

阳光test

粉丝 541
博文 71
码字总数 91741
作品 1
杭州
程序员
私信 提问
加载中

评论(10)

帖子列表
帖子列表

引用来自“hylent”的评论

一看就是名校毕业 不过没有完美主义 估计是被学校考试什么的拖成这样的 完成任务是首要目的
对php了解不够深 代码没有明确的风格和严谨的规则
但总体来说还算不错 能以通俗易懂的方式传达思想 新手看足够了

名校毕业是怎么看出来的?
overlords
overlords

引用来自“明庭令”的评论

引用来自“overlords”的评论

defined('APP_PATH') || define('APP_PATH',dirname(__FILE__) . '/..');
等同于
if(!defined('APP_PATH')) define('APP_PATH', dirname(__FILE__) . '/..');
吗?

是一样的,这样更简洁,一个是if,一个是用或。

明白了,只是我刚开始不知道||或还可以这样用,又学了一招!(*^__^*) 嘻嘻
阳光test
阳光test 博主

引用来自“overlords”的评论

defined('APP_PATH') || define('APP_PATH',dirname(__FILE__) . '/..');
等同于
if(!defined('APP_PATH')) define('APP_PATH', dirname(__FILE__) . '/..');
吗?

是一样的,这样更简洁,一个是if,一个是用或。
overlords
overlords
defined('APP_PATH') || define('APP_PATH',dirname(__FILE__) . '/..');
等同于
if(!defined('APP_PATH')) define('APP_PATH', dirname(__FILE__) . '/..');
吗?
bunnys
bunnys

引用来自“明庭令”的评论

引用来自“bunnys”的评论

加个 qq吧 有些东西要请教你 837109151

可以,不过现在在上班,晚上回去再说吧

好的 晚上
阳光test
阳光test 博主

引用来自“bunnys”的评论

加个 qq吧 有些东西要请教你 837109151

可以,不过现在在上班,晚上回去再说吧
bunnys
bunnys
加个 qq吧 有些东西要请教你 837109151
阳光test
阳光test 博主

引用来自“老北”的评论

这哥们的点评很霸气,你能否写给高手瞧瞧?
支持博主,加油!

谢谢!!!
老北
老北
这哥们的点评很霸气,你能否写给高手瞧瞧?
支持博主,加油!
hylent
hylent
一看就是名校毕业 不过没有完美主义 估计是被学校考试什么的拖成这样的 完成任务是首要目的
对php了解不够深 代码没有明确的风格和严谨的规则
但总体来说还算不错 能以通俗易懂的方式传达思想 新手看足够了
一步步编写简单的PHP的Framework(五)

上一次我讲到使用自动导入可以实现一个类的延迟加载,这一次我想讲一下配置文件。 不知道大家注意了没有,前几篇文章我都没有涉及到配置文件,可是在一个项目中,配置文件又是比不可少的。 ...

NateHuang
2016/07/28
2
0
一步步编写PHP的Framework(一)

框架这个概念可能一开始就吓坏了很多PHP的Coder,其实你只要把一个Framework想明白了,其实也没啥,只是别人功能更复杂,细节考虑的更多,代码质量更高。 框架最重要的一个文件为入口文件,基...

NateHuang
2016/07/27
23
0
怎么一步步编写简单的PHP的Framework(一)

自从入职天猫之后,都没怎么时间看oschina了,趁着这段时间参加培训,忙里偷闲,写几篇日志吧。 框架这个概念可能一开始就吓坏了很多PHP的Coder,其实你只要把一个Framework想明白了,其实也...

阳光test
2012/11/15
9.2K
22
一步步编写PHP的Framework(二)

实际上要自己实现一个MVC的应用也不难,我们知道MVC里面所有内容都必须经过控制器,所以如何把控制权交给控制器呢? 我们需要一个入口文件,入口文件负责将传递的请求交给对应的控制器,实际...

NateHuang
2016/07/27
17
0
怎么一步步编写简单的PHP的Framework(十三)

上次讲到控制器怎么样将数据传递到视图,今天我就主要说一下在程序中怎么让代码更“安全”,之后就转到讲模型,再讲怎么做视图,最后再讲控制器的功能强化。 我再声明一下,我写这个文章只是...

阳光test
2012/12/04
1K
16

没有更多内容

加载失败,请刷新页面

加载更多

Docker 可视化管理 portainer

官网安装指南: https://portainer.readthedocs.io/en/latest/deployment.html docker-compose.yml 位置,下载地址:https://downloads.portainer.io/docker-compose.yml...

Moks角木
38分钟前
5
0
Spring Security 实战干货:必须掌握的一些内置 Filter

1. 前言 上一文我们使用 Spring Security 实现了各种登录聚合的场面。其中我们是通过在 UsernamePasswordAuthenticationFilter 之前一个自定义的过滤器实现的。我怎么知道自定义过滤器要加在...

码农小胖哥
41分钟前
7
0
常见分布式事务解决方案

1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单、松耦合的服务,这样可以降低开发难度、增强扩展性、便于敏捷开发。当前被越来越多的开发者推崇,很多互联网行业巨头、开源...

asdf08442a
42分钟前
3
0
influxdb continuous queries(cq)从入门到放弃

从前一篇influxdb的文章prometheus基于influxdb的监控数据持久化存储方案完成之后,就一直在折腾influxdb发布测试和生产环境的问题,经过接近2个月的验证,最终发现使用influxdb自带cq的方案...

狗陈
53分钟前
7
0
7.线程通信

在现实生活中,如果一个人团队正在共同完成任务,那么他们之间应该有通信,以便正确完成任务。 同样的比喻也适用于线程。 在编程中,要减少处理器的理想时间,我们创建了多个线程,并为每个线...

Eappo_Geng
59分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部