ThinkPHP(十四)学生管理:M的关联,及查询

一、设计数据表

在这里插入图片描述

sql语句如下:

SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `yunzhi_student`
-- ----------------------------
DROP TABLE IF EXISTS `yunzhi_student`;
CREATE TABLE `yunzhi_student` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(40) NOT NULL DEFAULT '' COMMENT '姓名',
  `num` varchar(40) NOT NULL DEFAULT '',
  `sex` tinyint(2) NOT NULL DEFAULT '0',
  `klass_id` int(11) NOT NULL DEFAULT '0',
  `email` varchar(40) NOT NULL DEFAULT '',
  `create_time` int(11) NOT NULL DEFAULT '0',
  `update_time` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `yunzhi_student`
-- ----------------------------
BEGIN;
INSERT INTO `yunzhi_student` VALUES ('1', '徐琳杰', '111', '0', '1', 'xulinjie@yunzhiclub.com', '0', '0'), ('2', '魏静云', '112', '1', '2', 'weijingyun@yunzhiclub.com', '0', '0'), ('3', '刘茜', '113', '0', '2', 'liuxi@yunzhiclub.com', '0', '0'), ('4', '李甜', '114', '1', '1', 'litian@yunzhiclub.com', '0', '0'), ('5', '李翠彬', '115', '1', '3', 'licuibin@yunzhiclub.com', '0', '0'), ('6', '孔瑞平', '115', '0', '4', 'kongruiping@yunzhiclub.com', '0', '0');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

2.M

<?php
namespace app\common\model;
use think\Model;    // 使用前进行声明
/**
 * Student 学生表
 */
class Student extends Model
{
    
}

3.C

<?php
namespace app\index\controller;
use app\common\model\Student;


class StudentController extends IndexController
{
	public function index(){
		$Student=new Student;
		$students=$Student->paginate();
		$this->assign('students',$students);
		return $this->fetch();
	}
}

4.V

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <title>学生管理</title>
    <!-- <link rel="stylesheet" type="text/css" href="/thinkphp5/public/static/bootstrap-3.3.5-dist/css/bootstrap.min.css"> -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>

<body class="container">
    <div class="row">
        <div class="col-md-12">
            <hr />
            <div class="row">
                <div class="col-md-8">
                    <form class="form-inline">
                        <div class="form-group">
                            <label class="sr-only" for="name">姓名</label>
                       <input name="name" type="text" class="form-control" placeholder="姓名..." value={:input('get.name')}>
                        </div>
                        <button type="submit" class="btn btn-default"><i class="glyphicon glyphicon-search"></i>&nbsp;查询</button>
                    </form>
                </div>
                <div class="col-md-4 text-right">
                    <a href="{:url('add')}" class="btn btn-primary"><i class="glyphicon glyphicon-plus"></i>&nbsp;增加</a>
                </div>
            </div>
            <hr />
            <table class="table table-hover table-bordered">
                <tr class="info">
                    <th>序号</th>
                    <th>姓名</th>
                    <th>学号</th>
                    <th>性别</th>
                    <th>email</th>
                    <td>创建时间</td>
                    <th>班级</th>
                    <th>辅导员</th>
                    <th>操作</th>
                </tr>
                {volist name="students" id="student" key="key"}
                <tr>
                    <td>{$key}</td>
                    <td>{$student->getData('name')}</td>
                    <td>{$student->getData('num')}</td>
                    <td>{eq name="$student->getData('sex')" value="0"}男{else /}女{/eq}</td>
                    <td>{$student->getData('email')}</td>
                    <td>{$student->getData('create_time')}</td>
                    <td>{$student->getData('klass_id')}</td>
                    <td></td>
                    <td><a class="btn btn-danger btn-sm" href="{:url('delete?id=' . $student->getData('id'))}"><i class="glyphicon glyphicon-trash"></i>&nbsp;删除</a>&nbsp;<a class="btn btn-sm btn-primary" href="{:url('edit?id=' . $student->getData('id'))}"><i class="glyphicon glyphicon-pencil"></i>&nbsp;编辑</a></td>
                </tr>
                {/volist}
            </table>
            {$students->render()}
        </div>
    </div>
