laravel多对多关联

model层的多对多关系

表结构
要定义这种关联,需要三个数据库表: users,roles 和 role_user。role_user 表的命名是由关联的两个模型按照字母顺序来的,并且包含了 user_id 和 role_id 字段:

1
2
3
4
5
6
7
8
9
10
11
users
id - integer
name - string

roles
id - integer
name - string

role_user
user_id - integer
role_id - integer

模型结构
多对多关联通过调用 belongsToMany 这个内部方法返回的结果来定义,例如,我们在 User 模型中定义 roles 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
/**
* 用户拥有的角色
*/
public function roles()
{
return $this->belongsToMany('App\Models\Role');
}
}

一旦关联关系被定义后,你可以通过 roles「动态属性」获取用户角色:

1
2
3
4
5
$user = App\Models\User::find(1);

foreach ($user->roles as $role) {
//
}

当然,像其它所有关联模型一样,你可以使用 roles 方法,利用链式调用对查询语句添加约束条件:

1
$roles = App\Models\User::find(1)->roles()->orderBy('name')->get();

正如前面所提到的,为了确定关联连接表的表名,Eloquent 会按照字母顺序连接两个关联模型的名字。当然,你也可以不使用这种约定,传递第二个参数到 belongsToMany 方法即可:

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

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

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

定义反向关联
要定义多对多的反向关联, 你只需要在关联模型中调用 belongsToMany 方法。我们在 Role 模型中定义 users 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
/**
* 拥有此角色的用户
*/
public function users()
{
return $this->belongsToMany('App\Models\User');
}
}

如你所见,除了引入模型为 App\Models\User 外,其它与在 User 模型中定义的完全一样。由于我们重用了 belongsToMany 方法,自定义连接表表名和自定义连接表里的键的字段名称在这里同样适用。

获取中间表字段
就如你刚才所了解的一样,多对多的关联关系需要一个中间表来提供支持, Eloquent 提供了一些有用的方法来和这张表进行交互。例如,假设我们的 User 对象关联了多个 Role 对象。在获得这些关联对象后,可以使用模型的 pivot 属性访问中间表的属性:

1
2
3
4
5
$user = App\Models\User::find(1);

foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}

需要注意的是,我们获取的每个 Role 模型对象,都会被自动赋予 pivot 属性,它代表中间表的一个模型对象,并且可以像其他的 Eloquent 模型一样使用。

默认情况下,pivot 对象只包含两个关联模型的主键,如果你的中间表里还有其他额外字段,你必须在定义关联时明确指出:

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

如果你想让中间表自动维护 created_at 和 updated_at 时间戳,那么在定义关联时附加上 withTimestamps 方法即可:

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

注意:在数据透视表上使用时间戳时,该表必须同时具有 created_at 和 updated_at 时间戳字段。

自定义 pivot 属性名称
如前所述,来自中间表的属性可以使用 pivot 属性访问。但是,你可以自由定制此属性的名称,以便更好的反应其在应用中的用途。

例如,如果你的应用中包含可能订阅的用户,则用户与博客之间可能存在多对多的关系。如果是这种情况,你可能希望将中间表访问器命名为 subscription 取代 pivot。这可以在定义关系时使用 as 方法完成:

1
2
3
return $this->belongsToMany('App\Models\Podcast')
->as('subscription')
->withTimestamps();

一旦定义完成,你可以使用自定义名称访问中间表数据:

1
2
3
4
5
$users = User::with('podcasts')->get();

foreach ($users->flatMap->podcasts as $podcast) {
echo $podcast->subscription->created_at;
}

通过中间表过滤关系
在定义关系时,你还可以使用 wherePivot 和 wherePivotIn 方法来过滤 belongsToMany 返回的结果:

1
2
3
4
5
return $this->belongsToMany('App\Models\Role')->wherePivot('approved', 1);

return $this->belongsToMany('App\Models\Role')->wherePivotIn('priority', [1, 2]);

return $this->belongsToMany('App\Models\Role')->wherePivotNotIn('priority', [1, 2]);

定义中间表模型
如果你想定义一个自定义模型来表示关联关系中的中间表,可以在定义关联时调用 using 方法。自定义多对多中间表模型都必须扩展自 Illuminate\Database\Eloquent\Relations\Pivot 类,自定义多对多(多态)中间表模型必须继承 Illuminate\Database\Eloquent\Relations\MorphPivot 类。例如,我们在写 Role 模型的关联时,使用自定义中间表模型 RoleUser:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
/**
* 拥有此角色的所有用户
*/
public function users()
{
return $this->belongsToMany('App\Models\User')->using('App\Models\RoleUser');
}
}

当定义 RoleUser 模型时,我们要扩展 Pivot 类:

1
2
3
4
5
6
7
8
9
10
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\Pivot;

class RoleUser extends Pivot
{
//
}

你可以组合使用 using 和 withPivot 从中间表来检索列。例如,通过将列名传递给 withPivot 方法,就可以从 UserRole 中间表中检索出 created_by 和 updated_by 两列数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
/**
* 拥有此角色的用户
*/
public function users()
{
return $this->belongsToMany('App\Models\User')
->using('App\Models\RoleUser')
->withPivot([
'created_by',
'updated_by',
]);
}
}

注意: Pivot 模型可能不使用 SoftDeletes 特性。 如果您需要软删除数据关联记录,请考虑将您的数据关联模型转换为实际的 Eloquent 模型。

带有递增 ID 的自定义中继模型
如果你用一个自定义的中继模型定义了多对多的关系,而且这个中继模型拥有一个自增的主键,你应当确保这个自定义中继模型类中定义了一个 incrementing 属性其值为 true。

1
2
3
4
5
6
/**
* 标识 ID 是否自增
*
* @var bool
*/
public $incrementing = true;

文章来源:
https://learnku.com/docs/laravel/8.x/eloquent-relationships/9407#000a62

作者:庞学军

mysql相关知识

mysql优化

- 目前主要是索引的优化
- 给查询的字段添加索引,主键索引,外键索引,唯一索引.
- 数据量不是特别大的时候,足够了
- explain 来查是否命中索引
- 分库分表

mysql基础语句

mysql索引

mysql锁

mysql备份

mysql分表

1
2
3
4
5
6
7
create table newTable as select * oldTable where 1=0; 仅复制表结构

create table newTable as select * oldTable;复制表结构和数据

create table newTable as select * oldTable where a=*** and b=***;复制表结构和部分数据


作者:庞学军

laravel route缓存坑

本地访问没有问题,到测试服务器,一直访问不了,路由错误.
查看route文件路由没问题


最终发现是laravel路由缓存问题
顺便说一下,路由缓存可以大大提高路由注册的速度.
引用Laravel社区Wiki:
路由缓存会大大减少注册所有路由所需的时间。在某些情况下,路由注册的速度甚至能快上 100 倍。
要生成路由缓存,只需执行 artisan 命令

生成路由缓存命令:
php artisan route:cache
清除路由缓存命令:
php artisan route:clear

作者:庞学军

git知识点

总结下git版本管理

  1. git常用命令

    1. git clone #克隆项目
    2. git push #推送
    3. git add #添加
    4. git commit #提交
    5. git checkout #切换分支
    6. git pull #拉取
  2. 要用记不住的命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
* git reset --soft HEAD^ # 取消commit,保留修改的文件
* git reset --hard HEAD^ # 取消commit,不保留修改的文件
* git checkout -b shen-dev(本地分支名) origin/release_dev(远程分支名) #切换远程分支
* git checkout . #恢复工作树文件
* ssh-keygen -t rsa -C "your_email@example.com" #生成新的ssh key
* git stash #git储藏
* git stash list # 储藏列表
* git stash pop # 恢复最近并删除
* git stash drop #移除stash
* git stash show #跟着stash名字
* git stash clear #删除所有缓存的stash
* git stash save #跟着stash名字
* git update-index --assume-unchanged filenname #git 忽略已经追踪的文件
* git update-index --no--assume-unchanged filenname #git 取消忽略已经追踪的文件
  1. git的知识点

  2. 基于git的几大平台

  • github gitlab gitee
  1. 解决问题的命令

git拉取github超时

1
2
3
git config --global --unset http.proxy
git config --global --unset https.proxy
git config http.sslVerify "false"
  1. commit规范

type用于说明 commit 的类别。

feat:新增功能
fix:bug 修复
docs:文档更新
style:不影响程序逻辑的代码修改(修改空白字符,格式缩进,补全缺失的分号等,没有改变代码逻辑)
refactor:重构代码(既没有新增功能,也没有修复 bug)
perf:性能, 体验优化
test:新增测试用例或是更新现有测试
build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交
ci:主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交
chore:不属于以上类型的其他类,比如构建流程, 依赖管理
revert:回滚某个更早之前的提交

相关的资料链接

git官网

git官方中文文档

官网下载速度慢,可以使用阿里云镜像.

阿里云git镜像

作者:庞学军

回调接口高并发

一次高频率请求的优化

第三方平台的高频率回调事件
每分钟1k以上的请求
导致不断的502报错

1.首先接触laravel的频率限制,防止业务不能正常执行.
2.这种回调事件都是可以异步的,因此使用队列,从而快速响应请求防止连接数过多.
3.数据库的表索引优化
4.单独的容器(服务器处理回调事件)

作者:庞学军

go 环境的安装

安装golang

1.下载地址
https://golang.google.cn/dl/

2.添加环境变量
Go\bin 添加到Path环境变量
设置 go GOPROXY

1
2
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

3.配置GOROOT和GOPATH

GOROOT: 配置go的sdk目录
GOPATH: 配置go项目都要放置到这个目录之下

作者:庞学军

第一篇文章(当然是利用githubPage和hexo搭建博客)

简单的介绍下好了,不做为教程.

环境介绍

  • git node
1
2
3
4
5
npm install hexo-cli -g
hexo init blog
cd blog
npm install
hexo server

五行命令就可以本地运行Hexo博客了,就是这么简单.你学会了吗?

hexo g 
  • 生成 public 目录,放到服务器上,就完成了自已的个人博客.

服务器需要钱?

可以利用 githubPages | giteePages |gitlabPages
免费搭建自已的博客

本博客就是利用 githubPages

  • 域名可以自已在阿里云或者腾讯云等购买,解析到对应的网址.
  • 就可以拥有自已域名的免费博客.

文中涉及的相关内容,官方相关资料直通车.

Hexo中文官网
githubPages

作者:庞学军