主要:

  1. 常量优化路径
  2. 自动加载类
  3. 优化入口文件
  4. 安全访问项目目录

--------------文件结构:--------------------------------------
blog
├─App
│  ├─Model 模型
│  │  └─UserModel.class.php 用户模型类    
│  ├─View 视图
│  │  ├─Back后台
│  │  │  └─Index
│  │  │          └─index.html  后台首页面
│  │  └─Home前台
│  │      └─User 用户视图目录
│  │             └─login.html  登录表单页面
│  ├─Controller 控制器
│  │  ├─Back后台
│  │  │  └─IndexController.class.php 后台首页控制器
│  │  └─Home前台
│  │      └─UserController.class.php 用户控制器
├─Public   静态公共文件(js,css,images)
│  ├─Plugins 插件
│  │  └─layui 前端框架插件
│  ├─Back后台
│  │    ├─js/   js文件
│  │    ├─css/  css样式文件
│  │    └─image img图片
│  └─Home前台
│      ├─js/   js文件
│      ├─css/  css样式文件
│      └─image img图片
├─Frame 公共使用的类
│   ├─BaseModel.class.php 数据库连接类
│   ├─BaseController.class.php 控制器公共操作(设置编码,信息跳转)
│   ├─FactoryModel.class.php  模型工厂类
│   ├─Init.class.php  初始化应用类
│   └─MySQLDB.class.php 数据库操作工具类
└─index.php  入口文件
-----------------------------------------------------------------

上一篇中,提出4个问题待解决,本篇集中解决这4个问题,最终形成完整的微型MVC框架结构, 后续博客项目,或其他项目,均可以直接使用该框架结构进行开发学习。

下载查看该项目源码: https://gitee.com/NewbiesYang/young_blog

常量优化路径

准备: 创建分支

 $ git checkout master
$ git checkout -b "MVC"

  思路

  1)把常用的目录路径定义成常量。如 模型目录,控制器目录等
     2)引入类使用定义的常量替代部分路径。 如 include FRAME.BaseModel.class.php
       3) 载入视图使用常量替代部分路径 如 include VIEW.'login.html' 简单形式

  代码实现

1)操作步骤

step 1: 在入口文件中定义所需要的常量

step 2: 控制器中引入视图时, 使用常量进行优化 

操作步骤思路

2) 入口文件中定义常用路径常量 【index.php】

 <?php
/**
* 入口文件
*/
$p = !empty($_GET['p']) ? $_GET['p'] : 'Home'; //平台
$c = !empty($_GET['c']) ? $_GET['c'] : 'User'; //控制器
$a = !empty($_GET['a']) ? $_GET['a'] : 'login'; //动作 define('PLAT', $p); //平台常量
define('CTR', $c); //控制器
define('ACTION', $a); //动作 define('DS', DIRECTORY_SEPARATOR); //目录分割符
define('ROOT', getcwd().DS); //当前所在目录 项目目录
define('FRAME', ROOT.'Frame'.DS);
define('APP', ROOT.'App'.DS);
define('PUB', ROOT.'Public'.DS);
define('ADMIN', PUB.'Admin'.DS);
define('HOME', PUB.'Home'.DS); //MVC目录
define('MODEL', APP.'Model'.DS);
define('VIEW', APP.'View'.DS.PLAT.DS.CTR.DS);
define('CTRONLLER', APP.'Controller'.DS.PLAT.DS); $ctr = $c."Controller"; require_once FRAME.'Db.class.php'; //数据库操作类
require_once FRAME.'BaseModel.class.php'; //基础模型类
require_once MODEL.'UserModel.class.php'; //用户模型类
require_once FRAME.'FactoryModel.class.php';//模型工厂类
require_once FRAME.'BaseController.class.php'; //基础控制器类
require_once CTRONLLER.$ctr.'.class.php'; //实例化控制器
$userCtr = new $ctr(); $userCtr -> $a();

2) 常量的使用:

  后台首页控制器【App/Controller/Admin/IndexController.class.php】

 <?php
/**
* IndexController控制器类
* 后台相关操作
* User: young
*/ class IndexController extends BaseController
{
//展示后台首页
public function index()
{
include VIEW.'index.html';
}
}

后台首页控制器引入视图路径修改

  用户控制器 登录视图引入路径【App/Controller/Home/UserController.class.php】

 <?php
