Laravel 数据模型关系笔记(一)

301 阅读3分钟

Laravel 中的模型操作非常强大,但是光看文档的话使用的各个参数相对而言比较绕,蹭着还没有被绕晕,赶紧写个笔记来巩固一下,也方便以后查看。

  1. 一对一关系

举个例子,一个用户拥有一个对应的个人扩展信息。

users表结构与表数据为:

id name email password remember_token created_at updated_at
1 name alex@163.com 123123 123123 2019-02-13 23:59:59 2019-02-13 23:59:59

profiles表结构与表数据为:

id user_id realname phone created_at updated_at
1 1 张三 13500001111 2019-02-13 23:59:59 2019-02-13 23:59:59

有两个表,Laravel中的默认规定是创建User来对应users表,Profile类来对应profiles表。两个模型之间是一对一的关系,关系中不需要中间表。

定义User模型

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 获取用户关联的个人信息
     */
    public function profile() {
        /**
         * hasOne三个参数
         *  关联的模型 Profile
         *  关联模型Profile的外键 user_id
         *  当前模型 User 的主键 id
         */
        return $this->hasOne(Profile::class, 'user_id', 'id');
    }
}

调用形式为:

$profile = User::first()->profile;
echo $profile->realname . PHP_EOL; // 张三
echo $profile->phone . PHP_EOL; // 13500001111

// 修改属性并保存到数据库
// 方法一
$profile->phone = '13566663333';
$profile->save();

// 方法二
$profile->save(['phone' => '13566663333']);
echo $profile->phone . PHP_EOL; // 13566663333

Laravel中不仅仅可以正向关联,还可以定义反向关联。这个通常是我们知道用户的真实姓名realname,但是像知道对应我们系统的具体哪个用户。

定义Profile模型

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Profile extends Model
{
  /**
     * 获取此个人信息对应的系统用户信息
     */
    public function user()
    {
        /**
         * belongsTo 参数
         *  关联的数据模型 User
         *  当前模型 Phone 的外键 user_id
         *  关联模型 User 的主键 id
         */
        return $this->belongsTo(User::class, 'user_id', 'id');
    }
}

调用形式为:

$user = Profile::where(id, 1)->first()->user;

$user->name = 'HolyShit';
$user->save();

echo $user->name . PHP_EOL; // HolyShit
  1. 一对多关系

举个例子,一个文章对应着多个评论信息

posts表结构与表数据为:

id title content created_at updated_at
1 标题1 文章内容 2019-09-10 18:10:00 2019-09-10 18:10:00

comments表结构与表数据为:

id post_id user_id parent_id content created_at updated_at
1 1 1 0 不错支持楼主 2019-09-10 18:10:00 2019-09-10 18:10:00
2 1 1 0 66666 2019-09-10 18:10:00 2019-09-10 18:10:00
3 1 1 0 必须支持 2019-09-10 18:10:00 2019-09-10 18:10:00

定义Post模型

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    /**
     * 获取Post信息对应的评论
     */
    public function comments() {
        /**
         * hasMany三个参数
         *  关联的模型 Comment
         *  关联模型Comment的外键 post_id
         *  当前模型 Post 的主键 id
         */
        return $this->hasMany(Comment::class, 'post_id', 'id');
    }
}

调用方法为:

$comments = Post::first()->comments;

foreach($comments as $comment) {
    echo $comment->content . PHP_EOL;
}

定义Comment模型反向关联

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    /**
     * 获取Post信息
     */
    public function post() {
        /**
         * belongsTo 三个参数
         * 	关联的数据模型 Post
         *  当前模型 Comment 的外键 post_id
         *  关联模型 Post 的主键 id
         */
        return $this->belongsTo(Post::class, 'post_id', 'id');
    }
}

调用方法为:

$post = Comment::first()->post;

echo $post->title . PHP_EOL; // 标题1
  1. 多对多关系

举个例子,一个用户可以有多个角色,一个角色可以有多个用户

users用户表结构和表数据为:

id name created_at updated_at
1 张三 2019-09-10 18:10:00 2019-09-10 18:10:00
2 李四 2019-09-10 18:10:00 2019-09-10 18:10:00
3 王五 2019-09-10 18:10:00 2019-09-10 18:10:00

roles角色表结构和表数据为:

id name created_at updated_at
1 超级管理员 2019-09-10 18:10:00 2019-09-10 18:10:00
2 管理员 2019-09-10 18:10:00 2019-09-10 18:10:00
3 普通用户 2019-09-10 18:10:00 2019-09-10 18:10:00
4 销售 2019-09-10 18:10:00 2019-09-10 18:10:00

role_user角色用户关系表和表数据为:

role_id user_id created_at updated_at
1 1 2019-09-10 18:10:00 2019-09-10 18:10:00
2 3 2019-09-10 18:10:00 2019-09-10 18:10:00
3 3 2019-09-10 18:10:00 2019-09-10 18:10:00
4 1 2019-09-10 18:10:00 2019-09-10 18:10:00
2 2 2019-09-10 18:10:00 2019-09-10 18:10:00
4 2 2019-09-10 18:10:00 2019-09-10 18:10:00
3 2 2019-09-10 18:10:00 2019-09-10 18:10:00

定义User模型

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 用户拥有的角色
     */
    public function roles()
    {
        /**
         * belongsToMany 参数描述
         * 	关联的模型类名 Role
         *  中间表表名
         *  关联模型 Role 在中间模型的外键名称 role_id
         *  当前模型 User 在中间模型中的外键名称 user_id
         */
        return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id')->withPivot('created_at', 'updated_at');
    }
}

调用方法为:

$roles = User::find(1)->roles;

foreach($roles as $role) {
	echo $role->name . PHP_EOL;
}

// 输出结果:
// 超级管理员
// 销售

定义Role模型

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    /**
     * 角色下的用户
     */
    public function users()
    {
        /**
         * belongsToMany 参数描述
         * 	关联的模型类名 User
         *  中间表表名
         *  关联模型 User 在中间模型的外键名称 user_id
         *  当前模型 Role 在中间模型中的外键名称 role_id
         */
        return $this->belongsToMany(User::class, 'role_user', 'user_id', 'role_id')->withPivot('created_at', 'updated_at');
    }
}

调用方法为:

$users = Role::find(2)->users;

foreach ($users as $user) {
	echo $user->name . PHP_EOL;
}

// 输出结果:
// 李四
// 王五

上面我们使用了withPivot方法,他是针对多对多中的中间表role_user多出了两个字段 created_at 和 updated_at,如果你需要访问这两个字段,必须在关联的时候指出。