关联模型(1:n)

关联模型 (1对n)

ThinkPHP5.0 的关联采用了对象化的操作模式,你无需继承不同的模型类
只是把关联定义成一个方法,并且直接通过当前模型对象的属性名获取定义的关联数据。

关联定义:一个user有多本书book

DROP TABLE IF EXISTS `think_user`;
CREATE TABLE IF NOT EXISTS `think_user` (
`id` int(6) UNSIGNED NOT NULL AUTO_INCREMENT,
`nickname` varchar(25) NOT NULL,
`name` varchar(25) NOT NULL,
`password` varchar(50) NOT NULL,
`create_time` int(11) UNSIGNED NOT NULL,
`update_time` int(11) UNSIGNED NOT NULL,
`status` tinyint(1) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;



DROP TABLE IF EXISTS `think_book`;
CREATE TABLE IF NOT EXISTS `think_book` (
`id` int(8) UNSIGNED NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`publish_time` int(11) UNSIGNED DEFAULT NULL,
`create_time` int(11) UNSIGNED NOT NULL,
`update_time` int(11) UNSIGNED NOT NULL,
`status` tinyint(1) NOT NULL,
`user_id` int(6) UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

在User 模型类添加Book 关联如下:

  • hasMany

hasMany 的参数如下:
hasMany('关联模型名','关联外键','关联模型主键','别名定义')

步骤一、定义Uer模型和关联方法book

<?php 
namespace app\index\model;
use think\Model;
class User extends Model
{
// 开启自动写入时间戳
protected $autoWriteTimestamp = true;
// 定义自动完成的属性
protected $insert = ['status' => 1];

    // 定义关联hasMany
    public function books()
    {
    return $this->hasMany('Book');
    }
}

步骤二、定义book模型

<?php 
namespace app\index\model;
use think\Model;
class Book extends Model
{
protected $type = [
'publish_time' => 'timestamp:Y-m-d',
];
    // 开启自动写入时间戳
    protected $autoWriteTimestamp = true;
    // 定义自动完成的属性
    protected $insert = ['status' => 1];
}

 ?>

1. 关联新增

添加addBook 方法用于新增关联数据:

public function addBook()
{
$user = UserModel::get(1);
$book = new Book;
$book->title = 'ThinkPHP5快速入门';
$book->publish_time = '2016-05-06';
$user->books()->save($book);
return '添加Book成功';
}

对于一对多关联,也可以批量增加数据:

public function addBook()
{
$user = UserModel::get(1);
$books = [
['title' => 'ThinkPHP5快速入门', 'publish_time' => '2016-05-06'],
['title' => 'ThinkPHP5开发手册', 'publish_time' => '2016-03-06'],
];
$user->books()->saveAll($books);
return '添加Book成功';
}

2.关联查询

可以直接调用模型的属性获取全部关联数据,例如:

public function read()
{
$user = UserModel::get(1);
$books = $user->books;
dump($books);

一对多查询同样可以使用预载入查询,例如:

public function read()
{
$user = UserModel::get(1,'books');
$books = $user->books;
dump($books);
}

一对多预载入查询会在原先延迟查询的基础上增加一次查询,可以解决典型的N+1 次查询问题。
如果要过滤查询,可以调用关联方法:

public function read()
{
$user = UserModel::get(1);
// 获取状态为1的关联数据
$books = $user->books()->where('status',1)->select();
dump($books);
// 获取作者写的某本书
$book = $user->books()->getByTitle('ThinkPHP5快速入门');
dump($book);
}

还可以根据关联数据来查询当前模型数据,例如:

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

3.关联更新

public function update($id)
{
$user = UserModel::get($id);
$book = $user->books()->getByTitle('ThinkPHP5开发手册');
$book->title = 'ThinkPHP5快速入门';
$book->save();

或者使用查询构建器的update 方法进行更新(但可能无法触发关联模型的事件

public function update($id)
{
$user = UserModel::get($id);
$user->books()->where('title', 'ThinkPHP5快速入门')->update(['title' => 'ThinkPHP5开
发手册']);
}

4. 关联删除

删除部分关联数据:

    public function delete($id){
    $user = UserModel::get($id);
    // 删除部分关联数据
    $book = $user->books()->getByTitle('ThinkPHP5开发手册');
    $book->delete();
    }

删除所有的关联数据:

public function delete($id){
    $user = UserModel::get($id);
    if($user->delete()){
    // 删除所有的关联数据
    $user->books()->delete();
    }
}
posted @ 2018-01-11 09:48  金于虎  阅读(1017)  评论(0编辑  收藏  举报