热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PHP框架模板原理分析-PHP源码

PHP框架现在是一种很流行的东西了,很多朋友开发应用与网站都会选择一个PHP框架或模板了,下面我们来看看PHP框架是如何实现的吧。
PHP框架现在是一种很流行的东西了,很多朋友开发应用与网站都会选择一个PHP框架或模板了,下面我们来看看PHP框架是如何实现的吧。

本文主要来聊聊框架理论,但不针对任何一款框架,不过任何一款框架都离不开这个理论,首先我们了解下框架的来龙去脉,任何技术的出现都是为了解决某个问题,之前的博客有讲过smarty,其存在就是为了html和php更好地分离开来。而所谓的“框架”是一种为了统一书写格式,访问方式而进行的自我约束行为,其实按照这个说法我们每个人基本上都或多或少的使用过自己定义的框架,比如说在没使用框架之前自己开发一个项目,有时候是一天无法完成的,我们为了防止混乱,为了更好地记忆我们会进行目录规划和程序的规划,潜意识的把程序分类,放到不同的文件夹,于是框架应运而生了,又比如说我们曾经做了一个CMS系统,如果我们又接手一个类似的项目,你会重复书写代码吗,答案肯定不会,但如果是别人的项目你拿来改其实是一件很蛋疼的事情的,因为你根本不知道他的这个CMS的规则是什么,即使是自己的项目时间久了如果自己没有固定的规范的话也是很容易忘记的,那么怎么样才能保证自己每次写的代码都可以按照一定的规范呢,把每个项目要用的东西挑出来,目录结构挑出来,以后无论什么项目都在这个基础上书写,那么属于自己的框架就出来了。

  但框架单纯这样是不完善的,那么框架应该有哪些能力呢,与其这样说我们不妨想想我们平时一定会写的代码一定会做的事情是什么呢,首先解决的是什么呢,为了减少路径问题,目录结构的安排其实很重要,有时候文件包含 再进行文件的移动总是一件很蛋疼的事情,最好的办法是什么呢,绝对路径,但同时存在了一个类似E:www 这样的问题,但这个值我们可以通过预定义变量$_SERVER["DOCUMENT_ROOT"]获得,我们可以将其定义为常量,define("ROOT_PATH", $_SERVER["DOCUMENT_ROOT"]);include ROOT_PATH . "/lib/mysql.php";类似这样的文件夹怎么移动都不会有事的,那么就出现了一个固定的写法,为了解决路径问题而存在的写法,几乎每一页都会用到,还有模板的输出,数据库的连接,那么我们可以把这些代码封装起来,或者分离出来,每一页包含即可,被分离的这些部分其实就是一个小框架,为什么这么说呢,如果我们包含它们进来,例如smarty模板,肯定是实例化好的对象,那个量名已经固定,可能是$smarty 如果我们包含了这么个文件进来,这个量就不能再次进行赋值使用,这样下面部分的代码就无法进行使用了,由于包含的类,如数据类 上传类 图像类 分页类 位置已经写死在这个公共文件里,为了不改代码 这个目录就成了必须存在的了,目录格式固定,编写代码方式的约束,这就形成了框架。 

  多年来的程序员的总结交流及开发经验,大家总结了一些优秀的编写方式,最经典的是单点入口,什么是单点入口呢,之前我们总结了一些几乎每个程序都要用到的功能,这里依然存在一些问题,例如 在公共文件包含之前我们还是不知道根目录是多少,如果我们在每一个文件夹下面都放一个公共文件存在代码重复问题,哪天修改的话需要全部修改,需要找到需要多少个这样的文件,现在是多个程序包含一个程序,然后用户访问n个程序来完成各个功能,于是程序员就想可不可以反过来我用一个程序包含这些不同功能的程序,用户只访问这个程序就可以了呢,于是单点入口模式出现了,在网站首页的 index.php 写上每个程序都要用的部份 然后跟据某个量,比如一个 get 量来判断当前实际要执行的程序是哪一个,由 index.php 把它包含进来运行,这种由一个程序。完成所有功能的方式,称为 单点入口, 于是由这个入口程序和它对应的各个目录结构成为了一个框架。

  出于安全在包含文件的时候往往都会固定目录,不然就容易出漏洞 所以,往往会在路径头尾加个限制。例如

