>백엔드 개발 >PHP 튜토리얼 >laravel-many-to-many의 일반적인 관계

laravel-many-to-many의 일반적인 관계

零下一度
零下一度원래의
2017-06-23 13:16:141575검색

데이터 테이블은 서로 교차되어 있고 서로 연관되어 있습니다. Laravel의 일대일 및 일대다 테이블은 이해하기 쉽습니다. 다대다 관계에 중점을 둡니다.

일반적인 연관 관계는 다대다입니다. 즉, 테이블 A의 레코드는 중간 테이블 C를 통해 테이블 ​​B의 여러 레코드와 관련되며 그 반대의 경우도 마찬가지입니다. 예를 들어, 사용자는 여러 역할을 갖고, 반대로 하나의 역할은 여러 사용자에 해당합니다.

이 연관성을 테스트하기 위해 공식 웹사이트의 사용자 역할 예를 사용합니다.

3개의 데이터 테이블이 필요합니다: users, rolesrole_user 에서 role_user 테이블은 연관된 모델 이름의 알파벳 순서로 이름이 지정되며(여기서 role_user는 중간 테이블입니다) user_id라는 두 개의 열을 포함합니다. >role_id. usersroles 和 role_userrole_user 表按照关联模型名的字母顺序命名(这里role_user是中间表),并且包含 user_id 和 role_id两个列。

多对多关联通过编写返回 belongsToMany 方法返回结果的方法来定义。废话不说多,直接上数据结构:

