控制器
Posted qiqideya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了控制器相关的知识,希望对你有一定的参考价值。
?www.mengyunzhi.com
本文档使用 看云 发布
间接读取数据
直接读取数据虽然简单易懂,但往往在大型的项目中却并不适用。如果实现一个功能,我们把所有的代码都写在一个方法中,显然当功能复杂时,代码就会越来越长,越来越难以维护。这显然不是我们想看到的。
基于此,我们有了数据库M层,一个专门为我们处理数据表的文件。
M 数据模型层
没有M层以前我们取数的过程是这样的。
有了M层以后,我们取数的过程变成了这样。
是的,你想的没错,在小型的项目,或是我们这个教程中,这样做的确是画蛇添足了。但是我们的目标,并不仅仅满足于做小项目。后面你将会一点点的感受到分层的魅力。
调用谁,你就要USE谁
我们再看前面写过的代码:
如果删除或注释掉第3行。
就会报如下错误:
报错信息中提示这个类 ‘app\index\controller\DB‘ 没有找到。
原因就是我们在用Db类以前,没有告诉程序这个正确的Db类在哪个位置,怎么告诉呢?利用的就是USE。
那我们说,你怎么就知道要这么use呢?
我们先看一下,Db这个类到底在哪。
其实它在哪并不要紧,php中有一个叫命名空间的东西,至于怎么工作的,有兴趣的GOOGLE吧。我们只需要知道它叫命名空间就可以了。如下图所示:
命名空间,可以简单的理解为:我住哪。
我们看到Db这个类,它住在了think
中,它的名字叫Db
,所以别人想找它帮忙的时候,只需要use think\Db;
就可以了。
当然了,我们自己写的类,由于也有命名空间,别人也可以通过我们的类住在哪,叫什么名字,来use我们的文件。
其实想搞清楚命名空间这个神奇的东西并不容易,所以搞不太清楚没有关系,我们现在只需要知道 调用谁,就USE谁 ,就可以了。慢慢的,我们会一点点的明白什么是命名空间。
调用M层,我们就要USE M层
建立M层文件
上面我们是使用了Db这个类,这次我们放弃Db类。在实际的开发过程中,大多数的数据表都是固定的(有些项目需要动态生成数据表),所以我们也很少会去用这个Db类。基于此,我们对Db类的了解,到此为止。
这次我们引用think内置的一个类think\Model,这个类中封装好了所有的数据库操作方法。我们将采用继承的方法,如果现在不太清楚什么是继承,可以直接往下看,但我们有必要去学一学C++了。
代码如下:
<?php
namespace app\model;
use think\Model; // 使用前进行声明
/**
* Teacher 教师表
*/
class Teacher extends Model
{
}
我们再来巩固一下这个namespace,叫做命名空间的东西。
app\model; 是指这个文件位于application文件夹下的model文件夹中。
所以当我们看到以app打头的命名空间时,也就相当于告诉了我们这个文件位于哪个位置。
是的,不仅仅我们在调用这个类之前需要进行use,我们在继承一个类之前也需要use。
调用Teacher.php 模型文件
我们先回到C层,即controller文件夹下,对原Teahcer.php进行重新编辑,去除对Db类的调用。
我们需要记往一点,只有controller文件夹下的文件,才可以通过URL访问的到。其它的文件,比如我们刚刚新建的这个M层的Teacher.php,是直接访问不到的。
删除冗余的代码后如下:
<?php
namespace app\index\controller;
/**
* 教师管理
*/
class Teacher
{
public function index()
{
echo "hello teacher";
}
}
输入URL进行测试结果显示如下:
下面,我们正式调用Teacher模型。
1、先use;
2、再调用。
示例代码如下:
<?php
namespace app\index\controller;
use app\model\Teacher; // 教师模型
/**
* 教师管理
*/
class Teacher
{
public function index()
{
$Teacher = new Teacher;
dump($Teacher);
}
}
经测试,我们将得到如下错误提示:
git checkout step3.2.4.1
执行上述命令后,上述示例代码信息如下:
提示:不能重新声明app\index\controller\Teacher这个类,原因是由于这个类已经存在。
每个班级里面只能有一个小明,如果存在两个小明,那么他们肯定有一个是大小明,另一个是小小明。因为只有这样,当老师点名的时候,才会有唯一的学生站出来。这个故事告诉我们,同一个文件中,如果有两个类的名字相同,是会发生错误的。
上述错误的原因,是由于这两个人起的名字相同的。
我们把这两个文件拿出,发现还真是这样。
解决方法1
为引用的那个Teacher 改个名字
<?php
namespace app\index\controller;
use app\model\Teacher as SmallTeacher; // 教师模型 带有别名
/**
* 教师管理
*/
class Teacher
{
public function index()
{
$SmallTeacher = new SmallTeacher;
dump($SmallTeacher);
}
}
git checkout step3.2.4.2
执行上述命令后,上述示例代码信息如下:
解决方法2,更改thinkphp的命名规则,不给他们发生冲突的机会。
1、修改config.php
在config.php增加如下语句:
‘controller_suffix‘ => true,
修改后如下图所示:
一个新的问题产生了,为什么这个文件就没有命名空间呢?
是的,它是没有,因为我们也没有看到里面有Class的字样呀,既然它不是一个Class(类),没有就是正常的。
2、修改原来C层的文件名
Teacher.php -> TeacherController.php
当然了,如果以前的Index控制器,你还在使用的话,也是需要修改的。
修改后如图所示:
这时候,C层的类名字叫做TeacherController,M层的叫做Teacher,两个名字不一样了,当然也就不需要使用别名了。
刷新URL进行测试:
如果你见到如下错误,说明我们的config.php中的配置信息没有起作用,请检查拼写是否有错误,文件是否进行保存等。
如果你见到如下错误:
我们看到,thinkphp已经在尝试调用TeacherController了。那么,说明我们的config.php的配置信息已经配置正确,我们需要在命名空间、文件名和类名三个方面下手去找问题。
我们在以后的学习中,还会遇到上述错误,找问题的方向也是围绕命名空间、文件名、类名三个方面。
需要重点检查的项如下图所示:
由于此次我们并没有变动文件的位置,所以命名空间可以确定是没有问题的。那么问题就应该出现在文件名和类名上了。
正确的测试结果如下图所示:
我们看到,第一行提示说在debug文件的161行。显然,我们更希望看到的是在TeacherController文件的第12行,这是由于我们使用了thinkphp内置的dump()方法造成的。在以后的教程中,如果我们在其它的历史项目中看到这个函数,知道它等于var_dump()就可以了。在以后的项目或是教程中,我们将弃用dump()函数,一律改为var_dump()。
修改后代码如下:
<?php
namespace app\index\controller;
use app\model\Teacher; // 教师模型
/**
* 教师管理
*/
class TeacherController
{
public function index()
{
$Teacher = new Teacher;
var_dump($Teacher);
}
}
测试结果:
git checkout step3.2.4.3
执行上述命令后,上述示例代码信息如下:
我们看到$Teacher变量的类型是一个object,这个对象的原型是app\model\Teacher。没错,的确是我们引入的那个原型。
主角登场
使用select()来获取数据库中的信息。
<?php
namespace app\index\controller;
use app\model\Teacher; // 教师模型
/**
* 教师管理
*/
class TeacherController
{
public function index()
{
$Teacher = new Teacher;
$teachers = $Teacher->select();
var_dump($teachers);
}
}
测试结果:
git checkout step3.2.4.4
执行上述命令后,上述示例代码信息如下:
我们看到返回值是个数组,这个数组的第0项是一个对象,第1项也是个对象。这两个对象都是基于app\model\Teacher这个类创建的。也就是说,这个对象中除了那些被var_dump()出来的变量以外,还有一些没有被var_dump()出来的方法可以供我们使用。
其实现在我们已经很清楚了,我们并没在app\model\Teacher中写任何代码,那么这些保护类型的私有属性是怎么来的呢?这当然是由于它继承了一个叫做think\Model类的原因了。我们说你自己是没有,但是你父类有就和你有是一样的。因为我们的继承中规定,在父类中所有的protected和public的变量或方法,都是可以被子类直接使用的。
那么好,我们现在就找一个think\Model中的方法,我们调用一下看看。
我们找到第180行的获取对象原始数据的方法。
如下:
/**
* 获取对象原始数据
* @access public
* @param string $name 字段名 留空获取全部
* @return array
*/
public function getData($name = ‘‘)
{
return array_key_exists($name, $this->data) ? $this->data[$name] : $this->data;
}
在此,不得不说:越是技术牛气的人,代码越是规范!
想成为技术大牛吗?从规范代码做起!
修改C层代码:
<?php
namespace app\index\controller;
use app\model\Teacher; // 教师模型
/**
* 教师管理
*/
class TeacherController
{
public function index()
{
$Teacher = new Teacher;
$teachers = $Teacher->select();
// 获取第0个数据
$teacher = $teachers[0];
// 调用上述对象的getData()方法
var_dump($teacher->getData());
}
}
测试结果如下:
为getData()传参:
// 调用上述对象的getData()方法
var_dump($teacher->getData(‘name‘));
再测试,结果显示如下:
增加另外两个直接显示数据的方式:
// 调用上述对象的getData()方法
var_dump($teacher->getData(‘name‘));
echo $teacher->getData(‘name‘);
return $teacher->getData(‘name‘);
测试结果如下:
thinkphp 模型与数据表的自动关联
细心的你,发现我们并没有指定要去查哪个表,系统自动的就将Teacher表中的数据返回给了我们。
这是由于当我们新建 model\Teacher时,继承了think\Model, 在think\Model中,有个功能是自动关联数据表。也就是说,我们起的类名叫做Teacher,它就自动关联yunzhi_teacher这个表。我们说yunzhi_是在哪定义的? 再去找一下database.php吧。
是的,就这么神奇,数据表中的数据就这么过来了。
用Db类的select()方法和我们此处的select()方法,获取到的虽然都是一个数组,但是一个是数组中的子项还是数组,而另一个是数组中的子项却是对象了。由于我们并不打算使用Db类,所以在此不对这两者的区别做过多的阐述。我们只需要知道,我们是面向对象的编程思路,即:一切皆对象 就可以了。
重构代码
重新去写自己的代码就叫做重构,所以我们这里也叫重构,但我们重构的目的是越重构越清晰,而在这里重构的目标是希望大家对代码有了更加深入的理解。
重构后代码如下:
<?php
namespace app\index\controller;
use app\model\Teacher; // 教师模型
/**
* 教师管理
*/
class TeacherController
{
public function index()
{
$JiaoShiBiao = new Teacher;
$SuoYouJiaoShi = $JiaoShiBiao->select();
// 获取第0个数据
$jiaoShiZhangSan = $SuoYouJiaoShi[0];
// 调用上述对象的getData()方法
echo ‘教师姓名‘ . $jiaoShiZhangSan->getData(‘name‘) . ‘<br />‘;
return ‘重复一遍:教师姓名‘ . $jiaoShiZhangSan->getData(‘name‘);
}
}
也就是说$xxxx,xxxx是变量名,这个名字你随便起,只要前后一致就可以。这些是由我们规定好的,它们在我们的代码中第一次出现的位置是表达式的最左侧,所以我们想起什么名字,就起什么名字。
比如下图中这三项,第一次出现的位置是等号的左边,说明他们是我们建立的,我们当然有自主权了,起什么名字我们说了算。
但第一次出现的位置是等号的右边的话,那就不一样了。
这个是其他人规定好的,它怎么规定的,我们就需要怎么使用。
最简单的,比如:
$JiaoShiBiao = new Teacher;
Teacher这个名字,是我们在use的时候规定好的,在我们的代码中出现在了等号右边,那么我们就必须按规则执行。
比如:
为了提升代码的可读性,我们必须统一代码书写的规范。
我们规定大家必须这样写:
<?php
namespace app\index\controller;
use app\model\Teacher; // 教师模型
/**
* 教师管理
*/
class TeacherController
{
public function index()
{
// $Teacher 首写字大写,说明它是一个对象, 更确切一些说明这是基于Teacher这个模型被我们手工实例化得到的,如果存在teacher数据表,它将对应teacher数据表。
$Teacher = new Teacher;
// $teachers 以s结尾,表示它是一个数组,数据中的每一项都是一个对象,这个对象基于Teahcer这个模型。
$teachers = $Teacher->select();
// 获取第0个数据
$teacher = $teachers[0];
// 调用上述对象的getData()方法
var_dump($teacher->getData(‘name‘));
echo $teacher->getData(‘name‘);
return $teacher->getData(‘name‘);
}
}
git checkout step3.2.4.5
执行上述命令后,上述示例代码信息如下:
以上是关于控制器的主要内容,如果未能解决你的问题,请参考以下文章
如何将这个 Objective-C 代码片段写入 Swift?
ASP.net MVC 代码片段问题中的 Jqgrid 实现
全栈编程系列SpringBoot整合Shiro(含KickoutSessionControlFilter并发在线人数控制以及不生效问题配置启动异常No SecurityManager...)(代码片段