代码如下
include "./app/" . $_GET['url'] . ".php";
?>

那路径就只能写成类似这样index.php?url=news/list,实际包含的是 /app/news/list.php 当然了,实际的情况,还要检查一下这个程序文件是否存在之类的。

完整一点的话。我们可以这样写这个入口文件。

代码如下

//这里写绝对路径

//这里写数据库连接

//这里写模板初始化,配置

//这里判断连接变量

//这里包含文件进来运行

//这里输出模板

//这里关闭数据库
?>

一个面向过程的单点入口框架就完成了, 是不是有觉得每次都在地址栏带一个 get 不方便? 那我们可以换一个写法,例如 tp 框架最喜欢用的 http://localhost/index.php/news/list后面的 /news/list 由程序转成 php 路径包含进来就可以了。在 Apache 环境中,这个 /news/list 可以由服务器变量的 PATH_INFO 取得,如果没有的话。也可以用 REQUEST_URI 取得接近的 ,IIS 下面,有 HTTP_X_REWRITE_URL 可以取得这个值 ,自从单点入口模式出现之后,而且oop开发模式从php5开始大行其道,各种oop设计的框架让我们眼花缭乱,但是万变不离其宗,依然是什么入口方式,路径结构是什么样的,文件名的命名规则,用什么样的访问方式,可以运行哪个程序。用oop开发的框架,不外乎就是把主程序改写成为了一个类,
例如:

//包含共用文件,实例化各个类啥的
页面->初始化();

//把用户发来的网址转成要包含的路径
页面->处理网扯();

//在这里包含程序运行
页面->运行()

//输出模板
页面->输出()

各种各样的框架只是为我们准备了一个规矩罢了。。在我们的开发累计的过程中,我们常常会把一些常用的类封装成类,例如,数据库类,文件上传类,图片处理类,邮件收发类,远程访问类,各种接口类……这个时候,我们就会希望框架能给我们提供一个好一点调用类的方法, 也就是所谓的“扩展性” ,比如 TP 框架的 Db 类 。如果不用其自带的类库只用它们的核心框架,其实几个文件就够了。
TP 框架支持三种访问格式。
/news/list
/index.php/news/list
/index.php?m=news&a=list
第一种需要服务器的 urlrewrite 支持,后面两种可以直接用,
事实上,Zend 框架也差不多 文件的包含方式是。以类的形式包含,执行的其实是:/文件夹/对象/方法,这种做法有优势。因为在同一个功能中,相似的代码很多,封装到同一个类里面,可以更高效的重复使用代码 ,

比如这样

代码如下

