内容简介:控制器的作用是作为模型于视图之间的桥梁,细分的话有两个创建模型类时时按照表划分的,也就是说一张表对应一个模型类创建控制器则应该按照功能划分,如以前编写的博客系统,后台有模块“博客管理”、“类别管理”、“评论 管理”,我们则应该每个模块对应一个控制器
1. 概念
控制器的作用是作为模型于视图之间的桥梁,细分的话有两个
- 获取视图提交的数据,转发给模型
- 获取模型的数据,转发给视图
创建模型类时时按照表划分的,也就是说一张表对应一个模型类
创建控制器则应该按照功能划分,如以前编写的博客系统,后台有模块“博客管理”、“类别管理”、“评论 管理”,我们则应该每个模块对应一个控制器
2. 创建控制器
控制器类应该创建在controller 目录下,每个类就是一个控制器,我们称为控制器类
控制器文件的命名规范
1)功能名称+Controller.class.php
2)控制器名称也采用大驼峰写法,如UserController、NewsTypeController
3)控制器中的方法使用小驼峰写法,如 selectAction、getInsertIdAction
4)如上,方法名称后面加上Action后缀
2.1 创建UserController
创建一个控制器,用于管理所有的用户数据
在controller下创建UserController.class.php 文件
在控制器中编写方法,用于向users表中添加数据
<?php class UsersController { public function addAction() { require_once 'model/Factory.class.php'; $model = Factory::M("UsersModel"); $model->users_add(); } }
我们发现,控制器中的addAction 方法调用了模型类中的users_add方法
这就是我们前面所说的:模型类负责与数据库交互,控制器负责调用模型类
为了更加清晰的理解控制器与模型的关系,在控制器中再编写一个用于查询的方法
public function selectAction() { require_once 'model/Factory.class.php'; $model = Factory::M("UsersModel"); $users = $model->users_select(); var_dump($users); }
控制器中的selectAction 方法调用了模型中的方法获取数据库中的数据,这也是控制器调用模型类获取数据的经典案例
为了查看效果,我们运行当前的程序,调用控制器的方法,看看结果
问题来了?我们在浏览器中怎么输入地址呢?直接访问控制器类?绝对不行的。
解决方案是,在网站根目录下创建一个 php 文件,可以命名为 index.php
我们在浏览器中访问这个文件,然后在这个文件中,实例化控制器类,再调用控制器中的方法
require_once 'controller/UsersController.class.php'; $controller = new UsersController(); $controller->addAction();
查看数据库,一条记录被保存到数据库中、
修改代码,改为调用select方法查询数据库的数据
require_once 'controller/UsersController.class.php'; $controller = new UsersController(); $controller->selectAction();
2.2 路径问题
先不忙着仿照UsersController类创建另外的两个控制器
2.2.1 当前的问题
上面代码中,我们在控制器中引入了模型中的Factory.class.php文件
require_once 'model/Factory.class.php';
但是观察一下当前的目录结构
发现,UsersController和Factory.class.php 分布在两个目录下,所以按照正常的写法应该是
require_once '../model/Factory.class.php';
但这种写法是无法被正确加载的
原因在于,index.php 是我们在浏览器中访问的文件,在这个文件中引入了 UsersController.class.php
require_once 'controller/UsersController.class.php';
我们讲过,所谓引入和包含,其实就是将这个文件中的代码全部拷贝一份到当前文件中,也就是拷贝到了index.php 中,所以,UsersController中引入其他文件时,应该时站在index.php的角度,所以使用下面的方式引入
require_once 'model/Factory.class.php';
其实,我们发现,这种方式进行文件引入和包含,路径很容易写错,而且我们当前还有一个隐藏的问题,就是Factory类中的如下代码
因为Factory.class.php文件在model目录下,所以这里的引用都是相对于model目录的
这在我们工厂类创建魔形类的对象时没有问题
$model = Factory::M("UsersModel");
但使用工厂类创建控制器类,就会出错,修改index.php 代码
运行就会出现错误
总结一句话,我们当前引入文件的方式是有问题的,有没有一种稳妥的方式呢?
2.2.2 解决方法
绝对路径+自动加载
首先换成绝对路径
绝对路径就是带盘符的路径
具体方法是在index.php文件中,声明常量用来存储index.php文件的目录,也就是当前网站的根目录
define("APP_PATH",__DIR__."/"); echo APP_PATH;
输出结果为:
D:\phpStudy\PHPTutorial\WWW\testMVC/
然后在所有文件中,凡是引入文件的地方,全部都使用绝对路径的方式拼接,这样就不用考虑当前文件和被引用文件的位置关系了
如UserController中
require_once APP_PATH.'model/Factory.class.php';
引入时只需要知道 model目录与 网站根目录的关系即可,不需要再考虑UsersController.class.php与UsersModel.class.php的关系了
但是这仍然没有解决使用工厂类无法创建控制器对象的问题
当然可以使用判断的方式解决
将Factory类的M方法更改如下,在包含文件前,先根据关键词进行判断
public static function M($classname) { static $model_list = []; if (!isset($model_list[$classname])) { if (strpos($classname,"Controller")){ require_once APP_PATH."controller/".$classname.".class.php"; }else{ require_once APP_PATH."model/".$classname.".class.php"; } $model_list[$classname] = new $classname(); } return $model_list[$classname]; }
然后index.php中修改代码如下,使用工厂类创建类的对象
define("APP_PATH",__DIR__."/"); require_once APP_PATH.'model/Factory.class.php'; $controller = Factory::M("UsersController"); $controller->selectAction();
现在使用自动加载解决遍布各处的文件引入代码
修改index.php
define("APP_PATH",__DIR__."/"); /*require_once APP_PATH.'model/Factory.class.php';*/ function load1($classname){ $file=APP_PATH."controller/".$classname.".class.php"; if (file_exists($file)){ require_once $file; } } function load2($classname){ $file=APP_PATH."model/".$classname.".class.php"; if (file_exists($file)){ require_once $file; } } spl_autoload_register("load1"); spl_autoload_register("load2"); $controller = Factory::M("UsersController"); $controller->selectAction();
然后删除各个文件中的文件引入代码,包含Factory中的M类
public static function M($classname) { static $model_list = []; if (!isset($model_list[$classname])) { $model_list[$classname] = new $classname(); } return $model_list[$classname]; }
但是Model.class.php 中的引入保留,或者再加入一个自动加载类函数
测试程序能够正常运行
2.3 编写其他控制器类
仿照UsersController 类编写另外两个类的代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 自定义MVC框架-封装控制器基类
- iOS之导航返回上上个控制器或指定返回某个控制器
- iOS小技巧·把子视图控制器的视图添加到父视图控制器
- javascript – AngularJS控制器错误 – :$http.get不是控制器部分的函数
- AC敏捷控制器及准入控制技术对比
- angularjs – 使用ui-router时,控制器是否可以从父控制器继承范围
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。