</body>

</html>

二、解决几个V层显示问题

1、性别显示的问题

方法1:之前在前端用以下语法实现:

<td>{eq name="$student->getData('sex')" value="0"}{else /}{/eq}</td>

方法2:『获取器』实现

http://www.kancloud.cn/manual/thinkphp5/135192

1)M层

获取器必须以get+字段名+Attr()格式命名,否则无法实现

<?php
namespace app\common\model;
use think\Model;

class Student extends Model
{
	/**
	*获取器:获取对应学习性别
	*@param 0/1
	*@return 性别
	*/
	public function getSexAttr($value){
		$status=['0'=>'男','1'=>'女',];
		$sex=$status[$value];

		if(isset($sex)){//如果设置了就根据设置值返回性别
			return $sex;
		}else{//如果没设置默认返回男性
			return $status[0];
		}
	}
}

2)V层

<!-- <td>{eq name="$student->getData('sex')" value="0"}男{else /}女{/eq}</td> -->
<td>{$student->sex}</td>
效果:http://tt/index.php/index/student

在这里插入图片描述

让我们尝试一下删除掉getSexAttr(),然后再刷新页面,发现就性别显示的变成了 0/1 而不再是男女了。
没错,你猜的对:
1、如果没有getSexAttr()函数,那么$student->getData('sex')$student->sex的作用是相同的,都是返回sex的原始数据。
2、如果有了getSexAttr()函数,那么$student->getData('sex')仍然是返回sex的原始数据。
3、如果有了getSexAttr()函数,那么$student->sex返回的是sex字段经过getSexAttr()函数处理后的数据。

2、创建时间显示的问题

1.方法1

1.1)M层
/**
	*获取器:根据时间戳显示时间
	*@param 时间戳
	*@return 时间
	*/
	public function getCreateTimeAttr($value){
		return date('Y-m-d',$value);
	}
1.2)V层
<!-- <td>{$student->getData('create_time')}</td> -->
<td>{$student->create_time}</td>

3)方法2:时间转换thinkphp封装的更好的方法

3.1 M层

由于时间戳的使用频率太频繁了,以至于thinkphp为我们封装了一个更好的方法。
http://www.kancloud.cn/manual/thinkphp5/138669
按照官方的教程,在这里,我们使用类型转换的功能,即重写$type$dataFormat
在此,我们需要先删除刚刚创建的getCreateTimeAttr方法,然后在M层中增加以下代码:
删除getCreateTimeAttr()获取器,或重命名

/**
     * 自定义自转换字换:重写$type
     * @var array
     */
	protected $type=[
		'create_time'=>'datetime',
	]; 

//自定义时间格式:重写$dateFormat
protected $dateFormat = 'Y年m月d日';    // 日期格式 1970年1月1日 默认格式:1970-01-01 08:00:00

3.2.V层不变

<!-- <td>{$student->getData('create_time')}</td> -->
<td>{$student->create_time}</td>
效果:http://tt/index.php/index/student

在实际项目中,我们还会对其他字段进行相应的类型转换处理,以防止有非法数据尝试写入数据库而带来系统错误。我们还会对日期的显示形式进行统一处理,这样当用户对日期的显示格式不满意时,能够通过设置某一个变量值,而达到统一更改的目的。
最后,我们再将删除掉的getCreateTimeAttr()还原回来,然后我们再刷新网页,发现日期又变回了yyyy-mm-dd的形式了。
总结:获取器及类型转换,都会对原始的数据进行二次的加工处理,其优先级顺序为:获取器(getAttrXXX) > 类型转换($type)。

3、利用关联查询显示班级名称