1:创建一个角色表roles,并添加一些初始化数据:

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `password` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
 `remember_token` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
 `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
 `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
 PRIMARY KEY (`id`),
 UNIQUE KEY `users_email_unique` (`email`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES ('1', 'admin', 'admin@163.com', 'y$J/yXqscucanrHAGZp9G6..Tu1Md.SOljX3M8WrHsUdrgat4zeSuhC', 'ilocXtjZJwhrmIdLG1cKOYegeCwQCkuyx1pYAOLuzY2PpScQFT5Ss7lBCi7i', '2016-04-21 16:26:23', '2016-12-14 09:29:59');
INSERT INTO `users` VALUES ('2', 'baidu', '10940370@qq.com', 'yA5zJ4pnJ5uCp1DN3NX.5uj/Ap7P6O4nP2BaA55aFra8/rti1K6I2', null, '2016-04-22 06:48:10', '2016-04-22 06:48:10');
INSERT INTO `users` VALUES ('3', 'fantasy', '1009@qq.com', '', null, '2017-06-14 10:38:57', '2017-06-15 10:39:01');

2:创建一个角色表roles,并添加一些初始化数据:

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for roles
-- ----------------------------
DROP TABLE IF EXISTS `roles`;
CREATE TABLE `roles` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
 `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- ----------------------------
-- Records of roles
-- ----------------------------
INSERT INTO `roles` VALUES ('1', '超级版主', '2016-04-21 16:26:23', '2016-12-14 09:29:59');
INSERT INTO `roles` VALUES ('2', '司令', '2016-04-22 06:48:10', '2016-04-22 06:48:10');
INSERT INTO `roles` VALUES ('3', '军长', '2017-06-14 10:38:57', '2017-06-15 10:39:01');
INSERT INTO `roles` VALUES ('4', '司长', '2017-06-07 10:41:41', '2017-06-15 10:41:51');
INSERT INTO `roles` VALUES ('5', '团战', '2017-06-22 10:41:44', '2017-06-28 10:41:54');
INSERT INTO `roles` VALUES ('6', '小兵', '2017-06-22 10:41:47', '2017-06-22 10:41:56');

3:创建一个中间表role_user用于记录users表与roles表的对应关系,并添加一些初始化数据:

SET FOREIGN_KEY_CHECKS=0;-- ------------------------------ Table structure for role_user-- ----------------------------DROP TABLE IF EXISTS `role_user`;CREATE TABLE `role_user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `role_id` int(11) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;-- ------------------------------ Records of role_user-- ----------------------------INSERT INTO `role_user` VALUES ('1', '1', '2', '2017-06-07 11:42:13', '2017-06-21 11:32:16');INSERT INTO `role_user` VALUES ('2', '1', '3', '2017-06-07 11:32:13', '2017-06-07 11:22:13');INSERT INTO `role_user` VALUES ('3', '2', '4', '2017-06-07 11:32:13', '2017-06-07 11:12:13');INSERT INTO `role_user` VALUES ('4', '1', '5', '2017-06-07 11:32:13', '2017-06-07 11:22:13');INSERT INTO `role_user` VALUES ('5', '3', '6', '2017-06-07 11:32:13', '2017-06-07 11:52:13');INSERT INTO `role_user` VALUES ('6', '3', '2', '2017-06-07 11:32:13', '2017-06-07 11:42:13');INSERT INTO `role_user` VALUES ('7', '2', '2', '2017-06-07 11:42:13', '2017-06-07 11:52:13');

注意我们定义中间表的时候没有在结尾加s并且命名规则是按照字母表顺序,将role放在前面,user放在后面,并且用_分隔,这一切都是为了适应Eloquent模型关联的默认设置:在定义多对多关联的时候如果没有指定中间表,Eloquent默认的中间表使用这种规则拼接出来。

创建一个Role

다대다 관계는 belongsToMany 메서드에서 반환된 결과를 반환하는 메서드를 작성하여 정의됩니다. 더 이상 고민하지 않고 바로 데이터 구조로 넘어가겠습니다.
1: roles 역할 테이블을 생성하고 일부 초기화 데이터를 추가합니다: 🎜🎜🎜SET FOREIGN_KEY_CHECKS=0;🎜🎜-- ---- - ----------
-- 사용자를 위한 테이블 구조
-- ---------- - ------------------
`users`가 존재하는 경우 테이블 삭제;
CREATE TABLE `users` (
`id` int( 10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`remember_token` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`created_at` 타임스탬프 NOT NULL DEFAULT '0000-00-00 00:00:00',
` update_at` 타임스탬프 NULL이 아닙니다 기본 '0000-00-00 00:00:00',
기본 키(`id`),
고유 키 `users_email_unique`(`email`) BTREE를 사용함
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;🎜🎜-------------------------------- --
-- 사용자 기록
-- ---------------
INSERT INTO `users` VALUES ( '1', 'admin', 'admin@163.com', '$2y$10$J/yXqscucanrHAGZp9G6..Tu1Md.SOljX3M8WrHsUdrgat4zeSuhC', 'ilocXtjZJwhrmIdLG1cKOYegeCwQCkuyx1pYAOLuzY2PpScQFT5S s7lBCi7i', ' 2016-04-21 16:26 :23', '2016 -12-14 09:29:59');
INSERT INTO `users` VALUES ('2', 'baidu', '10940370@qq.com', '$2y$10$2 A5zJ4pnJ5uCp1DN3NX.5uj/Ap7P6O4nP2BaA55aFra8/ rti1K6I2', null, '2016-04-22 06:48:10', '2016-04-22 06:48:10');
INSERT INTO `users` VALUES (' 3', '판타지' , '1009@qq.com', '', null, '2017-06-14 10:38:57', '2017-06-15 10:39:01');🎜🎜🎜 2: 문자 테이블 roles를 생성하고 일부 초기화 데이터를 추가합니다: 🎜🎜🎜SET FOREIGN_KEY_CHECKS=0;🎜🎜-------------------- ---- -----
-- 역할에 대한 테이블 구조
-- ------------ ---`roles`가 존재하는 경우 테이블 삭제;
CREATE TABLE `roles` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar( 255) COLLATE utf8_unicode_ci NOT NULL,
`created_at` 타임스탬프 NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` 타임스탬프 NOT NULL DEFAULT '0000-00-00 00: 00:00' ,
기본 키(`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;🎜🎜-- ----------- ---- -------------
-- 역할 기록
--------- --- ------
INSERT INTO `roles` VALUES ('1', 'Super Moderator', '2016-04-21 16:26:23', '2016-12-14 09: 29: 59');
INSERT INTO `roles` VALUES ('2', 'Commander', '2016-04-22 06:48:10', '2016-04-22 06:48:10' )
INSERT INTO `roles` VALUES ('3', 'Commander', '2017-06-14 10:38:57', '2017-06-15 10:39:01');
INSERT INTO `roles` VALUES ('4', '이사', '2017-06-07 10:41:41', '2017-06-15 10:41:51');
INSERT INTO `roles` VALUES ('5', '팀 배틀', '2017-06-22 10:41:44', '2017-06-28 10:41:54');
INSERT INTO `roles` VALUES ('6', '小兵', '2017-06-22 10:41:47', '2017-06-22 10:41:56');🎜🎜🎜3: 중간 테이블 role_user 생성 users 테이블과 roles 테이블 간의 대응을 기록하고 일부 초기화 데이터를 추가하는 데 사용됩니다. 🎜🎜
<?php

namespace App\Models;use Illuminate\Database\Eloquent\Model;/**
 * Class Role
 * @package App\Models
 * @mixin \Eloquent */class Role extends Model
{


}
🎜🎜우리가 정의할 때 중간 테이블에서는 끝에 s를 추가하지 않았으며 명명 규칙은 알파벳 순서로 되어 있으며 역할은 앞에, 사용자는 뒤에 _로 구분되어 있습니다. 이 모든 것은 Eloquent 모델 연관의 기본 설정에 적응하기 위한 것입니다. 다대다 연관 정의, 중간 테이블이 지정되지 않은 경우 Eloquent의 기본 중간 테이블은 이 규칙을 사용하여 연결됩니다. 🎜🎜역할 모델 만들기: 🎜🎜
<?php

namespace App\Models;use Illuminate\Database\Eloquent\Model;/**
 * Class User
 * @package App\Models
 * @mixin \Eloquent */class User extends Model
{/**
     * 用户角色     */public function roles()
    {return $this->belongsToMany('App\Models\Role');
    }
}
🎜

然后我们在 User 模型上定义 roles 方法:

<?php

namespace App\Models;use Illuminate\Database\Eloquent\Model;/**
 * Class User
 * @package App\Models
 * @mixin \Eloquent */class User extends Model
{/**
     * 用户角色     */public function roles()
    {return $this->belongsToMany('App\Models\Role');
    }
}

注:正如我们上面提到的,如果中间表不是role_user,那么需要将中间表作为第二个参数传入belongsToMany方法,如果中间表中的字段不是user_idrole_id,这里我们姑且将其命名为$user_id$role_id,那么需要将$user_id作为第三个参数传入该方法,$role_id作为第四个参数传入该方法,如果关联方法名不是roles还可以将对应的关联方法名作为第五个参数传入该方法。

接下来我们在控制器中编写测试代码:

<? = User::find(1 = -> '用户'.->name.'所拥有的角色:'(   ->name.'  '; //对应输出为:用户admin所拥有的角色:司令  军长  团战

 当然,和所有其它关联关系类型一样,你可以调用roles 方法来添加条件约束到关联查询上:

User::find(1)->roles()->orderBy('name')->get();

正如前面所提到的,为了确定关联关系连接表的表名,Eloquent 以字母顺序连接两个关联模型的名字。不过,你可以重写这种约定 —— 通过传递第二个参数到 belongsToMany 方法:

return $this->belongsToMany('App\Models\Role', 'user_roles');

除了自定义连接表的表名,你还可以通过传递额外参数到 belongsToMany 方法来自定义该表中字段的列名。第三个参数是你定义关联关系模型的外键名称,第四个参数你要连接到的模型的外键名称:

return $this->belongsToMany('App\Models\Role', 'user_roles', 'user_id', 'role_id');

定义相对的关联关系

要定义与多对多关联相对的关联关系,只需在关联模型中调用一下 belongsToMany 方法即可。我们在 Role 模型中定义 users 方法:

<?php

namespace App\Models;use Illuminate\Database\Eloquent\Model;/**
 * Class Role
 * @package App\Models
 * @mixin \Eloquent */class Role extends Model
{/**
     * 角色用户     */public function users()
    {return $this->belongsToMany('App\Models\User');
    }

}

 正如你所看到的,定义的关联关系和与其对应的User 中定义的一模一样,只是前者引用 App\Models\Role,后者引用App\Models\User,由于我们再次使用了 belongsToMany 方法,所有的常用表和键自定义选项在定义与多对多相对的关联关系时都是可用的。

测试代码如下:

 = Role::find(2 = -> '角色#'.->name.'下面的用户:' (   ->name.' '

正如你看到的,处理多对多关联要求一个中间表。Eloquent 提供了一些有用的方法来与这个中间表进行交互,例如,我们假设 User 对象有很多与之关联的 Role 对象,访问这些关联关系之后,我们可以使用这些模型上的pivot 属性访问中间表字段:

 = User::find(1)-> (   ->pivot->role_id.'<br>'

 注意我们获取到的每一个 Role 模型都被自动赋上了 pivot 属性。该属性包含一个代表中间表的模型,并且可以像其它 Eloquent 模型一样使用。

默认情况下,只有模型主键才能用在 pivot 对象上,如果你的 pivot 表包含额外的属性,必须在定义关联关系时进行指定:

return $this->belongsToMany('App\Models\Role')->withPivot('column1', 'column2');

比如我们修改role_user表增加一个字段 username 数据如下:

修改模型User:

<?php

namespace App\Models;use Illuminate\Database\Eloquent\Model;/**
 * Class User
 * @package App\Models
 * @mixin \Eloquent */class User extends Model
{/**
     * 用户角色     */public function roles()
    {//return $this->belongsToMany('App\Models\Role');return $this->belongsToMany('App\Models\Role')->withPivot('username');
    }
}

 测试代码如下:

 = User::find(1 (->roles   ->pivot->

如果你想要你的 pivot 表自动包含created_at 和 updated_at 时间戳,在关联关系定义时使用 withTimestamps 方法:

return $this->belongsToMany('App\Models\Role')->withTimestamps();

 通过中间表字段过滤关联关系

你还可以在定义关联关系的时候使用 wherePivot 和 wherePivotIn 方法过滤belongsToMany 返回的结果集:

return $this->belongsToMany('App\Models\Role')->withPivot('username')->wherePivot('username', '马特2');
//return $this->belongsToMany('App\Models\Role')->wherePivotIn('role_id', [1, 2]);

测试代码如下:

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

以上对应输出:

Array
(
    [0] => Array
        (
            [id] => 3[name] => 军长
            [created_at] => 2017-06-14 10:38:57[updated_at] => 2017-06-15 10:39:01[pivot] => Array
                (
                    [user_id] => 1[role_id] => 3[username] => 马特2
                )

        )

)

如果你想要你的pivot表自动包含created_atupdated_at时间戳,在关联关系定义时使用withTimestamps方法:

return $this->belongsToMany('App\Models\Role')->withTimestamps();

这一节我先讲到这里啦,下一节我将讨论更复杂的三种关联关系及其在模型中的定义及使用。未完待续...

위 내용은 laravel-many-to-many의 일반적인 관계의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.