/**
* UserController.class.php 用户控制器
*/ class UserController extends BaseController{
/**
* 展示登录界面
* @access public
*/
public function login()
{
include VIEW."login.html";
}
。。。
。。。
。。。

用户控制器登录视图引入路径

3)提交代码

$  git add -A
$ git commit -m "常量使用"

自动加载类

  思路

  问题: 入口文件中已经require_once 引入6个类,既增加一个需要引入一个,容易遗漏,重复和出错。

  解决方法:自动加载类文件

     方式1: 使用自动加载类函数__autoload()可以实现自动加载
          方式2: 实际项目中,多人开发,根据实用性,更多的是使用 sql_autoload_register()注册函数自动加载

  根据目录的特点实现自动加载
          Model类文件特点,以Model结尾的类名  substr($className,-5)
          Controller文件特点: 以Controller结尾的类名, substr($class,-10)

    公共类: 类名没有统一形式,可以将Fame下的公共类放入到数组中,然后判断类是否在数组中, 从而自动加载该目录下的类文件

  代码实现

  1) 入口文件实现类的自动加载

 <?php
/**
* 入口文件
*/
$p = !empty($_GET['p']) ? $_GET['p'] : 'Home'; //平台
$c = !empty($_GET['c']) ? $_GET['c'] : 'User'; //控制器
$a = !empty($_GET['a']) ? $_GET['a'] : 'login'; //动作 define('PLAT', $p); //平台常量
define('CTR', $c); //控制器
define('ACTION', $a); //动作 define('DS', DIRECTORY_SEPARATOR); //目录分割符
define('ROOT', getcwd().DS); //当前所在目录 项目目录
define('FRAME', ROOT.'Frame'.DS);
define('APP', ROOT.'App'.DS);
define('PUB', ROOT.'Public'.DS);
define('ADMIN', PUB.'Admin'.DS);
define('HOME', PUB.'Home'.DS); //MVC目录
define('MODEL', APP.'Model'.DS);
define('VIEW', APP.'View'.DS.PLAT.DS.CTR.DS);
define('CTRONLLER', APP.'Controller'.DS.PLAT.DS); $ctr = $c."Controller"; spl_autoload_register('autoload'); //注册自动加载函数
//自动加载类
/**
* 实自动加载类文件
* @param string $className 类名
*/
function autoload($className)
{
$upperClassName = strtoupper($className);
$frame = array('BaseController','BaseModel','Db','FactoryModel');
if(in_array($className, $frame)) { //加载公共Frame目录中的类文件
require_once FRAME."$className.class.php";
} elseif(substr($upperClassName, -5) == 'MODEL'){ //加载模型Model目录中的类文件
require_once MODEL."$className.class.php";
} elseif(substr($upperClassName, -10) == 'CONTROLLER'){ //加载控制器目录中的类文件
require_once CTRONLLER."$className.class.php";
}
} //实例化控制器
$userCtr = new $ctr();
$userCtr -> $a();

2) 提交代码

 $  git add -A
$ git commit -m "自动加载类完成"

优化入口文件

  思路

  问题: 此时,入口文件代码零碎增多,随着后续代码的增加,入口文件会更加臃肿复杂,不易管理

  解决方法: 封装入口文件中的操作称为一个类,这样只需要在入口文件调用类的方法即可

    创建Init.class.php类文件,放入到Frame中
         将入口文件所有操作封装成类方法
              loadClass() 设置自动加载函数
              autoload()自动加载类
              setConst()  定义常量
              dispatch()  前端分发器

  代码实现

  1) 在Frame目录中创建Init.class.php文件, 将入口文件index中的代码复制进行修改为类

  【Frame/Init.class.php】

 <?php
