zoukankan      html  css  js  c++  java
  • 控制器

    文字
    分享
    评论收藏

    3.2.4 间接读取数据

    间接读取数据

    直接读取数据虽然简单易懂,但往往在大型的项目中却并不适用。如果实现一个功能,我们把所有的代码都写在一个方法中,显然当功能复杂时,代码就会越来越长,越来越难以维护。这显然不是我们想看到的。
    基于此,我们有了数据库M层,一个专门为我们处理数据表的文件。

    M 数据模型层

    没有M层以前我们取数的过程是这样的。

    有了M层以后,我们取数的过程变成了这样。

    是的,你想的没错,在小型的项目,或是我们这个教程中,这样做的确是画蛇添足了。但是我们的目标,并不仅仅满足于做小项目。后面你将会一点点的感受到分层的魅力。

    调用谁,你就要USE谁

    我们再看前面写过的代码:

    如果删除或注释掉第3行。
    就会报如下错误:

    报错信息中提示这个类 'appindexcontrollerDB' 没有找到。

    原因就是我们在用Db类以前,没有告诉程序这个正确的Db类在哪个位置,怎么告诉呢?利用的就是USE。

    那我们说,你怎么就知道要这么use呢?
    我们先看一下,Db这个类到底在哪。

    其实它在哪并不要紧,PHP中有一个叫命名空间的东西,至于怎么工作的,有兴趣的GOOGLE吧。我们只需要知道它叫命名空间就可以了。如下图所示:

    命名空间,可以简单的理解为:我住哪。
    我们看到Db这个类,它住在了think中,它的名字叫Db,所以别人想找它帮忙的时候,只需要use thinkDb;就可以了。

    当然了,我们自己写的类,由于也有命名空间,别人也可以通过我们的类住在哪,叫什么名字,来use我们的文件。
    其实想搞清楚命名空间这个神奇的东西并不容易,所以搞不太清楚没有关系,我们现在只需要知道 调用谁,就USE谁 ,就可以了。慢慢的,我们会一点点的明白什么是命名空间。

    调用M层,我们就要USE M层

    建立M层文件

    上面我们是使用了Db这个类,这次我们放弃Db类。在实际的开发过程中,大多数的数据表都是固定的(有些项目需要动态生成数据表),所以我们也很少会去用这个Db类。基于此,我们对Db类的了解,到此为止。

    这次我们引用think内置的一个类thinkModel,这个类中封装好了所有的数据库操作方法。我们将采用继承的方法,如果现在不太清楚什么是继承,可以直接往下看,但我们有必要去学一学C++了。

    代码如下:

    <?php
    namespace appmodel;
    use thinkModel;    // 使用前进行声明
    /**
     * Teacher 教师表
     */
    class Teacher extends Model
    {
    
    }

    我们再来巩固一下这个namespace,叫做命名空间的东西。
    appmodel; 是指这个文件位于application文件夹下的model文件夹中。
    所以当我们看到以app打头的命名空间时,也就相当于告诉了我们这个文件位于哪个位置。

    是的,不仅仅我们在调用这个类之前需要进行use,我们在继承一个类之前也需要use。

    调用Teacher.php 模型文件

    我们先回到C层,即controller文件夹下,对原Teahcer.php进行重新编辑,去除对Db类的调用。

    我们需要记往一点,只有controller文件夹下的文件,才可以通过URL访问的到。其它的文件,比如我们刚刚新建的这个M层的Teacher.php,是直接访问不到的。

    删除冗余的代码后如下:

    <?php
    namespace appindexcontroller;
    /**
     * 教师管理
     */
    class Teacher
    {
        public function index()
        {
           echo "hello teacher";
        }
    }

    输入URL进行测试结果显示如下:

    下面,我们正式调用Teacher模型。
    1、先use;
    2、再调用。

    示例代码如下:

    <?php
    namespace appindexcontroller;
    use appmodelTeacher;  // 教师模型
    /**
     * 教师管理
     */
    class Teacher
    {
        public function index()
        {
            $Teacher = new Teacher;
            dump($Teacher);
        }
    }

    经测试,我们将得到如下错误提示:

    git checkout step3.2.4.1

    执行上述命令后,上述示例代码信息如下:

    提示:不能重新声明appindexcontrollerTeacher这个类,原因是由于这个类已经存在。

    每个班级里面只能有一个小明,如果存在两个小明,那么他们肯定有一个是大小明,另一个是小小明。因为只有这样,当老师点名的时候,才会有唯一的学生站出来。这个故事告诉我们,同一个文件中,如果有两个类的名字相同,是会发生错误的。

    上述错误的原因,是由于这两个人起的名字相同的。

    我们把这两个文件拿出,发现还真是这样。

    解决方法1

    为引用的那个Teacher 改个名字

    <?php
    namespace appindexcontroller;
    use appmodelTeacher 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 appindexcontroller;
    use appmodelTeacher;  // 教师模型
    /**
     * 教师管理
     */
    class TeacherController
    {
        public function index()
        {
            $Teacher = new Teacher;
            var_dump($Teacher);
        }
    }

    测试结果:

    git checkout step3.2.4.3

    执行上述命令后,上述示例代码信息如下:

    我们看到$Teacher变量的类型是一个object,这个对象的原型是appmodelTeacher。没错,的确是我们引入的那个原型。

    主角登场

    使用select()来获取数据库中的信息。

    <?php
    namespace appindexcontroller;
    use appmodelTeacher;  // 教师模型
    /**
     * 教师管理
     */
    class TeacherController
    {
        public function index()
        {
            $Teacher = new Teacher;
            $teachers = $Teacher->select();
            var_dump($teachers);
        }
    }

    测试结果:

    git checkout step3.2.4.4

    执行上述命令后,上述示例代码信息如下:

    我们看到返回值是个数组,这个数组的第0项是一个对象,第1项也是个对象。这两个对象都是基于appmodelTeacher这个类创建的。也就是说,这个对象中除了那些被var_dump()出来的变量以外,还有一些没有被var_dump()出来的方法可以供我们使用。

    其实现在我们已经很清楚了,我们并没在appmodelTeacher中写任何代码,那么这些保护类型的私有属性是怎么来的呢?这当然是由于它继承了一个叫做thinkModel类的原因了。我们说你自己是没有,但是你父类有就和你有是一样的。因为我们的继承中规定,在父类中所有的protected和public的变量或方法,都是可以被子类直接使用的。

    那么好,我们现在就找一个thinkModel中的方法,我们调用一下看看。

    我们找到第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 appindexcontroller;
    use appmodelTeacher;  // 教师模型
    /**
     * 教师管理
     */
    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表中的数据返回给了我们。

    这是由于当我们新建 modelTeacher时,继承了thinkModel, 在thinkModel中,有个功能是自动关联数据表。也就是说,我们起的类名叫做Teacher,它就自动关联yunzhi_teacher这个表。我们说yunzhi_是在哪定义的? 再去找一下database.php吧。

    是的,就这么神奇,数据表中的数据就这么过来了。

    用Db类的select()方法和我们此处的select()方法,获取到的虽然都是一个数组,但是一个是数组中的子项还是数组,而另一个是数组中的子项却是对象了。由于我们并不打算使用Db类,所以在此不对这两者的区别做过多的阐述。我们只需要知道,我们是面向对象的编程思路,即:一切皆对象 就可以了。

    重构代码

    重新去写自己的代码就叫做重构,所以我们这里也叫重构,但我们重构的目的是越重构越清晰,而在这里重构的目标是希望大家对代码有了更加深入的理解。

    重构后代码如下:

    <?php
    namespace appindexcontroller;
    use appmodelTeacher;  // 教师模型
    /**
     * 教师管理
     */
    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 appindexcontroller;
    use appmodelTeacher;  // 教师模型
    /**
     * 教师管理
     */
    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

    执行上述命令后,上述示例代码信息如下:

     
     

     

     
  • 相关阅读:
    Codeforces 994B. Knights of a Polygonal Table
    Codeforces 994A. Fingerprints
    Codeforces 988F. Rain and Umbrellas
    51nod 1158 全是1的最大子矩阵(单调栈 ,o(n*m))
    51nod 1102 面积最大的矩形 && 新疆大学OJ 1387: B.HUAWEI's billboard 【单调栈】+【拼凑段】(o(n) 或 o(nlog(n))
    Codeforces 988E. Divisibility by 25
    【复习资料】单片机与嵌入式系统原理及应用
    Codeforces 723D. Lakes in Berland
    Codeforces 986A. Fair(对物品bfs暴力求解)
    Codeforces 986B. Petr and Permutations(没想到这道2250分的题这么简单,早知道就先做了)
  • 原文地址:https://www.cnblogs.com/chuanqideya/p/6032514.html
Copyright © 2011-2022 走看看