Home > Backend Development > PHP Tutorial > A common relationship in laravel-many-to-many

A common relationship in laravel-many-to-many

零下一度
Release: 2023-03-10 16:38:02
Original
1580 people have browsed it

Data tables are intertwined and interrelated. Laravel’s one-to-one and one-to-many are easier to understand. The official website introduction is very detailed. I won’t go into details here. I will note the key points of many-to-many. Relationship

A common association relationship is many-to-many, that is, a record in table A is related to multiple records in table B through intermediate table C, and vice versa. For example, a user has multiple roles, and conversely, one role corresponds to multiple users.

In order to test this association, we follow the user role example on the official website:

requires three data tables: users, roles and role_user, role_user tables are named in alphabetical order of the associated model names (here role_user is an intermediate table), and contain two columns: user_id and role_id .

Many-to-many relationships are defined by writing methods that return the result of the belongsToMany method. Without further ado, let’s go directly to the data structure:

1: Create a role table roles and add some initialization data:

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', '$2y$10$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', '$2y$10$2A5zJ4pnJ5uCp1DN3NX.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: Create a role table roles and add some initialization data:

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', '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', 'Director', '2017-06-07 10:41:41', '2017-06-15 10:41:51');
INSERT INTO `roles` VALUES ('5', 'Team battle', '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: Create an intermediate Table role_user is used to record the correspondence between the users table and the roles table, and add some initialization data:

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');
Copy after login

Note that when we define the intermediate table, we do not add s at the end and the naming rules are in alphabetical order, with role in the front, user in the back, and separated by _. All this is to adapt to the default settings of Eloquent model association. : If no intermediate table is specified when defining a many-to-many association, Eloquent's default intermediate table will be spliced ​​out using this rule.

Create a Role model:

<?php

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


}
Copy after login

然后我们在 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');
    }
}
Copy after login

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

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

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

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

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

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

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

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

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

定义相对的关联关系

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

}
Copy after login

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

测试代码如下:

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

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

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

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

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

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

比如我们修改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');
    }
}
Copy after login

 测试代码如下:

 = User::find(1 (->roles   ->pivot->
Copy after login

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

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

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

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

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

测试代码如下:

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

以上对应输出:

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
                )

        )

)
Copy after login

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

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

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

The above is the detailed content of A common relationship in laravel-many-to-many. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template