现代php 阅读笔记,【原创】BroPHP框架阅读笔记

Ps:乡下过年回来神清气爽啊~~闲得蛋疼看看简单的框架实现。

另外也有个小小的计划了先….任何问题请轻拍。

第一遍站在开发的角度来读,主要是看功能如何实现。

第二遍站在安全的角度来读,主要是发现这样的写法有何不安全又有何好处。

当前进行:

*akcms

*kiwiphp(号称门户级的框架 – -)

计划中的:

1.Discuz(大型论坛)

2.phpbb(轻量级论坛)

3.Wordpress(传统PHP写法的Blog)

4.ThinkPHP(MVC轻量级框架的实现方式)

======================================开始-蛋疼的分割线======================================

目录结构:

│  index.php

└─brophp

│  brophp.php

├─bases  — 核心类

├─classes — 常用方法类

├─commons

│      functions.inc.php

│      success

└─libs — smarty类

———————————————————————————————–

Index.php:

define(“BROPHP”, “./brophp”);  //框架源文件的位置

define(“APP”, “./”);           //设置当前应用的目录

require(BROPHP.’/brophp.php’); //加载框架的入口文件

一个单一入口,几乎所有的框架都是这么搞貌似,至少thinkphp是这么来的。

———————————————————————————————–

brophp.php:

header(“Content-Type:text/html;charset=utf-8″);  //设置系统的输出字符为utf-8

date_default_timezone_set(“PRC”);       //设置时区(中国)

/* 这里没啥好说的,设定编码和市区 */

