从 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 停止维护
升级指南
随着 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 tidy
2. 修改数据库配置
删除数据库配置文件 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:list
Testing 支持创建 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 方法
- path 方法返回绝对路径
之前 path 方法返回的是相对于根目录的路径,例如 path.Config("app.go") == config/app.go
,从 v1.16 开始,path 方法返回的是绝对路径,例如 path.Config("app.go") == /Users/goravel/workspace/goravel/config/app.go
;
- 新增
Resource
方法
path.Resource("views/welcome.tmpl")
优化 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