我们在第六章班级管理中,其实已经对这种情况进行了完美的处理。
我们简单回顾一下处理的流程:
1、增加一个同名方法;
2、在这个方法中,通过klass_id字段来获取Klass这个对象;
3、返回Klass对象。
上述流程,是我们处理n:1关系中基本不变的法则。由于这个用的实在是太频繁了,所以thinkphp5同时也内置了该功能。现在,我们尝试使用thinkphp的方法来实现查看班级名称的功能。
http://www.kancloud.cn/manual/thinkphp5/142358
关联详解:https://www.cnblogs.com/kangshuai/p/12051718.html
我们看到,原来还可以通过调用一个叫做$this->belongsTo(‘klass’);的方法来直接实现我们的需求。
我们仍然在Student 数据表模型中增加代码:

M层:

 /**
     * ThinkPHP使用一个叫做__get()的魔法函数来完成这个函数的自动调用
     * 在本章第五节中,我们将专门对__get()进行讲解
     * @author 梦云智 http://www.mengyunzhi.com
    */
    public function Klass()
    {
        return $this->belongsTo('Klass');
    }

V层修改:

//<td>{$student->Klass->name}</td> //此处原写法有误改成:
<td>{$student->Klass['name']}</td>

原因:输出{:var_dump($student->Klass)}显示:
{"id":1,"name":"实验1班","teacher_id":1,"create_time":0,"update_time":0}
因此显示name需用以上方式

测试结果为:实验一班、二班……
其实我们不需要纠结thinkphp是怎么做到的,会用就可以了。简单的事情重复做,你就是专家。现在我们需要做的,仅仅是简单的事情重复做,是的,只要你做到了,thinkphp5入门这块的专家,就是你。
如果你想在V层中,直接查看Klass这个对象,可以使用{:var_dump($Klass)};
位置如下:{$student->Klass->name}{:var_dump($student->Klass)};

总结:
我们在这里使用 s t u d e n t − > K l a s s 获 取 到 了 K l a s s 这 个 对 象 , 它 执 行 的 流 程 基 本 上 是 这 样 的 : 有 K l a s s 这 个 字 段 吗 ? 没 有 。 有 K l a s s 这 个 方 法 吗 ? 有 。 执 行 K l a s s 这 个 方 法 。 返 回 了 一 个 K l a s s 对 象 。 其 实 我 们 完 全 可 以 在 K l a s s 这 个 方 法 中 , 返 回 一 个 非 K l a s s 对 象 ; 也 可 以 在 一 个 非 K l a s s 方 法 中 , 返 回 K l a s s 对 象 。 只 是 在 这 里 , 我 们 更 愿 意 在 K l a s s 方 法 中 返 回 K l a s s 对 象 , 这 就 是 规 范 。 就 像 我 们 往 往 习 惯 于 使 用 student->Klass获取到了Klass这个对象,它执行的流程基本上是这样的: 有Klass这个字段吗?没有。 有Klass这个方法吗?有。 执行Klass这个方法。 返回了一个Klass对象。 其实我们完全可以在Klass这个方法中,返回一个非Klass对象;也可以在一个非Klass方法中,返回Klass对象。只是在这里,我们更愿意在Klass方法中返回Klass对象,这就是规范。就像我们往往习惯于使用 student>KlassKlassKlassKlassKlassKlassKlassKlassKlassKlassKlassKlass使Student = new Student;而不是使用$sdfsdf = new Student;一样。规范使得团队的代码风格统一,能够使我们的代码更具有易读性。

4、利用M的关联查询显示辅导员姓名

模型的关联详解:https://www.cnblogs.com/kangshuai/p/12051718.html

1) M层:在app\commom\model\Klass.php加【注意:此处不是Student】

/**
	*代替getTeacher获取对应教师对象
	*/
	public function Teacher(){
		return $this->belongsTo('Teacher');
	}

2)V层:student的v 层显示对应老师名

