详解PHP laravel中多对多关系的代码实例
数据表之间是纵横交叉、相互关联的,laravel的一对一,一对多比较好理解,官网介绍滴很详细了,在此我就不赘述啦,重点我记下多对多的关系
一种常见的关联关系是多对多,即表A的某条记录通过中间表C与表B的多条记录关联,反之亦然。比如一个用户有多种角色,反之一个角色对应多个用户。
为了测试该关联关系,我们沿用官网的用户角色示例:
需要三张数据表:users、roles 和 role_user,role_user 表按照关联模型名的字母顺序命名(这里role_user是中间表),并且包含 user_id 和 role_id两个列。
多对多关联通过编写返回 belongsToMany 方法返回结果的方法来定义。废话不说多,直接上数据结构:
1:创建一个角色表roles,并添加一些初始化数据:
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structureforusers
-- ----------------------------
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-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT-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 (Ƈ','admin','admin@163.com','$2y$10$J/yXqscucanrHAGZp9G6..Tu1Md.SOljX3M8WrHsUdrgat4zeSuhC','ilocXtjZJwhrmIdLG1cKOYegeCwQCkuyx1pYAOLuzY2PpScQFT5Ss7lBCi7i',-04-21 16:26:23',-12-14 09:29:59');
INSERT INTO `users` VALUES (ƈ','baidu',�@qq.com','$2y$10$2A5zJ4pnJ5uCp1DN3NX.5uj/Ap7P6O4nP2BaA55aFra8/rti1K6I2', null,-04-22 06:48:10',-04-22 06:48:10');
INSERT INTO `users` VALUES (Ɖ','fantasy',@qq.com','', null,-06-14 10:38:57',-06-15 10:39:01');
2:创建一个角色表roles,并添加一些初始化数据:
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structureforroles
-- ----------------------------
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-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT-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 (Ƈ','超级版主',-04-21 16:26:23',-12-14 09:29:59');
INSERT INTO `roles` VALUES (ƈ','司令',-04-22 06:48:10',-04-22 06:48:10');
INSERT INTO `roles` VALUES (Ɖ','军长',-06-14 10:38:57',-06-15 10:39:01');
INSERT INTO `roles` VALUES (Ɗ','司长',-06-07 10:41:41',-06-15 10:41:51');
INSERT INTO `roles` VALUES (Ƌ','团战',-06-22 10:41:44',-06-28 10:41:54');
INSERT INTO `roles` VALUES (ƌ','小兵',-06-22 10:41:47',-06-22 10:41:56');
3:创建一个中间表role_user用于记录users表与roles表的对应关系,并添加一些初始化数据:
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structureforrole_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 (Ƈ',Ƈ',ƈ',-06-07 11:42:13',-06-21 11:32:16');
INSERT INTO `role_user` VALUES (ƈ',Ƈ',Ɖ',-06-07 11:32:13',-06-07 11:22:13');
INSERT INTO `role_user` VALUES (Ɖ',ƈ',Ɗ',-06-07 11:32:13',-06-07 11:12:13');
INSERT INTO `role_user` VALUES (Ɗ',Ƈ',Ƌ',-06-07 11:32:13',-06-07 11:22:13');
INSERT INTO `role_user` VALUES (Ƌ',Ɖ',ƌ',-06-07 11:32:13',-06-07 11:52:13');
INSERT INTO `role_user` VALUES (ƌ',Ɖ',ƈ',-06-07 11:32:13',-06-07 11:42:13');
INSERT INTO `role_user` VALUES (ƍ',ƈ',ƈ',-06-07 11:42:13',-06-07 11:52:13');
注意我们定义中间表的时候没有在结尾加s并且命名规则是按照字母表顺序,将role放在前面,user放在后面,并且用_分隔,这一切都是为了适应Eloquent模型关联的默认设置:在定义多对多关联的时候如果没有指定中间表,Eloquent默认的中间表使用这种规则拼接出来。
创建一个Role模型:
<?php
namespaceApp\Models;
useIlluminate\Database\Eloquent\Model;
/**
* Class Role
* @package App\Models
* @mixin \Eloquent
*/
classRoleextendsModel
{
}
然后我们在 User 模型上定义 roles 方法:
<?php
namespaceApp\Models;
useIlluminate\Database\Eloquent\Model;
/**
* Class User
* @package App\Models
* @mixin \Eloquent
*/
classUserextendsModel
{
/**
* 用户角色
*/
publicfunctionroles()
{
return$this->belongsToMany('App\Models\Role');
}
}
注:正如我们上面提到的,如果中间表不是role_user,那么需要将中间表作为第二个参数传入belongsToMany方法,如果中间表中的字段不是user_id和role_id,这里我们姑且将其命名为$user_id和$role_id,那么需要将$user_id作为第三个参数传入该方法,$role_id作为第四个参数传入该方法,如果关联方法名不是roles还可以将对应的关联方法名作为第五个参数传入该方法。
接下来我们在控制器中编写测试代码:
<?php
$user= User::find(1);
$roles=$user->roles;
echo'用户'.$user->name.'所拥有的角色:'
foreach($rolesas$role)
echo$role->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
namespaceApp\Models;
useIlluminate\Database\Eloquent\Model;
/**
* Class Role
* @package App\Models
* @mixin \Eloquent
*/
classRoleextendsModel
{
/**
* 角色用户
*/
publicfunctionusers()
{
return$this->belongsToMany('App\Models\User');
}
}
正如你所看到的,定义的关联关系和与其对应的User 中定义的一模一样,只是前者引用 App\Models\Role,后者引用App\Models\User,由于我们再次使用了 belongsToMany 方法,所有的常用表和键自定义选项在定义与多对多相对的关联关系时都是可用的。
测试代码如下:
$role= Role::find(2);
$users=$role->users;
echo'角色#'.$role->name.'下面的用户:'
foreach($usersas$user)
echo$user->name.' '//对应输出为:角色#司令下面的用户:admin fantasy baidu
正如你看到的,处理多对多关联要求一个中间表。Eloquent 提供了一些有用的方法来与这个中间表进行交互,例如,我们假设 User 对象有很多与之关联的 Role 对象,访问这些关联关系之后,我们可以使用这些模型上的pivot 属性访问中间表字段:
$roles= User::find(1)->roles;
foreach($rolesas$role)
echo$role->pivot->role_id.'
'//对应输出为:2 3 5
注意我们获取到的每一个 Role 模型都被自动赋上了 pivot 属性。该属性包含一个代表中间表的模型,并且可以像其它 Eloquent 模型一样使用。
默认情况下,只有模型主键才能用在 pivot 对象上,如果你的 pivot 表包含额外的属性,必须在定义关联关系时进行指定:
return$this->belongsToMany('App\Models\Role')->withPivot('column1','column2');
比如我们修改role_user表增加一个字段 username 数据如下:
修改模型User:
<?php
namespaceApp\Models;
useIlluminate\Database\Eloquent\Model;
/**
* Class User
* @package App\Models
* @mixin \Eloquent
*/
classUserextendsModel
{
/**
* 用户角色
*/
publicfunctionroles()
{
//return $this->belongsToMany('App\Models\Role');
return$this->belongsToMany('App\Models\Role')->withPivot('username');
}
}
测试代码如下:
$user= User::find(1);
foreach($user->rolesas$role)
echo$role->pivot->username;//对应输出为:马特马特2马特3
如果你想要你的 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();
以上所述是小编给大家介绍的PHP laravel中的多对多关系实例详解,希望对大家有所帮助。
这篇文章主要介绍了PHP简单获取随机数的方法,结合实例形式分析了php实现指定范围随机数与指定字符序列随机数的简单实现技巧,需要的朋友可以参考下本文实例讲述了PHP简单获取随机数的常用方法。分享给大家供大家参考,具体如下:
1.直接获取从min-max的数,例如1-20:
代码如下 | 复制代码 |
$randnum= mt_rand(1, 20); |
2.在一个数组里面随机选择一个(验证码的时候需要字母、数字混合的情况)
代码如下 | 复制代码 |
functionrandUid(){ $str="1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20";//要显示的字符,可自己进行增删 $list=explode(",",$str); $cmax=count($list) - 1; $randnum= mt_rand(0,$cmax); $uid=$list[$randnum]; } |
希望本文所述对大家PHP程序设计有所帮助。
本文介绍了php 截取GBK文档某个位置开始的n个字符方法,非常实用,有兴趣的同学可以参考一下本文cut.php:
代码如下 | 复制代码 |
#!/usr/bin/php <?php define('INPUT_FILE','t.txt'); define('OUTPUT_FILE','a.txt'); $pos= max(intval($argv[1]), 0); $len= max(intval($argv[2]), 0); $file_size=filesize(INPUT_FILE); if($pos>=$file_size)exit; $fp=fopen(INPUT_FILE,'rb'); $point= 0;//current byte position $string='' while(ftell($fp) <$file_size) { if($point>=$pos+$len)break;$byte=fread($fp, 1); //php version >= 5.4 $char= unpack('C',$byte)[1]; if($char<= 0x7f) { //single byte if($point>=$pos)$string.=$byte; $point+= 1; continue; }else{ //double bytes if($point>=$pos) { $string.=$byte.fread($fp, 1); }else{ fseek($fp, 1, SEEK_CUR); } $point+= 1; continue; } } fclose($fp); file_put_contents(OUTPUT_FILE,$string); ?> |
源文件t.txt内容:
dkei20王nnso
测试命令:
./cut.php 6 1
查看结果:
hexdump -C t.txt && hexdump -C a.txt
本文主要介绍了PHP获取真实客户端的真实IP(REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR)的方法,具有很好的参考价值。下面跟着小编一起来看下吧REMOTE_ADDR 是你的客户端跟你的服务器“握手”时候的IP。如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP。
HTTP_CLIENT_IP 是代理服务器发送的HTTP头。如果是“超级匿名代理”,则返回none值。同样,REMOTE_ADDR也会被替换为这个代理服务器的IP。
$_SERVER['REMOTE_ADDR']; //访问端(有可能是用户,有可能是代理的)IP
$_SERVER['HTTP_CLIENT_IP']; //代理端的(有可能存在,可伪造)
$_SERVER['HTTP_X_FORWARDED_FOR']; //用户是在哪个IP使用的代理(有可能存在,也可以伪造)
三个值区别如下:
一、没有使用代理服务器的情况:
REMOTE_ADDR = 您的 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示
二、使用透明代理服务器的情况:Transparent Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 您的真实 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。
三、使用普通匿名代理服务器的情况:Anonymous Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
隐藏了您的真实IP,但是向访问对象透露了您是使用代理服务器访问他们的。
四、使用欺骗性代理服务器的情况:Distorting Proxies
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 随机的 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。
五、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示 ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
完全用代理服务器的信息替代了您的所有信息,就象您就是完全使用那台代理服务器直接访问对象。
//获取用户IP $ip='' foreach(array('HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR','HTTP_FROM','REMOTE_ADDR')as$v) { if(isset($_SERVER[$v])) { if(! preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/',$_SERVER[$v])) { continue; } $ip=$_SERVER[$v]; } } uset($ip,$v); |
相关文章
- 如果我们需要安培Laravel4的话最php最低要求要在php5.3.7版本并且我们需要把mcrypt与openss这两个扩展开启才可以,具体步骤我们参考下文。 前面我们介绍我了 com...2016-11-25
- 有一种方法,可以不打开网站而直接查看到这个网站的源代码.. 这样可以有效地防止误入恶意网站... 在浏览器地址栏输入: view-source:http://...2016-09-20
- <?php require('path.inc.php'); header('content-Type: text/html; charset=utf-8'); $borough_id = intval($_GET['id']); if(!$borough_id){ echo ' ...2016-11-25
Laravel 调试工具 laravel-debugbar 打印日志消息
laravel-debugbar 调试工具的教程小编整理了几篇不错的教程,今天我们来看一篇Laravel 调试工具 laravel-debugbar 打印日志消息例子,希望文章对各位有帮助。 其实不...2016-11-25- 本文实例讲述了JS+CSS实现分类动态选择及移动功能效果代码。分享给大家供大家参考,具体如下:这是一个类似选项卡功能的选择插件,与普通的TAb区别是加入了动画效果,多用于商品类网站,用作商品分类功能,不过其它网站也可以用,...2015-10-21
- 本文实例讲述了JS实现自定义简单网页软键盘效果。分享给大家供大家参考,具体如下:这是一款自定义的简单点的网页软键盘,没有使用任何控件,仅是为了练习JavaScript编写水平,安全性方面没有过多考虑,有顾虑的可以不用,目的是学...2015-11-08
- 本文实例讲述了JS基于Mootools实现的个性菜单效果代码。分享给大家供大家参考,具体如下:这里演示基于Mootools做的带动画的垂直型菜单,是一个初学者写的,用来学习Mootools的使用有帮助,下载时请注意要将外部引用的mootools...2015-10-23
- php 取除连续空格与换行代码,这些我们都用到str_replace与正则函数 第一种: $content=str_replace("n","",$content); echo $content; 第二种: $content=preg_replac...2016-11-25
- php简单用户登陆程序代码 这些教程很对初学者来讲是很有用的哦,这款就下面这一点点代码了哦。 <center> <p> </p> <p> </p> <form name="form1...2016-11-25
Laravel 5.1中定义事件、事件监听器以及触发事件例子
下文我们来看一篇关于Laravel 5.1中定义事件、事件监听器以及触发事件例子,希望能够帮助到各位新手朋友的哦。 这里我们基于之前基于模型+缓存对文章增删改查这篇...2016-11-25- 公司一些wordpress网站由于下载的插件存在恶意代码,导致整个服务器所有网站PHP文件都存在恶意代码,就写了个简单的脚本清除。恶意代码示例...2015-10-23
- 其实挺简单的就是if(navigator.userAgent.indexOf('UCBrowser') > -1) {alert("uc浏览器");}else{//不是uc浏览器执行的操作}如果想测试某个浏览器的特征可以通过如下方法获取JS获取浏览器信息 浏览器代码名称:navigator...2015-11-08
- 本文实例讲述了JS实现双击屏幕滚动效果代码。分享给大家供大家参考,具体如下:这里演示双击滚屏效果代码的实现方法,不知道有觉得有用处的没,现在网上还有很多还在用这个特效的呢,代码分享给大家吧。运行效果截图如下:在线演...2015-10-30
- 一、日期减去天数等于第二个日期function cc(dd,dadd){//可以加上错误处理var a = new Date(dd)a = a.valueOf()a = a - dadd * 24 * 60 * 60 * 1000a = new Date(a)alert(a.getFullYear() + "年" + (a.getMonth() +...2015-11-08
- 微信支付,即便交了保证金,你还是处理测试阶段,不能正式发布。必须到你通过程序测试提交订单、发货通知等数据到微信的系统中,才能申请发布。然后,因为在微信中是通过JS方式调用API,必须在微信后台设置支付授权目录,而且要到...2014-05-31
- 本文实例讲述了PHP常用的小程序代码段。分享给大家供大家参考,具体如下:1.计算两个时间的相差几天$startdate=strtotime("2009-12-09");$enddate=strtotime("2009-12-05");上面的php时间日期函数strtotime已经把字符串...2015-11-24
- 小编分享了一段简单的php中文转拼音的实现代码,代码简单易懂,适合初学php的同学参考学习。 代码如下 复制代码 <?phpfunction Pinyin($_String...2017-07-06
php导出csv格式数据并将数字转换成文本的思路以及代码分享
php导出csv格式数据实现:先定义一个字符串 存储内容,例如 $exportdata = '规则111,规则222,审222,规222,服2222,规则1,规则2,规则3,匹配字符,设置时间,有效期'."/n";然后对需要保存csv的数组进行foreach循环,例如复制代...2014-06-07- ecshop商品无限级分类代码 function cat_options($spec_cat_id, $arr) { static $cat_options = array(); if (isset($cat_options[$spec_cat_id]))...2016-11-25
- 本文介绍了如何延迟javascript代码的加载,加快网页的访问速度。 当一个网站有很多js代码要加载,js代码放置的位置在一定程度上将会影像网页的加载速度,为了让我们的网页加载速度更快,本文总结了一下几个注意点...2013-10-13