/**
* 应用初始化操作类
* User: young
*/ class Init
{
protected static $frame = array('BaseController','BaseModel','Db','FactoryModel'); //Frame目录公共操作类
public static function run()
{
//平台
self::dispatch(); //定义常量
self::setConst(); //自动加载类
self::loadClass(); $ctr = CTR."Controller"; //拼接控制器名称 //实例化控制器
$ctrObj = new $ctr();
$a = ACTION;
$ctrObj -> $a();
}
/**
* 设置自动加载类方法
*/
private static function loadClass()
{
spl_autoload_register('self::autoload');
} /**
* 实现自动加载
* @param string $className 类名
*/
private static function autoload($className)
{
$upperClassName = strtoupper($className);
if(in_array($className, static::$frame)) {
require_once FRAME."$className.class.php";
} elseif(substr($upperClassName, -5) == 'MODEL'){
require_once MODEL."$className.class.php";
} elseif(substr($upperClassName, -10) == 'CONTROLLER'){
require_once CTRONLLER."$className.class.php";
}
} /**
* 定义常量
*/
private static function setConst()
{
define('DS', DIRECTORY_SEPARATOR); //目录分割符
define('ROOT', getcwd().DS);
define('FRAME', ROOT.'Frame'.DS);
define('APP', ROOT.'App'.DS);
define('PUB', ROOT.'Public'.DS);
define('ADMIN', PUB.'Admin'.DS);
define('HOME', PUB.'Home'.DS); define('MODEL', APP.'Model'.DS);
define('VIEW', APP.'View'.DS.PLAT.DS.CTR.DS);
define('CTRONLLER', APP.'Controller'.DS.PLAT.DS);
} /**
* 获取 p c a 的GET值,并设置为常量
* @return void
*/
private static function dispatch()
{
$p = !empty($_GET['p']) ? $_GET['p'] : 'Home'; //平台
$c = !empty($_GET['c']) ? $_GET['c'] : 'User'; //控制器
$a = !empty($_GET['a']) ? $_GET['a'] : 'login'; //动作 define('PLAT', $p);
define('CTR', $c);
define('ACTION', $a);
}
}

2) 入口文件引入初始化类,并调用其方法 【index.php】

 <?php
/**
* 入口文件
*/ require_once './Frame/Init.class.php';
Init::run();

3) 提交代码

 $  git add -A
$ git commit -m "优化入口文件,封装初始化类"

安全访问项目目录

  思路

  问题: 此时,项目中所有目录都是可以通过浏览器访问的,如直接访问Frame/Db.class.php文件 直接可以去查看数据库登录信息,显然是不安全的。

  解决方法:

    方式1: 在可以访问的文件开始处定义常量,访问是判断是否定义常量defined(..), 没有定义指定常量则直接exit('Access Deny');

    方式2: 开启分布式权限配置,编写.htaccess文件, 如禁止访问, 将该文件放置在禁止访问的目录中

   实现

  1)使用上述方式2的形式来实现, 站点配置中加入一项(环境搭建时已经加入了): 详细见:PHP源码搭建博客1-环境搭建

  apache配置文件httpd-vhosts.conf 中站点配置

  #允许分布式权限配置(允许重写)(.htacess)
AllowOverride All

  2) 重启apache后,编写 .htaccess文件, 该文件内容:

deny from all

  3) 将.htaccess文件放置禁止访问的目录中。  如App/ ,  Frame/ 目录下。只用放在第一层即可,内层目录自动不允许直接访问。

  4) 访问测试

小结:

主要实现了 引入路径优化, 类的自动加载, 封装优化入口文件,目录访问限制

MVC微型框架到此基本完成。其实还有很多还是可以继续扩展,如

  1, 类文件命名此处都用了 .class.php结尾, 实质可以优化直接使用.php结尾

  2, 引入命名空间,更方便的加载类

3, 项目中出现错误,此时是直接显示在浏览器上的, 可以写一个日志类,发生错误写入文件或数据库都可

  4, 数据库连接信息此处是直接写在DB类和BaseModel中了, 是不安全的。 可以创建一个配置目录,将这些信息写入配置文件,再写一个加载配置文件的类。

  5.   此架构目录 ,是在C,V中分平台,如Controller/Home, Controller/Admin;  实际也可以写成 平台下分MVC结构, 如Admin/Controller, Admin/Model, Home/Controller,Home/View ..  这个是比较灵活的,可以根据需求选择更加合适的方式

  实际上线项目,还是建议使用框架,安全快捷; 自己模仿定义的框架结构适合学习研究使用,容易遗漏,造成安全隐患,操作不便等问题

下一步:根据博客前端模板,分析创建数据表, 开始搭建博客后台程序,后续首先准备实现 “分类模块”。既分类的展示,修改,添加,删除功能

