Maison >développement back-end >tutoriel php >Une relation commune dans Laravel-many-to-many
Les tableaux de données sont entrelacés et liés les uns aux autres. Les un-à-un et un-à-plusieurs de Laravel sont plus faciles à comprendre. Le site officiel le présente en détail, je n'entrerai donc pas dans les détails ici. notez les points clés de plusieurs à plusieurs. La relation
Une relation d'association courante est plusieurs à plusieurs, c'est-à-dire qu'un enregistrement de la table A est lié à plusieurs enregistrements de la table B via la table intermédiaire. C et vice-versa. Par exemple, un utilisateur a plusieurs rôles, et inversement, un rôle correspond à plusieurs utilisateurs.
Afin de tester cette association, nous suivons l'exemple de rôle d'utilisateur du site officiel :
nécessite trois tables de données : users
, roles
et role_user
, et le role_user
la table est basée sur l'association Le nom du modèle est nommé par ordre alphabétique (ici role_user est la table intermédiaire) et contient deux colonnes user_id
et role_id
.
Les relations plusieurs-à-plusieurs sont définies par des méthodes d'écriture qui renvoient les résultats renvoyés par la méthode belongsToMany
. Sans plus attendre, passons directement à la structure des données :
1 : Créez une table de caractères roles
et ajoutez quelques données d'initialisation :
SET FOREIGN_KEY_CHECKS=0;
-------------------------------
-- Structure du tableau pour les utilisateurs
-- -- -- --------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
` id` int(10) non signé 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',
CLÉ PRIMAIRE (`id`),
CLÉ UNIQUE `users_email_unique` (`email`) UTILISANT BTREE
) ENGINE=InnoDB AUTO_INCREMENT= 4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--------------------------------
-- Enregistrements des utilisateurs
---------------------------------------------
INSÉRER DANS LES VALEURS `users` ('1', 'admin', 'admin@163.com', '$2y$10$J/yXqscucanrHAGZp9G6..Tu1Md.SOljX3M8WrHsUdrgat4zeSuhC', 'ilocXtjZJwhrmIdLG1cKOYegeCwQCkuyx1pYAOLuzY2PpScQFT5Ss7lBCi7i ', '21/04/2016 16:26:23', ' 2016-12-14 09:29:59');
INSÉRER DANS LES VALEURS `users` ('2', 'baidu', '10940370@qq.com', '$2y$10$2A5zJ4pnJ5uCp1DN3NX.5uj/Ap7P6O4nP2BaA55aFra8/ rti1K6I2', null, '2016-04-22 06:48:10', '2016-04-22 06:48:10');
INSÉRER DANS LES VALEURS `users` ('3', 'fantasy', '1009@qq.com', '', nul, '2017-06-14 10:38:57', '2017-06-15 10:39:01');
2 : Créez une table de caractères roles
, et ajoutez quelques données d'initialisation :
SET FOREIGN_KEY_CHECKS=0;
-- ------------- ----- ----------
-- Structure de table pour les rôles
-- --------------------- ----- --
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;
------------- ----- ------------
-- Enregistrements de rôles
---------------------- ----- ---
INSÉRER DANS LES VALEURS `rôles` ('1', 'Super Modérateur', '2016-04-21 16:26:23', '2016-12-14 09:29 : 59');
INSÉRER DANS LES VALEURS `rôles` ('2', 'Commandant', '2016-04-22 06:48:10', '2016-04-22 06:48:10');
INSÉRER DANS LES VALEURS `rôles` ('3', 'Commandant de l'armée', '2017-06-14 10:38:57', '2017-06-15 10:39:01');
INSÉRER DANS `rôles` VALEURS ('4', 'Directeur', '2017-06-07 10:41:41', '2017-06-15 10:41:51');
INSÉRER DANS LES `rôles` VALEURS ( '5', 'Bataille en équipe', '2017-06-22 10:41:44', '2017-06-28 10:41:54');
INSÉRER DANS LES VALEURS `rôles` ('6', '小兵' , '2017-06-22 10:41:47', '2017-06-22 10:41:56');
3 : Créer une table intermédiaire role_user
pour enregistrement et la table users
, et ajouter quelques données d'initialisation : 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');
: Role
<?php namespace App\Models;use Illuminate\Database\Eloquent\Model;/** * Class Role * @package App\Models * @mixin \Eloquent */class Role extends Model { }
然后我们在 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_id
和role_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_at
和updated_at
时间戳,在关联关系定义时使用withTimestamps
方法:
return $this->belongsToMany('App\Models\Role')->withTimestamps();
这一节我先讲到这里啦,下一节我将讨论更复杂的三种关联关系及其在模型中的定义及使用。未完待续...
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!