thinkphp5模型关联

模型定义

namespace app\index\model; 
use think\Model;
class User extends Model{
	// 设置完整的数据表(包含前缀)
	protected $table = 'think_user';
	// 设置数据表(不含前缀)
	protected $name = 'member';
}

插入数据

//对象插入方式:
$users=new Users;
$users->email='hello@abc.com';
$user->mobile='123432';
$uer->save();

//静态方式数组插入方式:
$user['emial']='123@qq.com';
$user['mobile']='12312';
if($res=User::create($user)){
	echo "success"
}


批量插入

	$user=new Users;
	$ist=[
		['email'=>'12312@qq.com','mobile'=>'12312312']
		['email'=>'546@qq.com','mobile'=>'545434']
	]
	if($user->saveAll($list)){
	echo "success";
	}

查询数据

$user=User::get(1);
echo $user->mobile;
echo $user->email;
//因为实现了\ArrayAccess的接口,所以也可以用数组的方式进行访问
echo $user['email'];
echo $user['mobile'];

查询单个数据

根据某个条件查询数据格式:getByxxx()方法
$user=Users::getByEmail('123@qq.com');
echo $user['mobile'];

如果不是主键,可以传入数组作为查询条件
$user=User::get(['mobile'=>'123']);

查询多条数据

$list = UserModel::all();
foreach ($list as $user) {
echo $user->nickname . '<br/>';
echo $user->email . '<br/>';
echo date('Y/m/d', $user->birthday)
}

如果不是使用主键查询,可以直接传入数组条件查询,例如:
$list = UserModel::all(['status'=>1]);
foreach ($list as $user) {
echo $user->nickname . '<br/>';
echo $user->email . '<br/>';
echo date('Y/m/d', $user->birthday) . '<br/>';
echo '----------------------------------<br/>';
}


我们也可以使用数据库的查询构建器完成更多的条件查询
$list = UserModel::where('id','<',3)->select();

更新数据

public function update($id)
{
$user['id'] = (int) $id;
$user['nickname'] = '刘晨';
$user['email'] = 'liu21st@gmail.com';
$result = UserModel::update($user);
return '更新用户成功';
}

删除数据

public function delete($id)
{
	$user = UserModel::get($id);
	if ($user) {
		$user->delete();
		return '删除用户成功';
	} else {
		return '删除的用户不存在';
	}
}

public function delete($id)
{
	$result = UserModel::destroy($id);
	if ($result) {
		return '删除用户成功';
	} else {
		return '删除的用户不存在';
	}
}

读取器

读取器方法的命名规范是:
get + 属性名的驼峰命名+ Attr

 getBirthdayAttr 读取器读取的是 birthday 属性,而 getUserBirthdayAttr 读取器读取的
则是 user_birthday 属性。


<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// birthday读取器
protected function getBirthdayAttr($birthday)
{
return date('Y-m-d', $birthday);
}
}

读取器还可以定义读取数据表中不存在的属性,例如把原始生日和转换的格式分开两个属性 birthday 和
user_birthday ,我们只需定义 user_birthday 属性的读取器方法:
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// user_birthday读取器
protected function getUserBirthdayAttr($value,$data)
{
return date('Y-m-d', $data['birthday']);
}
}
这里的读取器方法使用了第二个参数,表示传入所有的属性数据。因为原始的 user_birthday 属性数据是
不存在的,所以我们需要通过 data 参数获取。
read操作方法修改为:
// 读取用户数据
public function read($id='')
{
$user = UserModel::get($id);
echo $user->nickname . '<br/>';
echo $user->email . '<br/>';
echo $user->birthday . '<br/>';
echo $user->user_birthday . '<br/>';
}
当刷新页面的时候,最终输出的结果为:
流年
thinkphp@qq.com
226339200
1977-03-05

修改器

修改器方法的命名规范是:
set + 属性名的驼峰命名+ Attr
所以, setBirthdayAttr 方法修改的是 birthday 属性,而 setUserBirthdayAttr 方法修改的则是
user_birthday 属性。


<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// 读取器
protected function getUserBirthdayAttr($birthday, $data)
{
return date('Y-m-d', $data['birthday']);
}
// birthday修改器
protected function setBirthdayAttr($value)
{
return strtotime($value);
}
}

// 新增用户数据
public function add()
{
$user = new UserModel;
$user->nickname = '流年';
$user->email = 'thinkphp@qq.com';
$user->birthday = '1977-03-05';
if ($user->save()) {
return '用户[ ' . $user->nickname . ':' . $user->id . ' ]新增成功';
} else {
return $user->getError();
}
}

全局查询范围

可以给模型定义全局的查询范围,在模型类添加一个静态的 base 方法即可,例如我们给模型类增加一个全
局查询范围,用于查询状态为1的数据:

<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// 全局查询范围
protected static function base($query)
{
	// 查询状态为1的数据
	$query->where('status',1);
}
}

当使用下面的查询操作
UserModel::scope('email')->all();
最后生成的SQL语句是:
SELECT * FROM `think_user` WHERE `email` = 'thinkphp@qq.com' AND `status` = 1 ORDER BY
`id` desc
每次查询都会自动带上全局查询范围的查询条件

类型转换和自动完成


// 开启自动写入时间戳字段
'auto_timestamp' => true,
会发现系统已经自动写入了 think_user 数据表中的的 create_time 、 update_time 字段,如果自动
写入的时间戳字段不是这两个的话,需要修改模型类的属性定义,例如:
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// 定义时间戳字段名
protected $createTime = 'create_at';
protected $updateTime = 'update_at';
}

// 关闭自动写入时间戳
protected $autoWriteTimestamp = false;

// 指定自动写入时间戳的类型为dateTime类型
protected $autoWriteTimestamp = 'datetime';

自动完成:
namespace app\index\model;
use think\Model;
class User extends Model
{
// 定义类型转换
protected $type = [
'birthday' => 'timestamp:Y/m/d',
];
// 定义自动完成的属性(auto insert update)
//在插入时自动完成
protected $insert = ['status' => 1];
}

查询范围

查询范围方法的定义规范为:
scope + 查询范围名称
例如,邮箱地址为 thinkphp@qq.com 和status为1这两个常用查询条件,可以定义为模型类的两个查询范围
方法:
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// email查询
protected function scopeEmail($query)
{
$query->where('email', 'thinkphp@qq.com');
}
// status查询
protected function scopeStatus($query)
{
$query->where('status', 1);
}
}

// 根据查询范围获取用户数据列表
public function index()
{
$list = UserModel::scope('email,status')->all();
foreach ($list as $user) {
echo $user->nickname . '<br/>';
echo $user->email . '<br/>';
echo $user->birthday . '<br/>';
echo $user->status . '<br/>';
echo '-------------------------------------<br/>';
}
}

最后查询的SQL语句是:
SELECT * FROM `think_user` WHERE `email` = 'thinkphp@qq.com' AND `status` = 1

支持多次调用 scope 方法,并且可以追加新的查询及链式操作,例如:
// 根据查询范围获取用户数据列表
public function index()
{
//
$list = UserModel::scope('email')
->scope('status')
->scope(function ($query) {
$query->order('id', 'desc');
})
->all();
foreach ($list as $user) {
echo $user->nickname . '<br/>';
echo $user->email . '<br/>';
echo $user->birthday . '<br/>';
echo $user->status . '<br/>';
echo '-------------------------------------<br/>';
}
}

最后生成的SQL语句是:
SELECT * FROM `think_user` WHERE `email` = 'thinkphp@qq.com' AND `status` = 1 ORDER BY
`id` desc

模型关联

一对多

User:
pubulic function comm(){
return $this->hasMany('Comment','user_id','id');
}

反向关联
Comment:
public function user(){
return $this->belongsTo('User','user_id','id');
}

//关联查询
$user=Users::get(1);
//获取user对象的nickname属性
echo $user->nickname
//获取user对象的关联对象commit
$user->comm;
//foreach($user->comm as $comm){
	echo "评论id".$comm->comment_id;
	echo "评论内容".$comm->content
}
$comm=$user->comm()->where('content','哈哈哈')->select()

//关联新增多条数据
$user=Users::get(1);
$comment=[
	['content'=>'11111','add_time'=>time()],
	['content'=>'22222','add_time'=>time()]
]
$user->comm()->saveAll($commnet)


//关联过滤查询
$user=Users::get(1)
$comment=$user->comm()->where('is_show',1)->select()
foreach($comment as $comm){
	echo "品论id".$comm->comment_id;
	echo "品论内容".$comm->content;
}

//预载入查询
public function read()
{
$user = UserModel::get(1,'books');
$books = $user->books;
dump($books);
}
一对多预载入查询会在原先延迟查询的基础上增加一次查询,可以解决典型的 N+1 次查询问题。

//根据关联数据来查询当前模型数据
public function read()
{
// 查询有写过书的作者列表
$user = UserModel::has('books')->select();
// 查询写过三本书以上的作者
$user = UserModel::has('books', '>=', 3)->select();
// 查询写过ThinkPHP5快速入门的作者
$user = UserModel::hasWhere('books', ['title' => 'ThinkPHP5快速入门'])->select();
}

//关联更新
$user=Users::get(1)
$comm=$user->comm()->getByContent('thinkphp5')
$comm->content='thinjava'
$commm->save()

$user=Users::get(1)
$user->comm()->where('content','thinkphp5')->update(['content'=>'thinkjava'])

//关联删除
$user=Users::get(1)
$comm=$user->comm()->getByContent('thinkphp5')
$comm->delete()

//删除所有的关联数据:
	$user = UserModel::get($id);
	if($user->delete()){
		// 删除所有的关联数据
		$user->books()->delete();
	}
	

一对一

(只有在新增的时候用car()方法,其他操作用car属性)

User:
public function car(){
return $this->hanOne('Car','user_id','id');
}


//查询一条数据
$user=Users::get(1);
echo $user->car->brand;

//关联新增
$user=new Users;
$user->email='1';
$user->nickname='hell'
$user->pass='123'
if($user->save()){
	$car['brand']='benchi';
	$user->car()->save($car)
	return $user->nickname;
}else{
return $user->getError()
}

//关联更新
$user=Users::get(1)
$user->email='1';
if($user->save()){
	$car['brand']='benchi';
	$user->car()->save($car)
	return $user->nickname;
}else{
return $user->getError()
}

//关联删除
$user=Users::get(1)
if($user->delete()){
	$user->car->delete(0)
}else{
	return $user->getError()
}

多对多


模型输出

输出数组
可以使用 toArray 方法把当前的模型对象输出为数组。
修改 User 控制器的 read 操作方法如下:
// 读取用户数据并输出数组
public function read($id = '')
{
$user = UserModel::get($id);
dump($user->toArray());
}
访问 http://tp5.com/user/20 页面输出结果为:
array (size=7)
'id' => int 20
'nickname' => string '张三' (length=6)
'email' => string 'zhanghsan@qq.com' (length=16)
'birthday' => string '1988/01/15' (length=10)
'status' => string '待审核' (length=9)
'create_time' => string '2016-05-02 16:40:57' (length=19)
'update_time' => string '2016-05-02 16:40:57' (length=19)
可以看到,User模型的数据已经经过了读取器方法处理。


隐藏属性
如果输出的时候需要隐藏某些属性,可以使用:
// 读取用户数据并输出数组
public function read($id = '')
{
$user = UserModel::get($id);
dump($user->hidden(['create_time','update_time'])->toArray());
}
再次访问 http://tp5.com/user/20 页面输出结果变成:
array (size=5)
'id' => int 20
'nickname' => string '张三' (length=6)
'email' => string 'zhanghsan@qq.com' (length=16)
'birthday' => string '1988/01/15' (length=10)
'status' => int 2

指定属性
或者指定一些属性输出,则可以用:
// 读取用户数据并输出数组
public function read($id = '')
{
$user = UserModel::get($id);
dump($user->visible(['id','nickname','email'])->toArray());
}
再次访问 http://tp5.com/user/20 页面输出结果变成:
array (size=3)
'id' => int 20
'nickname' => string '张三' (length=6)
'email' => string 'zhanghsan@qq.com' (length=16)


追加属性
如果读取器定义了一些非数据库字段的读取,例如:
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// status修改器
protected function getUserStatusAttr($value)
{
$status = [-1 => '删除', 0 => '禁用', 1 => '正常', 2 => '待审核'];
return $status[$value];
}
}

而我们如果需要输出 user_status 属性数据的话,可以使用 append 方法,用法如下:
// 读取用户数据并输出数组
public function read($id = '')
{
$user = UserModel::get($id);
dump($user->append(['user_status'])->toArray());
}
再次访问 http://tp5.com/user/20 页面输出结果变成:
array (size=8)
'id' => int 20
'nickname' => string '张三' (length=6)
'email' => string 'zhanghsan@qq.com' (length=16)
'birthday' => string '1988/01/15' (length=10)
'status' => int 2
'create_time' => string '2016-05-02 16:40:57' (length=19)
'update_time' => string '2016-05-02 16:40:57' (length=19)
'user_status' => string '待审核' (length=9)

输出JSON
对于 API 开发而言,经常需要返回 JSON 格式的数据,修改 read 操作方法改成 JSON 输出:
// 读取用户数据输出JSON
public function read($id = '')
{
$user = UserModel::get($id);
echo $user->toJson();
}
访问 http://tp5.com/user/20 页面输出结果为:
{"id":22,"nickname":"张三","email":"zhanghsan@qq.com","birthday":"1988\/01\/15","status"
:2,"create_time":"2016-05-02 16:40:57","update_time":"2016-05-02 16:40:57"}

或者采用更简单的方法输出 JSON ,下面的方式是等效的:
// 读取用户数据直接输出JSON
public function read($id = '')
{
echo UserModel::get($id);
}

posted @ 2020-08-05 05:27  琴似蓝调  阅读(354)  评论(0编辑  收藏  举报