php源码建博客4--实现MVC结构微型框架的更多相关文章

  1. php源码建博客5--建库建表-配置文件-错误日志

    主要: 整理框架 建库建表 配置文件类 错误日志记录 --------------本篇后文件结构:-------------------------------------- blog ├─App │ ...

  2. php源码建博客3--区分平台的MVC结构

    主要: 模型单例工厂 目录结构优化 区分平台(前台,后台....) --------------文件结构:-------------------------------------- blog├─Ap ...

  3. php源码建博客2--实现单入口MVC结构

    主要: MVC目录结构 数据库工具类制作 创建公共模型类和公共控制器类 --------------文件结构:-------------------------------------- blog├─ ...

  4. php源码建博客1--搭建站点-实现登录页面

    主要: 站点搭建 实现登录页面 分析及改进 站点搭建 1)  在apache安装目录下: [conf\extra\httpd-vhosts.conf]加入站点配置 <VirtualHost *: ...

  5. spark 源码阅读博客

    http://blog.csdn.net/oopsoom/article/details/38257749

  6. 00-django | 01-构建博客目录

    00-django | 01-构建博客目录 python Django 创建blog 进入到 manage.py 文件所在的目录(即项目根目录)下,运行 pipenv run python manag ...

  7. 用hugo建博客的记录 · 老张不服老

    前后累计折腾近6个小时,总算把搭建hugo静态博客的整个过程搞清楚了.为什么用了这么久?主要还是想偷懒,不喜欢读英文说明.那就用中文记录一下过程吧.还是中文顺眼啊. 某日发现自己有展示些东西给外网的需 ...

  8. MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)

    前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...

  9. MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)

    前言:最近一段时间在学习MVC源码,说实话,研读源码真是一个痛苦的过程,好多晦涩的语法搞得人晕晕乎乎.这两天算是理解了一小部分,这里先记录下来,也给需要的园友一个参考,奈何博主技术有限,如有理解不妥之 ...

随机推荐

  1. C#复制粘贴

    用C#程序复制粘贴非常简单,这里为了实用,只介绍对文字的操作,其他情况类似: Clipboard.SetText(“我是需要复制到系统剪贴板的文字”); 执行以上代码后,即可ctrl+V进行粘贴.是不 ...

  2. PowerDesigner表设计转化为excel或者markdown

    本文目的:知道有这种能够写脚本的方式减少工作量 写VBS脚本 导出

  3. The categories of Reinforcement Learning 强化学习分类

    RL分为三大类: (1)通过行为的价值来选取特定行为的方法,具体 包括使用表格学习的 q learning, sarsa, 使用神经网络学习的 deep q network: (2)直接输出行为的 p ...

  4. [EffectiveC++]item34:区分接口继承和实现继承

    [EffectiveC++]item34:区分接口继承和实现继承

  5. NET Core Web API下事件驱动型架构CQRS架构中聚合与聚合根的实现

    NET Core Web API下事件驱动型架构在前面两篇文章中,我详细介绍了基本事件系统的实现,包括事件派发和订阅.通过事件处理器执行上下文来解决对象生命周期问题,以及一个基于RabbitMQ的事件 ...

  6. JavaScript的DOM_获取和操作层次节点

    一.层次节点的概述 节点的层次结构可以划分为:父节点与子节点.兄弟节点这两种.当我们获取其中一个元素节点的时候,就可以使用层次节点属性来获取它相关层次的节点. 二.childNodes 属性 chil ...

  7. Android HttpClient自己主动登陆discuz论坛!

    你登陆论坛的时候,我们先看看浏览器干了什么事儿: 用Firefox打开HiPda 的登陆页面,输入用户名和password,点登陆. 以下是通过firebug插件获取的数据: 能够看到浏览器这个htt ...

  8. PHP中__get()和__set()的用法实例详

    刚刚看到一个对我有用的文章,我就把它摘抄下来了.                                                                        php面 ...

  9. Linux学习总结(十四) 文件的打包和压缩

    文件的压缩和打包,在windos下我们很熟悉.rar和.zip文件,这是两种压缩文件,他们支持单个文件和多个文件的压缩.windos下我们不提及打包的概念,虽然多个文件的压缩肯定存在打包过程.打包和压 ...

  10. MyBatis(8)延迟加载&缓存

    什么是延迟加载? resultMap可以实现高级映射,association,collection具有延迟加载的功能.   当我们需要查询某个信息的时候,再去查询,达到按需查询,就是延迟加载   可以 ...