class NewsAction {
public function head() {
在这里处理每一页头部
}

public function index() {
$this->head();
在这里处理这一页
}

public function show() {
$this->head();
在这里处理这一页
}

还可以利用构造函数等,使每一个功能,在刚进来的时候就都做了同一件事情。以上就是简单框架的理论。

制作应用原理

index.php 主入口文件

代码如下
define('ISEXIST',true);
require "init.php";
$cOntrol= new Controller();
$control -> Run();
?>

---------------------------------------------------------------------------------------------
init.php 文件

代码如下
if(!defined('ISEXIST'))
exit("请从入口文件运行程序");
header("Content-Type:text/html;charset=utf-8");

if(!defined('ROOT_PATH'))
//这里动态的声明,''是转义反斜线,默认''为转义字符
define('ROOT_PATH',str_replace('','/',dirname(__FILE__)));
require ROOT_PATH.'/a/config.php';
require ROOT_PATH.'/a/controller.class.php';
require ROOT_PATH.'/a/view.class.php';
require ROOT_PATH.'/a/model.class.php';

?>

----------------------------------------------------------------------------------------------
config.php 文件

代码如下
if(!defined('ISEXIST'))
exit("请从入口文件运行程序");
$C = array(
'URL_MODE'=>1,//url模式,1为普通模式,2为path_info模式
'DEFAULT'=>'welcome',//默认的控制器
'DEFAULT_ACTION'=>'index'//默认的方法
);
?>

-----------------------------------------------------------------------------------------------
controller.class.php 文件

代码如下
class Controller
{
public function Run()
{
$this->Analysis();
//开始解析URL获得请求的控制器和方法
$cOntrol= $_GET['con'];
$action = $_GET['act'];
$action = ucfirst($action);
//这里构造出控制器文件的路径
$cOntrolFile= ROOT_PATH . '/Controllers/' . $control . '.class.php';
if(!file_exists($controlFile)) //如果文件不存在提示错误, 否则引入
{
exit("{$control}.class.php控制器不存在
". "请检查: ".$controlFile."是否存在
");
}
include($controlFile);
$class = ucfirst($control); //将控制器名称中的每个单词首字母大写,来当作控制器的类名
if(!class_exists($class)) //判断类是否存在, 如果不存在提示错误
{
exit("{$control}.class.php中未定义的控制器类" . $class);
}
$instance = new $class(); //否则创建实例
if(!method_exists($instance, $action)) //判断实例$instance中是否存在$action方法, 不存在则提示错误
{
exit("$class类中不存在方法:". $action);
}
$instance->$action();
}



protected function Analysis()
{
//$GLOBALS['C']['URL_MODE'];
global $C; //包含全局配置数组, 这个数组是在Config.ph文件中定义的,global声明$C是调用外部的
if($C['URL_MODE'] == 1)
//如果URL模式为1 那么就在GET中获取控制器, 也就是说url地址是这种的 [url=http://localhost/index.php?c]http://localhost /index.php?c[/url]=控制器&a=方法
{
$cOntrol= !empty($_GET['con']) ? trim($_GET['con']) : '';
$action = !empty($_GET['act']) ? trim($_GET['act']) : '';
}
else if($C['URL_MODE'] == 2) //如果为2 那么就是使用PATH_INFO模式, 也就是url地址是这样的 [url=http://localhost/index.php/]http://localhost/index.php/[/url]控制器/方法 /其他参数
{
if(isset($_SERVER['PATH_INFO']))
{
//$_SERVER['PATH_INFO']URL地址中文件名后的路径信息, 不好理解, 来看看例子
//比如你现在的URL是 [url=http://www.php100.com/index.php]http://www.php100.com/index.php[/url] 那么你的$_SERVER['PATH_INFO']就是空的
//但是如果URL是 [url=http://www.php100.com/index.php/abc/123]http://www.php100.com/index.php/abc/123[/url]
//现在的$_SERVER['PATH_INFO']的值将会是 index.php文件名称后的内容 /abc/123/
$path = trim($_SERVER['PATH_INFO'], '/');
$paths = explode('/', $path);
$cOntrol= array_shift($paths);
$action = array_shift($paths);
}
}
//这里判断控制器的值是否为空, 如果是空的使用默认的
$_GET['con'] = !empty($control) ? $control : $C['DEFAULT'];
//和上面一样
$_GET['act'] = !empty($action) ? $action : $C['DEFAULT_ACTION'];
}
}
?>

--------------------------------------------------------------------------------------------------
welcome.class.php 文件

代码如下
class Welcome
{
function Index()
{
echo '欢迎使用此CMS系统';
}
function Run()
{
echo 'Hello';
}

function Show()
{
echo '方法名show';
}
}
?>

推荐阅读
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • 本文介绍了关于apache、phpmyadmin、mysql、php、emacs、path等知识点,以及如何搭建php环境。文章提供了详细的安装步骤和所需软件列表,希望能帮助读者解决与LAMP相关的技术问题。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 众筹商城与传统商城的区别及php众筹网站的程序源码
    本文介绍了众筹商城与传统商城的区别,包括所售产品和玩法不同以及运营方式不同。同时还提到了php众筹网站的程序源码和方维众筹的安装和环境问题。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
author-avatar
岁月无言0106
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有