define(“BROPHP_PATH”, rtrim(BROPHP, '/’).’/’);     //BroPHP框架的路径

define(“APP_PATH”, rtrim(APP,’/’).’/’);            //用户项目的应用路径

define(“PROJECT_PATH”, dirname(BROPHP_PATH).’/’);  //项目的根路径,也就是框架所在的目录

define(“TMPPATH”, str_replace(array(“.”, “/”), “_”, ltrim($_SERVER["SCRIPT_NAME"], '/’)).”/”);

//script_name = /brophp/index.php

//包含系统配置文件

$config=PROJECT_PATH.”config.inc.php”;

if(file_exists($config)){

include $config;

}

//存在config.inc.php就包含,框架第一次运行会自动创建项目所需要的文件。

//设置Debug模式

if(defined(“DEBUG”) && DEBUG==1){

$GLOBALS["debug"]=1;                 //初例化开启debug

error_reporting(E_ALL ^ E_NOTICE);   //输出除了注意的所有错误报告

include BROPHP_PATH.”bases/debug.class.php”;  //包含debug类

Debug::start();                               //开启脚本计算时间

set_error_handler(array(“Debug”, 'Catcher’)); //设置捕获系统异常

}else{

ini_set('display_errors’, 'Off’);   //屏蔽错误输出

ini_set('log_errors’, 'On’);              //开启错误日志,将错误报告写入到日志中

ini_set('error_log’, PROJECT_PATH.’runtime/error_log’); //指定错误日志文件

}

/* 设定调试的相关信息 注释也很详细了 */

//包含框架中的函数库文件

include BROPHP_PATH.’commons/functions.inc.php’;

//包含全局的函数库文件,用户可以自己定义函数在这个文件中

$funfile=PROJECT_PATH.”commons/functions.inc.php”;

if(file_exists($funfile))

include $funfile;

/* 如果项目中存在的话,就会包括 commons/functions.inc.php 结合第一次自动创建项目文件,您懂得*/

//设置包含目录(类所在的全部目录),  PATH_SEPARATOR 分隔符号 Linux(:) Windows(;)

$include_path=get_include_path();                         //原基目录

$include_path.=PATH_SEPARATOR.BROPHP_PATH.”bases/”;       //框架中基类所在的目录

$include_path.=PATH_SEPARATOR.BROPHP_PATH.”classes/” ;    //框架中扩展类的目录

$include_path.=PATH_SEPARATOR.BROPHP_PATH.”libs/” ;       //模板Smarty所在的目录

$include_path.=PATH_SEPARATOR.PROJECT_PATH.”classes/”;    //项目中用的到的工具类

$controlerpath=PROJECT_PATH.”runtime/controls/”.TMPPATH;  //生成控制器所在的路径

$include_path.=PATH_SEPARATOR.$controlerpath;             //当前应用的控制类所在的目录

/* get_include_path为PHP函数,此处就是框架所在目录了,加上分隔符放到$include_path变量中 */

set_include_path($include_path);

/* 包含前面所有的文件,见PHP手册代码:

$path = '/usr/lib/pear’;

set_include_path(get_include_path() . PATH_SEPARATOR . $path);

*/

//自动加载类

function __autoload($className){

if($className==”memcache”){        //如果是系统的Memcache类则不包含

return;

}else if($className==”Smarty”){    //如果类名是Smarty类,则直接包含

include “Smarty.class.php”;

}else{                             //如果是其他类,将类名转为小写

include strtolower($className).”.class.php”;

}

Debug::addmsg(“ $className 类”, 1);  //在debug中显示自动包含的类

}

/* 然后用__autoload魔术函数自动按类名加载类,如果加载错误的话会利用debug类来输出加载错误的类文件 */

//判断是否开启了页面静态化缓存

if(CSTART==0){

Debug::addmsg(“没有开启页面缓存!(但可以使用)”);

}else{

Debug::addmsg(“开启页面缓存,实现页面静态化!”);

}

//启用memcache缓存

if(!empty($memServers)){

//判断memcache控制是否安装

if(class_exists(“memcache”)){

$mem=new MemcacheModel($memServers);

//判断Memcache服务器是否有异常

if(!$mem->mem_connect_error()){

Debug::addmsg(“连接memcache服务器失败,请检查!”); //debug

}else{

define(“USEMEM”,true);

Debug::addmsg(“启用了Memcache”);

}

}else{

Debug::addmsg(“PHP没有安装memcache扩展模块,请先安装!”); //debug

}

}else{

Debug::addmsg(“没有使用Memcache(为程序的运行速度,建议使用Memcache)”);  //debug

}

//如果Memcach开启,设置将Session信息保存在Memcache服务器中

if(defined(“USEMEM”)){

MemSession::start($mem->getMem());

Debug::addmsg(“开启会话Session (使用Memcache保存会话信息)”); //debug

}else{

session_start();

Debug::addmsg(“开启会话Session (但没有使用Memcache,开启Memcache后自动使用)”); //debug

}

/* memcache的相关设定,由于我这个也用得比较少,所以暂时先不看吧 */

Structure::create();   //初使化时,创建项目的目录结构

Prourl::parseUrl();    //解析处理URL

/* 入口点二三,需要详细再看的地方 */

//模板文件中所有要的路径,html\css\javascript\image\link等中用到的路径,从WEB服务器的文档根开始

$spath=dirname($_SERVER["SCRIPT_NAME"]);

if($spath==”/” || $spath==”\\”)

$spath=””;

$GLOBALS["root"]=$spath.’/’; //Web服务器根到项目的根

$GLOBALS["app"]=$_SERVER["SCRIPT_NAME"].’/’;            //当前应用脚本文件

$GLOBALS["url"]=$GLOBALS["app"].$_GET["m"].’/’;       //访问到当前模块

$GLOBALS["public"]=$GLOBALS["root"].’public/’;        //项目的全局资源目录

$GLOBALS["res"]=$GLOBALS["root"].ltrim(APP_PATH, './’).”views/”.TPLSTYLE.”/resource/”; //当前应用模板的资源

//控制器类所在的路径

$srccontrolerfile=APP_PATH.”controls/”.strtolower($_GET["m"]).”.class.php”;

Debug::addmsg(“当前访问的控制器类在项目应用目录下的: $srccontrolerfile 文件!”);

//控制器类的创建

if(file_exists($srccontrolerfile)){

Structure::commoncontroler(APP_PATH.”controls/”,$controlerpath);

Structure::controler($srccontrolerfile, $controlerpath, $_GET["m"]);

$className=ucfirst($_GET["m"]).”Action”;

$controler=new $className();

$controler->run();

}else{

Debug::addmsg(“对不起!你访问的模块不存在,应该在”.APP_PATH.”controls目录下创建文件名为”.strtolower($_GET["m"]).”.class.php的文件,声明一个类名为”.ucfirst($_GET["m"]).”的类!”);

}

/* 通过GET方法开始取控制器类并进行初始化等创建工作,如果出错就提示错误信息 */

//设置输出Debug模式的信息

if(defined(“DEBUG”) && DEBUG==1 && $GLOBALS["debug"]==1){

Debug::stop();

Debug::message();

}

———————————————————————————————–

框架中的commons/functions.inc.php:

p函数主要用于友好的输出调试信息,比如变量等是var_dump函数的封装

D函数用于手动实例化一个类

tosize函数是一个字节转换函数

———————————————————————————————–

然后开始批量包含文件

├─bases

│      action.class.php  //继承于MyTpl是控制器的基类

│      db.class.php //抽象类DB,数据库相关操作的基类

│      debug.class.php  //各种调试的基类

│      dmysqli.class.php //继承于DB类,数据库的mysqli驱动类

│      dpdo.class.php //继承于DB类,数据库的pdo扩展类

│      memcachemodel.class.php //memcache类,缓存SQL语句

│      memsession.class.php //memcache类,缓存session

│      mytpl.class.php  //继承于smarty类,初始化smarty成员方法等

│      prourl.class.php //url解析类

│      structure.class.php //structure类用于自动创建项目等(文件操作相关函数可以看这里)

│      validate.class.php //validate类用于检测数据有效性(xml相关操作,通过解析xml来配置验证方式)

———————————————————————————————–

├─classes

│      fileupload.class.php //继承于Image类,用于文件上传

│      image.class.php  //图片处理类,加水印与缩放等操作

│      page.class.php  //分页类

│      vcode.class.php  //验证码类

———————————————————————————————–

└─libs

│  Config_File.class.php

│  debug.tpl

│  Smarty.class.php

│  Smarty_Compiler.class.php

/* smarty */

———————————————————————————————–

批量包含文件完成之后,进行了memcache的相关操作,这里我还没有学习过,所以暂时先不看了。

接下来是调用了两个类中不同的函数。他们是

Structure::create();   //初使化时,创建项目的目录结构

Prourl::parseUrl();    //解析处理URL

———————————————————————————————–

Structure::create()位于bases/structure.class.php文件中:

此类没有构造函数,create函数是一个静态函数,代码省略部分

static function create(){

self::mkdir(array(PROJECT_PATH.”runtime/”));

//文件锁,一旦生成,就不再创建

$structFile=PROJECT_PATH.”runtime/”.str_replace(“/”,”_”,$_SERVER["SCRIPT_NAME"]);  //主入口文件名

if(!file_exists($structFile)) {

$fileName=PROJECT_PATH.”config.inc.php”;

$str=<<

……

st;

self::touch($fileName, $str);

递归调用mkdir函数,此函数循环判断$dirs数组并检测是否已经创建,输出提示信息。

先判断项目目录结构是否创建,没创建则先创建config.inc.php文件(<<

接下来给$dirs赋值,判断debug标记,并且包含刚刚创建的config.inc.php文件

省略部分代码一次类推,最后调用自身类中的 runtime()函数创建项目目录

———————————————————————————————–

Prourl::parseUrl()函数位于bases/prourl.class.php文件中:

此类没有构造函数,parseURL是一个静态函数,代码如下

if (isset($_SERVER['PATH_INFO'])){

//获取 pathinfo

$pathinfo = explode('/’, trim($_SERVER['PATH_INFO'], “/”));

// 获取 control

$_GET['m'] = (!empty($pathinfo[0]) ? $pathinfo[0] : 'index’);

array_shift($pathinfo); //将数组开头的单元移出数组

// 获取 action

$_GET['a'] = (!empty($pathinfo[0]) ? $pathinfo[0] : 'index’);

array_shift($pathinfo); //再将将数组开头的单元移出数组

for($i=0; $i

$_GET[$pathinfo[$i]]=$pathinfo[$i+1];

}

}else{

$_GET["m"]= (!empty($_GET['m']) ? $_GET['m']: 'index’);    //默认是index模块

$_GET["a"]= (!empty($_GET['a']) ? $_GET['a'] : 'index’);   //默认是index动作

if($_SERVER["QUERY_STRING"]){

$m=$_GET["m"];

unset($_GET["m"]);  //去除数组中的m

$a=$_GET["a"];

unset($_GET["a"]);  //去除数组中的a

$query=http_build_query($_GET);   //形成0=foo&1=bar&2=baz&3=boom&cow=milk格式

//组成新的URL

$url=$_SERVER["SCRIPT_NAME"].”/{$m}/{$a}/”.str_replace(array(“&”,”=”), “/”, $query);

header(“Location:”.$url);

}

}

ps:待细看…

———————————————————————————————–

同时在操作控制器类时候调用了Structure::commoncontroler和Structure::controler,我们再回到

structure.class.php文件中看看他们是如何工作的:

static function commoncontroler($srccontrolerpath,$controlerpath){

$srccommon=$srccontrolerpath.”common.class.php”;

$common=$controlerpath.”common.class.php”;

//如果新控制器不存在, 或原控制器有修改就重新生成

if(!file_exists($common) || filemtime($srccommon) > filemtime($common)){

copy($srccommon, $common);

}

}

如果原项目目录(框架目录)中存在controls/common.class.php,且新项目路没得就拷贝过去。

static function controler($srccontrolerfile,$controlerpath,$m){

$controlerfile=$controlerpath.strtolower($m).”action.class.php”;

//如果新控制器不存在, 或原控制器有修改就重新生成

if(!file_exists($controlerfile) || filemtime($srccontrolerfile) > filemtime($controlerfile)){

//将控制器类中的内容读出来

$classContent=file_get_contents($srccontrolerfile);

//看类中有没有继承父类

$super=’/extends\s+(.+?)\s*{/i’;

//如果已经有父类

if(preg_match($super,$classContent, $arr)) {

$classContent=preg_replace('/class\s+(.+?)\s+extends\s+(.+?)\s*{/i’,’class \1Action extends \2 {',$classContent);

//新生成控制器类

file_put_contents($controlerfile, $classContent);

//没有父类时

}else{

//继承父类Common

$classContent=preg_replace('/class\s+(.+?)\s*{/i’,’class \1Action extends Common {',$classContent);

//生成控制器类

file_put_contents($controlerfile,$classContent);

}

}

}

也是用于生成项目中的控制器类的函数的,有详细注释。

———————————————————————————————–

基本上bropphp.php的几个关键地方都看完了,这也算是框架的入口点,这时访问index.php结合刚才阅读

structrue.class.php中的相关函数,框架就会自动创建项目所需的文件和目录结构了(和ThinkPHP好像~)

创建目录 ./runtime/ 成功.

创建文件 ./config.inc.php 成功.

创建目录 ./classes/ 成功.

创建目录 ./commons/ 成功.

创建目录 ./public 成功.

创建目录 ./public/uploads/ 成功.

创建目录 ./public/css/ 成功.

创建目录 ./public/js/ 成功.

创建目录 ./public/images/ 成功.

创建目录 ./models/ 成功.

创建目录 ./controls/ 成功.

创建目录 ./views/ 成功.

创建目录 ./views/default 成功.

创建目录 ./views/default/public/ 成功.

创建目录 ./views/default/resource/ 成功.

创建目录 ./views/default/resource/css/ 成功.

创建目录 ./views/default/resource/js/ 成功.

创建目录 ./views/default/resource/images/ 成功.

创建文件 ./commons/functions.inc.php 成功.

创建文件 ./controls/common.class.php 成功.

创建文件 ./controls/index.class.php 成功.

———————————————————————————————–

项目目录结构如下:

│  config.inc.php

│  index.php

├─classes

├─commons

│      functions.inc.php

├─controls

│      common.class.php

│      index.class.php

├─models

├─public

│  ├─css

│  ├─images

│  ├─js

│  └─uploads

├─runtime

│  │  error_log

│  │  _brophp_index.php

│  │

│  ├─cache

│  │  └─default

│  ├─comps

│  │  └─default

│  │      └─brophp_index_php

│  ├─controls

│  │  └─brophp_index_php

│  │          common.class.php

│  │          indexaction.class.php

│  │

│  ├─data

│  └─models

│      └─brophp_index_php

└─views

└─default

├─public

│      success.tpl

└─resource

├─css

├─images

└─js

———————————————————————————————–

(话说还有action等基本操作没有分析的啊…下回再慢慢看吧….)

———————————————————————————————–

可以说基本该分好都分好,至于什么用它创建项目,框架中有无漏洞等,就等下回继续分解了。

有空再看吧。虽说是发现了类似思想,是eval使用函数而导致的,下回分解欢迎拍砖. :0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值