Une relation commune dans Laravel-many-to-many

零下一度
Libérer: 2023-03-10 16:38:02
original
1534 Les gens l'ont consulté

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');
Copier après la connexion
Notez que lorsque nous définissons la table intermédiaire, nous ne ajoutez des s à la fin et les règles de dénomination sont les suivantes. Par ordre alphabétique, mettez le rôle au premier plan, l'utilisateur au fond, et séparez-les par _. Tout cela est pour s'adapter aux paramètres par défaut de l'association de modèles Eloquent : lors de la définition d'un. association plusieurs-à-plusieurs, si aucune table intermédiaire n'est spécifiée, valeurs par défaut éloquentes. La table intermédiaire est épissée à l'aide de cette règle.

Créer un modèle

 : Role

<?php

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


}
Copier après la connexion

然后我们在 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');
    }
}
Copier après la connexion

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

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

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

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

User::find(1)->roles()->orderBy('name')->get();
Copier après la connexion

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

return $this->belongsToMany('App\Models\Role', 'user_roles');
Copier après la connexion

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

return $this->belongsToMany('App\Models\Role', 'user_roles', 'user_id', 'role_id');
Copier après la connexion

定义相对的关联关系

要定义与多对多关联相对的关联关系,只需在关联模型中调用一下 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');
    }

}
Copier après la connexion

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

测试代码如下:

 = Role::find(2 = -> '角色#'.->name.'下面的用户:' (   ->name.' '
Copier après la connexion

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

 = User::find(1)-> (   ->pivot->role_id.'<br>'
Copier après la connexion

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

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

return $this->belongsToMany('App\Models\Role')->withPivot('column1', 'column2');
Copier après la connexion

比如我们修改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');
    }
}
Copier après la connexion

 测试代码如下:

 = User::find(1 (->roles   ->pivot->
Copier après la connexion

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

return $this->belongsToMany('App\Models\Role')->withTimestamps();
Copier après la connexion
Copier après la connexion

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

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

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

测试代码如下:

$user = User::find(1);print_r($user->roles->toArray());
Copier après la connexion

以上对应输出:

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
                )

        )

)
Copier après la connexion

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

return $this->belongsToMany('App\Models\Role')->withTimestamps();
Copier après la connexion
Copier après la connexion

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

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!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal