从 v1.15 升级到 v1.16
令人兴奋的新功能 🎉
- 新增 facades.DB()
- 新增 facades.Http()
- 重构 facades.Queue()
- facades.Auth() 支持自定义驱动
- make:* 命令生成的文件支持自动注册
- Goravel Installer 支持选择驱动
功能增强 🚀
- 拆分数据库驱动
- Orm 新增特性
- 支持根据数据表创建 Model
- 支持运行时动态获取 SQL 语句
- Migration 新增特性
- Grpc 新增 Shutdown 方法
- Artisan 新增禁用打印颜色选项
- 加解密 env 文件
- 发送邮件支持设置 Header
- Installer 支持自升级
- 多语言文件支持 embed 加载
- Schedule 新增特性
- Request 新增特性
- Route 新增特性
- Testing 支持创建 Cache 镜像
- 不同 JWT Guard 支持设置不同的 secert 与 ttl
- 注册 ServiceProvider 不再依赖顺序
破坏性变化 🛠
- 移除 SQL 迁移
- 优化 Config 模块方法默认值类型
- 优化 Orm 方法
- 优化 Path 方法
- 优化 Request 方法
- 优化 console Confirm 方法
- 优化 Session 自定义驱动方式
- 优化 Testing.Request 方法
- 优化 Carbon 方法
- 优化 str.Snake 方法
- goravel/cloudinary 停止维护
v1.16.1
- 修复发送邮件时 bcc 和 cc 设置无效的问题
- 修复使用队列发送邮件时返回的 error 错误的问题
- 修复使用 Orm Create 方法创建多条记录时会触发 create 事件的问题
- 修复 make:package 命令创建的代码错误的问题
- 修复发布包文件时路径错误的问题
v1.16.3
v1.16.4
v1.16.5
升级指南
随着 Golang v1.22 不再被维护,Goravel v1.16 默认支持 Golang 版本由 1.22 升级为 1.23。
goravel/example 项目由 v1.15 升级到 v1.16 PR 可以作为升级参考:goravel/example#68
1. 更新依赖
go get github.com/goravel/framework@latest
// 如果使用 gin
go get github.com/goravel/gin@latest
// 如果使用 fiber
go get github.com/goravel/fiber@latest
// 如果使用 redis
go get github.com/goravel/redis@latest
// 如果使用 S3
go get github.com/goravel/s3@latest
// 如果使用 Oss
go get github.com/goravel/oss@latest
// 如果使用 Cos
go get github.com/goravel/cos@latest
// 如果使用 Minio
go get github.com/goravel/minio@latest
go mod tidy2. 修改数据库配置
删除数据库配置文件 config/database.go 中自己用不到的 connections,安装自己需要的数据库驱动。
以 Postgres 为例:
- 安装驱动包
go get github.com/goravel/postgres- 添加
postgres.ServiceProvider到config/app.go文件
// config/app.go
import "github.com/goravel/postgres"
"providers": []foundation.ServiceProvider{
...
&postgres.ServiceProvider{},
},- 修改
config/database.go文件中的配置
// config/database.go
import (
"github.com/goravel/framework/contracts/database/driver"
postgresfacades "github.com/goravel/postgres/facades"
)
"connections": map[string]any{
"postgres": map[string]any{
...
++ "via": func() (driver.Driver, error) {
++ return postgresfacades.Postgres("postgres")
++ },
},
},3. 修改 auth.go 配置文件
// config/auth.go
// Supported: "jwt"
"guards": map[string]any{
"user": map[string]any{
"driver": "jwt",
++ "provider": "user",
},
},
++ // Supported: "orm"
++ "providers": map[string]any{
++ "user": map[string]any{
++ "driver": "orm",
++ },
++ },4. 修改 session.go 配置文件
// config/session.go
-- "driver": config.Env("SESSION_DRIVER", "file"),
++ "default": config.Env("SESSION_DRIVER", "file"),
++ "drivers": map[string]any{
++ "file": map[string]any{
++ "driver": "file",
++ },
++ },5. 修改 queue.go 配置文件
如果正在使用 Queue 模块的 Redis 驱动,需相应修改:优化 Queue 配置。
如果没有使用或想要以后使用 database 驱动,需要修改
config/queue.go文件中的配置:
// config/queue.go
-- // Drivers: "sync", "redis"
++ // Drivers: "sync", "database", "custom"
"connections": map[string]any{
"sync": map[string]any{
"driver": "sync",
},
-- "redis": map[string]any{
-- "driver": "redis",
-- "connection": "default",
-- "queue": config.Env("REDIS_QUEUE", "default"),
-- },
++ "database": map[string]any{
++ "driver": "database",
++ "connection": "postgres",
++ "queue": "default",
++ "concurrent": 1,
++ },
},
++ "failed": map[string]any{
++ "database": config.Env("DB_CONNECTION", "postgres"),
++ "table": "failed_jobs",
++ },添加 database 驱动需要的迁移文件: database/migrations/20210101000002_create_jobs_table.go,并在 database/kernel.go 文件中注册该迁移文件。
6. 如果需要使用 HTTP Client
config/http.go 文件中新增 HTTP Client 配置项:
// config/http.go
++ "client": map[string]any{
++ "base_url": config.GetString("HTTP_CLIENT_BASE_URL"),
++ "timeout": config.GetDuration("HTTP_CLIENT_TIMEOUT"),
++ "max_idle_conns": config.GetInt("HTTP_CLIENT_MAX_IDLE_CONNS"),
++ "max_idle_conns_per_host": config.GetInt("HTTP_CLIENT_MAX_IDLE_CONNS_PER_HOST"),
++ "max_conns_per_host": config.GetInt("HTTP_CLIENT_MAX_CONN_PER_HOST"),
++ "idle_conn_timeout": config.GetDuration("HTTP_CLIENT_IDLE_CONN_TIMEOUT"),
++ },7. 如果正在使用 goravel/redis 驱动
需修改 config/cache.go 文件中的配置:
// config/cache.go
"redis": map[string]any{
"driver": "custom",
"connection": "default",
"via": func() (cache.Driver, error) {
-- return redisfacades.Redis("redis"), nil
++ return redisfacades.Cache("redis")
},
},8. 如果正在使用 carbon.DateTime 等方法
需相应修改:优化 Carbon 方法
9. 如果正在使用 session 自定义驱动
需相应修改:优化 Session 自定义驱动方式
10. 如果正在使用 facades.Config() 中的方法
需相应修改:优化 Config 模块方法默认值类型
11. 如果正在使用 SQL 数据迁移
需相应修改:移除 SQL 迁移
12. 如果正在使用 Orm
需相应修改:优化 Orm 方法
13. 如果正在使用 Path 方法
Path 方法由原来返回相对路径改为返回绝对路径,如果正在使用需检查是否需要修改:优化 Path 方法
14. 如果 正在使用 ctx.Request().InputMap 方法
需相应修改:优化 Request 方法
15. 如果正在使用 console.Confirm 方法
需相应修改:优化 console Confirm 方法
16. 如果正在使用 Testing.Request 方法
需相应修改:优化 Testing.Request 方法
功能介绍
新增 facades.DB()
新增 facades.DB() 模块,方便进行数据库的原生操作,比 ORM 速度更快。
新增 facades.Http()
新增一个内置的 HTTP 客户端 facades.Http(),让 API 调用变得轻而易举。
重构 facades.Queue()
v1.15 之前 Queue 仅支持同步驱动与 Redis 驱动,从 v1.16 开始支持数据库驱动及自定义驱动。
新增
jobs和failed_jobs表,用于存储任务及失败任务。新增
queue:retry命令,用于重试失败的任务。新增
queue:failed命令,用于查看失败任务。支持在启动队列任务时设置重试次数。
详情请 查看文档
facades.Auth() 支持自定义驱动
v1.15 之前 Auth 仅支持 JWT 驱动,从 v1.16 开始支持 Session 及自定义驱动,详情请 查看文档。
make:* 命令生成的文件支持自动注册
make:migration、 make:seeder 等命令生成的文件,在生成后会自动注册到框架中,无需像之前一样需要手动注册。
Goravel Installer 支持选择驱动
使用 Goravel Installer 安装新项目的过程中可以选择安装不同的驱动,例如:可以选择安装 goravel/gin 或 goravel/fiber 等。
拆分数据库驱动
之前多个数据库驱动同时集成在框架中,使得软件打包体积变大。 从 v1.16 开始,数据库驱动将作为独立包存在,只需安装自己需要的数据库驱动即可。
| 数据库类型 | 驱动包 |
|---|---|
| Postgres | github.com/goravel/postgres |
| MySQL | github.com/goravel/mysql |
| Sqlserver | github.com/goravel/sqlserver |
| SQLite | github.com/goravel/sqlite |
Orm 新增特性
import (
contractsorm"github.com/goravel/framework/contracts/database/orm"
"github.com/goravel/framework/database/orm"
)
type User struct {
orm.Model
Name string
}
func (r *User) GlobalScopes() []func(contractsorm.Query) contractsorm.Query {
return []func(contractsorm.Query) contractsorm.Query{
func(query contractsorm.Query) contractsorm.Query {
return query.Where("name", "goravel")
},
}
}支持根据数据表创建 Model
make:model 命令新增 --table 选项,用于根据数据表创建 Model:
./artisan make:model --table=users User
// 如果 Model 已存在可以使用 -f 选项强制覆盖
./artisan make:model --table=users -f User支持运行时动态获取 SQL 语句
新增 EnableQueryLog 等方法,用于在运行时动态获取 SQL 语句:
ctx := db.EnableQueryLog(ctx)
facades.Orm().WithContext(ctx).Query().Find()
queryLogs := db.GetQueryLog(ctx)
ctx := db.DisableQueryLog(ctx)Migration 新增特性
- 新增
Change方法(适用于 Postgres, MySQL, Sqlserver),用于修改表结构:
table.String("name").Change()- 新增
RenameColumn方法,用于重命名表列:
table.RenameColumn("old_name", "new_name")- 新增
Comment方法,用于为表添加注释(适用于 Postgres, MySQL):
table.Comment("user table")- 新增
First方法,用于将字段设置为表的第一个字段(适用于 MySQL):
table.String("name").First()- 新增
After方法,用于将字段设置为表的最后一个字段(适用于 MySQL):
table.String("name").After("id")- 新增
Morphs,NullableMorphs,NumericMorphs,UuidMorphs,UlidMorphs方法,用于创建多态关联字段:
table.Morphs("morphable")
// morphable_type, morphable_id- 新增
Uuid,Ulid方法,用于创建 UUID 和 ULID 字段:
table.Uuid("uuid")
table.Ulid("ulid")- 新增
GeneratedAs和Always方法,用于创建生成列(仅 PostgreSQL):
table.String("name").GeneratedAs().Always()Grpc 新增 Shutdown 方法
新增 Shutdown 方法以便优雅的关闭 Grpc,查看文档。
Artisan 新增禁用打印颜色选项
有些命令默认会打印颜色,例如 list 命令。 但在某些终端或日志中颜色值会是乱码。 这时你可以使用 --no-ansi 选项禁用打印颜色:
go run . artisan list --no-ansi加解密 env 文件
你也许想将生产环境的 env 文件添加到版本控制中,但又不想将敏感信息暴露出来,这时你可以加解密 env 文件。
发送邮件支持设置 Header
新增 Headers 方法,用于设置邮件的 Header。
facades.Mail().Headers(map[string]string{"X-Mailer": "Goravel"})Installer 支持自升级
goravel/installer 新增 upgrade 命令,用于 installer 的自身升级:
goravel upgrade
goravel upgrade v1.1.1多语言文件支持 embed 加载
使用 embed 加载时,多语言文件将会被编译到二进制文件中,部署时不再需要多语言文件。
Schedule 新增特性
新增
EverySecond等方法,详细请 查看文档。新增
schedule:run命令,用于手动运行任务。新增
schedule:list方法,用于查看所有任务。
Request 新增特性
- v1.15 之前下面
Request绑定将报错,从 v1.16 开始支持绑定多个文件:
type StoreMediaRequest struct {
Files []*multipart.FileHeader `form:"files" json:"files"`
}- 新增
OriginalPath方法,用于获取原始路由路径:
ctx.Request().OriginPath()Request新增Info方法,用于获取当前请求路由信息:
info := ctx.Request().Info()Request新增Name方法,用于获取当前请求路由名称:
name := ctx.Request().Name()- 当设置
http.request_timeout配置项 为0时,请求将不会超时。
Route 新增特性
- 新增
GetRoutes方法,用于获取所有路由:
routes := facades.Route().GetRoutes()- 新增
Name方法,用于设置路由名称:
facades.Route().Get("users", usersController.Index).Name("users.index")然后可以使用 Info 方法获取路由信息:
route := facades.Route().Info("users.index")- 新增
route:list命令,用于查看所有路由:
./artisan route:listTesting 支持创建 Cache 镜像
新增 Cache 方法,用于创建 Cache 镜像:
cache, err := facades.Testing().Docker().Cache()不同 JWT Guard 支持设置不同的 ttl 与 secert
之前 JWT Guard 的 ttl 与 secret 配置项是全局配置,从 v1.16 开始,你可以为不同的 JWT Guard 设置不同的 ttl 与 secret,查看文档。
注册 ServiceProvider 不再依赖顺序
ServiceProvider 新增可选方法 Relationship() binding.Relationship,用来声明当前 ServicerProvider 的依赖关系,设置了该方法的 ServiceProvider 将不依赖注册顺序,未设置的 ServiceProvider 将被最后注册,例如:
type ServiceProvider struct {
}
func (r *ServiceProvider) Relationship() binding.Relationship {
return binding.Relationship{
Bindings: []string{
BindingSession,
},
Dependencies: []string{
binding.Config,
},
ProvideFor: []string{
binding.Cache,
},
}
}
func (r *ServiceProvider) Register(app foundation.Application) {}
func (r *ServiceProvider) Boot(app foundation.Application) {}移除 SQL 迁移
SQL 迁移被完全移除,请使用 Go 语言迁移。 迁移步骤:
- 移除
config/database.go中的migrations.driver键;
// config/database.go
"migrations": map[string]any{
-- "driver": "sql",
"table": "migrations",
},- 将
database/migrations目录下的 SQL 迁移文件转换为 Go 语言迁移文件:
// Up Run the migrations.
func (r *M20241207095921CreateUsersTable) Up() error {
return facades.Schema().Sql({Original SQL})
}
// Down Reverse the migrations.
func (r *M20241207095921CreateUsersTable) Down() error {
return facades.Schema().Sql({Original SQL})
}- 在
database/kernel.go文件中注册迁移文件;
优化 Config 模块方法默认值类型
之前 GetString、GetInt、GetBool 方法的默认值类型为 any,从 v1.16 开始,默认值类型为 string、int、bool,以保证类型安全。
-- GetString(path string, defaultValue ...any) string
++ GetString(path string, defaultValue ...string) string
-- GetInt(path string, defaultValue ...any) int
++ GetInt(path string, defaultValue ...int) int
-- GetBool(path string, defaultValue ...any) bool
++ GetBool(path string, defaultValue ...bool) bool优化 Orm 方法
- 优化
Count,Distinct,Select,Exists,Sum方法:
-- Count(count *int64) error
++ Count() (int64, error)
-- Distinct(args ...any) Query
++ Distinct(columns ...string) Query
-- Exists(exists *bool) error
++ Exists() (bool, error)
-- Select(query any, args ...any) Query
++ Select(columns ...string) Query
-- Sum(column string, dest any) error
++ Sum(column string) (int64, error)Where方法支持闭包:
facades.Orm().Query().Where(func(query orm.Query) orm.Query {
return query.Where("height", 180).Where("age", 18)
}).FindOrFail(&user, 100)
// SELECT * FROM users WHERE id = 100 AND (height = 180 AND age = 18);优化 Path 方法
- 新增
Resource方法
path.Resource("views/welcome.tmpl")- path 方法返回绝对路径
之前 path 方法返回的是相对于根目录的路径,例如 path.Config("app.go") == config/app.go。 从 v1.16 开始,path 方法返回的是绝对路径,例如 path.Config("app.go") == /Users/goravel/workspace/goravel/config/app.go。
优化 Request 方法
- 修改
InputMap方法默认值类型:
-- ctx.Request().InputMap(key string, defaultValue ...map[string]string) map[string]string
++ ctx.Request().InputMap(key string, defaultValue ...map[string]any) map[string]any- 新增
InputMapArray方法,用于获取数组类型的 Map:
ctx.Request().InputMapArray(key string, defaultValue ...[]map[string]any) []map[string]any- 新增
Files方法,用于获取多个文件:
ctx.Request().Files(name string) ([]filesystem.File, error)优化 console Confirm 方法
修改 Confirm 方法的返回值,简化判断逻辑:
-- Confirm(question string, option ...ConfirmOption) (bool, error)
++ Confirm(question string, option ...ConfirmOption) bool优化 Session 自定义驱动方式
之前,你需要通过 facades.Session().Extend 方法注册驱动。 从 v1.16 开始,你只需要将其添加到 config/session.go 配置文件中即可:
// app/providers/app_service_provider.go
-- facades.Session().Extend("custom", func() session.Driver {
-- return &CustomDriver{}
-- })
// config/session.go
"drivers": map[string]any{
"custom": map[string]any{
"driver": "custom",
"via": func() (session.Driver, error) {
return &CustomDriver{}, nil
},
}
},优化 Testing.Request 方法
优化 WithCookies 和 WithCookie 方法的入参:
-- WithCookies(cookies map[string]string) Request
++ WithCookies(cookies []*http.Cookie) Request
-- WithCookie(key, value string) Request
++ WithCookie(cookie *http.Cookie) Request优化 Carbon 方法
carbon.NewDateTime 等方法原来返回的是 struct 实例,v1.16 开始返回指针,如果你定义了 carbon.DateTime 等类型,需要修改为 *carbon.DateTime 等指针类型。
优化 str.Snake 方法
str.Snake 方法之前会将 userID 转换为 user_i_d,从 v1.16 开始,会转换为 user_id。
goravel/cloudinary 停止维护
goravel/cloudinary 停止维护,请使用 goravel/s3 等其他驱动替代。
优化 Queue 配置
v1.15 之前,Queue 模块的 Redis 驱动使用 RichardKnop/machinery 实现。 从 v1.16 开始,Redis 驱动在 goravel/redis 中提供官方支持。
你依然可以在 v1.16 中使用 Machinery 驱动,但其将在 v1.17 中被移除,建议使用 Redis 驱动。 下面提供两种升级方式:
继续使用 Machinery 驱动
修改 config/queue.go 文件中的配置:
// config/queue.go
"connections": map[string]any{
...
"redis": map[string]any{
-- "driver": "redis",
++ "driver": "machinery",
"connection": "default",
"queue": config.Env("REDIS_QUEUE", "default"),
},
},使用 Redis 队列驱动
修改 config/queue.go 文件中的配置:
// config/queue.go
import (
"github.com/goravel/framework/contracts/queue"
redisfacades "github.com/goravel/redis/facades"
)
"connections": map[string]any{
...
"redis": map[string]any{
-- "driver": "redis",
++ "driver": "custom",
"connection": "default",
"queue": config.Env("REDIS_QUEUE", "default"),
++ "via": func() (queue.Driver, error) {
++ return redisfacades.Queue("redis") // The ` + "`redis`" + ` value is the key of ` + "`connections`" + `
++ },
},
},新的 Redis 队列驱动与原 machinery 队列驱动的任务都保存在同一个 Redis 中,但使用不同的队列名称。 即使你切换为新的 Redis 队列驱动,框架会继续读取原 Machinery 队列驱动的任务,直到 Machinery 中所有任务执行完毕。 与此同时,新的队列任务不再写入 Machinery 队列中,而是写入新的 Redis 队列,并被新的 Redis 队列驱动消费。 以实现两个驱动间的无缝切换。
你可以到 Redis 中查看两个驱动的数据是否被正确写入与消费:
redis-cli
# 获取 Redis 中所有的键
keys
# 查看 Machinery 队列驱动数据(替换 {} 中的值)
LRANGE {app_name}_queues:{queue_name} 0 -1
# 查看 Redis 队列驱动数据(替换 {} 中的值)
LRANGE {app_name}_queues:{connection}_{queue} 0 -1修复发送邮件时 bcc 和 cc 设置无效的问题
goravel/framework: v1.16.1
Issue: #737
修复使用队列发送邮件时返回的 error 错误的问题
goravel/framework: v1.16.1
PR: #1148
修复使用 Orm Create 方法创建多条记录时会触发 create 事件的问题
goravel/framework: v1.16.1
Issue: #738
修复 make:package 命令创建的代码错误的问题
goravel/framework: v1.16.1
Issue: #743
修复发布包文件时路径错误的问题
goravel/framework: v1.16.1
Issue: #749
修复事务中 panic 不会回滚的问题
goravel/framework: v1.16.3
Issue: #762
修复在独立的迁移脚本中添加或删除列时应用报错的问题
goravel/framework: v1.16.3
goravel/postgres: v1.4.1
如果在独立的迁移脚本中添加或删除列,但没有重启应用,将会有下面两个错误:
- DB facade 将会 panic;
- Postgres 驱动将会返回错误:
cached plan must not change result type;
Issue: #768
修复 Orm Select 方法的破坏性升级
goravel/framework: v1.16.3
从 v1.15 升级到 v1.16, Orm Select 方法有一个破坏性变化。 Select 不再支持 db.Raw(),因此添加新的 SelectRaw 方法以便保持之前的代码逻辑。
Issue: #770
修复命令无法被并发执行的问题
goravel/framework: v1.16.4
当在 Schedule 模块中并发执行命令时,可能会由于同时写入而造成执行混乱或 panic。
修复 Queue 不能按预期 Shutdown
goravel/framework: v1.16.5
以前,当队列正在运行时,发送一个 SIGTERM 信号将立即关闭该队列。 修复后队列将等待当前任务执行完成后关闭。
Issue: #807