<!-- <pre>{:var_dump($student->Klass['Teacher'])}</pre> -->
<td>{$student->Klass['Teacher']['name']}</td>
效果:http://tt/index.php/index/student

在这里插入图片描述

【此处原写法】:$student->Klass->Teacher->name 无效。

【原因】:{:var_dump($student->Klass)}输出如下
可以看到它实际上变成了多层数组,因此读取方式也发生改变

object(app\common\model\Klass)#27 (27) {
  ["Teacher":"app\common\model\Klass":private]=>
  NULL
  ["connection":protected]=>
  array(0) {
  }
  ["name":protected]=>
  string(5) "Klass"
  ["table":protected]=>
  NULL
  ["class":protected]=>
  string(22) "app\common\model\Klass"
  ["error":protected]=>
  NULL
  ["validate":protected]=>
  NULL
  ["pk":protected]=>
  NULL
  ["field":protected]=>
  array(0) {
  }
  ["readonly":protected]=>
  array(0) {
  }
  ["visible":protected]=>
  array(0) {
  }
  ["hidden":protected]=>
  array(0) {
  }
  ["append":protected]=>
  array(0) {
  }
  ["data":protected]=>
  array(6) {
    ["id"]=>
    int(1)
    ["name"]=>
    string(10) "实验1班"
    ["teacher_id"]=>
    int(1)
    ["create_time"]=>
    int(0)
    ["update_time"]=>
    int(0)
    ["Teacher"]=>
    object(app\common\model\Teacher)#30 (26) {
      ["connection":protected]=>
      array(0) {
      }
      ["name":protected]=>
      string(7) "Teacher"
      ["table":protected]=>
      NULL
      ["class":protected]=>
      string(24) "app\common\model\Teacher"
      ["error":protected]=>
      NULL
      ["validate":protected]=>
      NULL
      ["pk":protected]=>
      NULL
      ["field":protected]=>
      array(0) {
      }
      ["readonly":protected]=>
      array(0) {
      }
      ["visible":protected]=>
      array(0) {
      }
      ["hidden":protected]=>
      array(0) {
      }
      ["append":protected]=>
      array(0) {
      }
      ["data":protected]=>
      array(8) {
        ["id"]=>
        int(1)
        ["name"]=>
        string(6) "张三"
        ["sex"]=>
        int(0)
        ["username"]=>
        string(7) "zhansan"
        ["password"]=>
        string(40) "4758eee18cc9a2d44db45d728bd7056d9e41b06b"
        ["email"]=>
        string(17) "zhangsan@mail.com"
        ["create_time"]=>
        int(123123)
        ["update_time"]=>
        int(1597024251)
      }
      ["change":protected]=>
      array(0) {
      }
      ["auto":protected]=>
      array(0) {
      }
      ["insert":protected]=>
      array(0) {
      }
      ["update":protected]=>
      array(0) {
      }
      ["autoWriteTimestamp":protected]=>
      bool(true)
      ["createTime":protected]=>
      string(11) "create_time"
      ["updateTime":protected]=>
      string(11) "update_time"
      ["dateFormat":protected]=>
      string(11) "Y-m-d H:i:s"
      ["type":protected]=>
      array(0) {
      }
      ["isUpdate":protected]=>
      bool(true)
      ["updateWhere":protected]=>
      array(1) {
        ["id"]=>
        array(2) {
          [0]=>
          string(2) "eq"
          [1]=>
          int(1)
        }
      }
      ["relation":protected]=>
      NULL
      ["failException":protected]=>
      bool(false)
    }
  }
  ["change":protected]=>
  array(0) {
  }
  ["auto":protected]=>
  array(0) {
  }
  ["insert":protected]=>
  array(0) {
  }
  ["update":protected]=>
  array(0) {
  }
  ["autoWriteTimestamp":protected]=>
  bool(true)
  ["createTime":protected]=>
  string(11) "create_time"
  ["updateTime":protected]=>
  string(11) "update_time"
  ["dateFormat":protected]=>
  string(11) "Y-m-d H:i:s"
  ["type":protected]=>
  array(0) {
  }
  ["isUpdate":protected]=>
  bool(true)
  ["updateWhere":protected]=>
  array(1) {
    ["id"]=>
    array(2) {
      [0]=>
      string(2) "eq"
      [1]=>
      int(1)
    }
  }
  ["relation":protected]=>
  object(think\model\Relation)#29 (11) {
    ["parent":protected]=>
    *RECURSION*
    ["model":protected]=>
    string(24) "app\common\model\Teacher"
    ["middle":protected]=>
    NULL
    ["type":protected]=>
    int(3)
    ["foreignKey":protected]=>
    string(10) "teacher_id"
    ["throughKey":protected]=>
    NULL
    ["localKey":protected]=>
    string(2) "id"
    ["alias":protected]=>
    array(0) {
    }
    ["joinType":protected]=>
    string(5) "INNER"
    ["query":protected]=>
    object(think\db\Query)#31 (11) {
      ["connection":protected]=>
      object(think\db\connector\Mysql)#9 (15) {
        ["PDOStatement":protected]=>
        object(PDOStatement)#12 (1) {
          ["queryString"]=>
          string(64) "SELECT * FROM `yunzhi_teacher` WHERE  `id` = :where_id LIMIT 1  "
        }
        ["queryStr":protected]=>
        string(57) "SELECT * FROM `yunzhi_teacher` WHERE  `id` = 1 LIMIT 1   "
        ["numRows":protected]=>
        int(1)
        ["transTimes":protected]=>
        int(0)
        ["error":protected]=>
        string(0) ""
        ["links":protected]=>
        array(1) {
          [0]=>
          object(PDO)#11 (0) {
          }
        }
        ["linkID":protected]=>
        object(PDO)#11 (0) {
        }
        ["linkRead":protected]=>
        NULL
        ["linkWrite":protected]=>
        NULL
        ["resultSetType":protected]=>
        string(5) "array"
        ["fetchType":protected]=>
        int(2)
        ["attrCase":protected]=>
        int(0)
        ["query":protected]=>
        array(3) {
          ["app\common\model\Student"]=>
          object(think\db\Query)#10 (11) {
            ["connection":protected]=>
            *RECURSION*
            ["builder":protected]=>
            string(5) "mysql"
            ["model":protected]=>
            string(24) "app\common\model\Student"
            ["table":protected]=>
            string(0) ""
            ["name":protected]=>
            string(7) "Student"
            ["pk":protected]=>
            NULL
            ["fieldType":protected]=>
            array(0) {
            }
            ["allowField":protected]=>
            array(0) {
            }
            ["prefix":protected]=>
            string(7) "yunzhi_"
            ["options":protected]=>
            array(0) {
            }
            ["bind":protected]=>
            array(0) {
            }
          }
          ["app\common\model\Klass"]=>
          object(think\db\Query)#28 (11) {
            ["connection":protected]=>
            *RECURSION*
            ["builder":protected]=>
            string(5) "mysql"
            ["model":protected]=>
            string(22) "app\common\model\Klass"
            ["table":protected]=>
            string(0) ""
            ["name":protected]=>
            string(5) "Klass"
            ["pk":protected]=>
            NULL
            ["fieldType":protected]=>
            array(0) {
            }
            ["allowField":protected]=>
            array(0) {
            }
            ["prefix":protected]=>
            string(7) "yunzhi_"
            ["options":protected]=>
            array(0) {
            }
            ["bind":protected]=>
            array(0) {
            }
          }
          ["app\common\model\Teacher"]=>
          *RECURSION*
        }
        ["config":protected]=>
        array(20) {
          ["type"]=>
          string(5) "mysql"
          ["hostname"]=>
          string(9) "127.0.0.1"
          ["database"]=>
          string(3) "tp5"
          ["username"]=>
          string(4) "root"
          ["password"]=>
          string(4) "root"
          ["hostport"]=>
          string(0) ""
          ["dsn"]=>
          string(0) ""
          ["params"]=>
          array(0) {
          }
          ["charset"]=>
          string(4) "utf8"
          ["prefix"]=>
          string(7) "yunzhi_"
          ["debug"]=>
          bool(true)
          ["deploy"]=>
          int(0)
          ["rw_separate"]=>
          bool(false)
          ["master_num"]=>
          int(1)
          ["slave_no"]=>
          string(0) ""
          ["fields_strict"]=>
          bool(true)
          ["resultset_type"]=>
          string(5) "array"
          ["auto_timestamp"]=>
          bool(true)
          ["sql_explain"]=>
          bool(false)
          ["builder"]=>
          string(0) ""
        }
        ["params":protected]=>
        array(5) {
          [8]=>
          int(0)
          [3]=>
          int(2)
          [11]=>
          int(0)
          [17]=>
          bool(false)
          [20]=>
          bool(false)
        }
      }
      ["builder":protected]=>
      string(5) "mysql"
      ["model":protected]=>
      string(24) "app\common\model\Teacher"
      ["table":protected]=>
      string(0) ""
      ["name":protected]=>
      string(7) "Teacher"
      ["pk":protected]=>
      NULL
      ["fieldType":protected]=>
      array(0) {
      }
      ["allowField":protected]=>
      array(0) {
      }
      ["prefix":protected]=>
      string(7) "yunzhi_"
      ["options":protected]=>
      array(0) {
      }
      ["bind":protected]=>
      array(0) {
      }
    }
    ["where":protected]=>
    NULL
  }
  ["failException":protected]=>
  bool(false)
}
{:var_dump($student->Klass['Teacher'])}
输出查看如下:
object(app\common\model\Teacher)#30 (26) {
  ["connection":protected]=>
  array(0) {
  }
  ["name":protected]=>
  string(7) "Teacher"
  ["table":protected]=>
  NULL
  ["class":protected]=>
  string(24) "app\common\model\Teacher"
  ["error":protected]=>
  NULL
  ["validate":protected]=>
  NULL
  ["pk":protected]=>
  NULL
  ["field":protected]=>
  array(0) {
  }
  ["readonly":protected]=>
  array(0) {
  }
  ["visible":protected]=>
  array(0) {
  }
  ["hidden":protected]=>
  array(0) {
  }
  ["append":protected]=>
  array(0) {
  }
  ["data":protected]=>
  array(8) {
    ["id"]=>
    int(1)
    ["name"]=>
    string(6) "张三"
    ["sex"]=>
    int(0)
    ["username"]=>
    string(7) "zhansan"
    ["password"]=>
    string(40) "4758eee18cc9a2d44db45d728bd7056d9e41b06b"
    ["email"]=>
    string(17) "zhangsan@mail.com"
    ["create_time"]=>
    int(123123)
    ["update_time"]=>
    int(1597024251)
  }
  ["change":protected]=>
  array(0) {
  }
  ["auto":protected]=>
  array(0) {
  }
  ["insert":protected]=>
  array(0) {
  }
  ["update":protected]=>
  array(0) {
  }
  ["autoWriteTimestamp":protected]=>
  bool(true)
  ["createTime":protected]=>
  string(11) "create_time"
  ["updateTime":protected]=>
  string(11) "update_time"
  ["dateFormat":protected]=>
  string(11) "Y-m-d H:i:s"
  ["type":protected]=>
  array(0) {
  }
  ["isUpdate":protected]=>
  bool(true)
  ["updateWhere":protected]=>
  array(1) {
    ["id"]=>
    array(2) {
      [0]=>
      string(2) "eq"
      [1]=>
      int(1)
    }
  }
  ["relation":protected]=>
  NULL
  ["failException":protected]=>
  bool(false)
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值