跳轉到內容

從 v1.15 升級到 v1.16

令人興奮的新功能 🎉

功能增強 🚀

破壞性變化 🛠

v1.16.1

升級指南

隨著 Golang v1.22 不再被維護,Goravel v1.16 預設支援的 Golang 版本已從 1.22 升級為 1.23.

goravel/example 項目由 v1.15 升級到 v1.16 PR 可作為升級參考:goravel/example#68.

1. 更新依賴

shell
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. 修改資料庫配置

刪除資料庫配置檔中的 connections,並安裝需要的資料庫驅動。

例如,Postgres:

  1. 安裝驅動包
shell
go get github.com/goravel/postgres
  1. postgres.ServiceProvider 添加到 config/app.go 文件中
go
// config/app.go
import "github.com/goravel/postgres"

"providers": []foundation.ServiceProvider{
  ...
  &postgres.ServiceProvider{},
},
  1. 修改 config/database.go 檔案中的設定
diff
// 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 配置檔案

diff
// config/auth.go

// 支援: "jwt"
"guards": map[string]any{
  "user": map[string]any{
    "driver":   "jwt",
++    "provider": "user",
  },
},

++ // 支援: "orm"
++ "providers": map[string]any{
++   "user": map[string]any{
++     "driver": "orm",
++   },
++ },

4. 修改 session.go 配置檔案

diff
// 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 檔案中的配置:

diff
// config/queue.go

-- // 驅動: "sync", "redis"
++ // 驅動: "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/migrations/20210101000002_create_jobs_table.go,並在 database/kernel.go 文件中註冊該遷移檔案。

6. 如果需要使用 HTTP 客戶端

config/http.go 檔案中添加 HTTP 客戶端配置項:

diff
// 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 檔案中的配置:

diff
// 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()

新增 facades.Http() 模組,方便進行 HTTP 操作。

查看文檔

重構 facades.Queue()

  • 在 v1.15 之前,Queue 僅支持同步與 Redis 驅動,從 v1.16 開始,支持資料庫與自定義驅動。

  • 新增 jobsfailed_jobs 表,用於存儲任務及失敗任務。

  • 新增 queue:retry 命令,用於重試失敗的任務。

  • 新增 queue:failed 命令,用於查看失敗任務。

  • 支持在啟動隊列任務時設置重試次數。

詳情請 查看文檔

facades.Auth() 支持自訂驅動

在 v1.15 之前,Auth 只支持 JWT 驅動,從 v1.16 開始支持 Session 和自定義驅動,請 查看文檔

make:* 命令支持自動註冊

make:migrationmake:seeder 等命令生成的檔案將在生成後自動註冊到框架中,不再需要像以前那樣手動註冊。

Goravel Installer 支持選擇驅動

使用 Goravel Installer 安裝新專案時,可以選擇不同的驅動,例如:可以選擇安裝 goravel/gin 或 goravel/fiber 等。

拆分資料庫驅動

之前多個資料庫驅動集成在框架中,增加了軟體包的大小。 從 v1.16 開始,資料庫驅動將作為獨立包存在,所以只需安裝所需的資料庫驅動。

資料庫類型驅動包
Postgresgithub.com/goravel/postgres
facades.Orm().Connection("mysql")github.com/goravel/mysql
Sqlservergithub.com/goravel/sqlserver
ToRawSqlgithub.com/goravel/sqlite

Orm 新增特性

  • 支持查詢 JSON 字段,查看文檔

  • 支持更新 JSON 字段,查看文檔

  • 模型支持設置 GlobalScope 方法,該方法限制查詢、更新和刪除操作的範圍:

go
import "github.com/goravel/framework/contracts/orm"

type User struct {
  orm.Model
  Name string
}

func (r *User) GlobalScopes() []func(orm.Query) orm.Query {
  return []func(orm.Query) orm.Query{
    func(query orm.Query) orm.Query {
      return query.Where("name", "goravel")
    },
  }
}

支持根據資料表創建 Model

make:model 命令增加 --table 選項,用於根據資料表創建 Model:

shell
./artisan make:model --table=users User

// 如果模型已存在,您可以使用 -f 選項強制覆蓋
./artisan make:model --table=users -f User

支持運行時動態 SQL 語句

新增 EnableQueryLog 方法,用於啟用查詢日誌:

go
ctx := db.EnableQueryLog(ctx)

facades.Orm().WithContext(ctx).Query()
facades.DB().WithContext(ctx).Table()

queryLogs := db.GetQueryLog(ctx)
ctx := db.DisableQueryLog(ctx)

Migration 新增特性

  • 新增 Change 方法以修改表結構(適用於 Postgres, MySQL, Sqlserver):
go
table.String("name").Change()
  • 新增 RenameColumn 方法,用於重命名表的列:
go
table.RenameColumn("old_name", "new_name")
  • 新增 Comment 方法,用於向表添加註釋(適用於 Postgres, MySQL):
go
table.Comment("user table")
  • 新增 First 方法,用於將欄位設置為表的第一個欄位(適用於 MySQL):
go
table.String("name").First()
  • 新增 After 方法,用於將欄位設置為表的最後一個欄位(適用於 MySQL):
go
table.String("name").After("id")
  • 新增 Morphs, NullableMorphs, NumericMorphs, UuidMorphs, UlidMorphs 方法,用於創建多態關聯欄位:
go
table.Morphs("morphable")
// morphable_type, morphable_id
  • 新增 Uuid, Ulid 方法,用於創建 UUID 和 ULID 欄位:
go
table.Uuid("uuid")
table.Ulid("ulid")
  • 新增 GeneratedAsAlways 方法,用於創建生成列(僅限 PostgreSQL):
go
table.String("name").GeneratedAs().Always()

Grpc 新增 Shutdown 方法

新增 Shutdown 方法用於優雅地關閉 Grpc,查看文檔

Artisan 新增禁用輸出顏色選項

一些命令默認會列印顏色,例如 list 命令。 然而,在某些終端或日誌中,顏色值可能會亂碼。 一些命令默認會列印顏色,例如 list 命令。 然而,在某些終端或日誌中,顏色值可能會亂碼。 你可以使用 --no-ansi 選項禁用列印顏色:

shell
go run . artisan list --no-ansi

加解密 env 文件

您可能想將生產環境的 env 文件添加到版本控制中,但您不想暴露敏感信息,您可以加解密 env 文件:

查看文檔

發送郵件支持設置 Header

新增 Headers 方法,用於設置郵件的 Header。

go
facades.Mail().Headers(map[string]string{"X-Mailer": "Goravel"})

Installer 支持自升級

goravel/installer 新增 upgrade 命令,用於升級 installer 自身:

shell
goravel upgrade
goravel upgrade v1.1.1

多語言文件支持 embed 加載

使用嵌入加載時,語言文件將被編譯到二進制文件中,不再需要部署。

查看文檔

Schedule 新增特性

  • 新增 EverySecond 方法等,請 查看文檔

  • 新增 schedule:run 命令,用於手動運行任務。

  • 新增 schedule:list 方法,用於查看所有任務。

Request 新增特性

  • 在 v1.15 之前,以下 Request 綁定將報錯,從 v1.16 開始支持綁定多個文件:
go
type StoreMediaRequest struct {
	Files []*multipart.FileHeader `form:"files" json:"files"`
}
  • 新增 OriginPath 方法,用於獲取原始路由路徑:
go
ctx.Request().OriginPath()
  • 新增 Info 方法,用於獲取路由信息:
go
info := ctx.Request().Info()
  • 新增 Name 方法,用於獲取路由名稱:
go
name := ctx.Request().Name()
  • http.request_timeout 配置項設置為 0 時,請求將不會超時。

Route 新增特性

  • 新增 GetRoutes 方法,用於獲取所有路由:
go
routes := facades.Route().GetRoutes()
  • 新增 Name 方法,用於設置路由名稱:
go
facades.Route().Get("users", usersController.Index).Name("users.index")

然後可以使用 Info 方法獲取路由信息:

go
route := facades.Route().Info("users.index")
  • 新增 route:list 命令,用於查看所有路由:
shell
./artisan route:list

Testing 支持創建 Cache 鏡像

新增 Cache 方法,用於創建 Cache 鏡像:

go
cache, err := facades.Testing().Docker().Cache()

不同 JWT Guard 支持不同配置

在 v1.15 之前,JWT Guard 的 ttlsecret 配置項是全局配置,從 v1.16 開始,您可以為不同的 JWT Guard 設置不同的 ttlsecret查看文檔

ServiceProvider 不再依賴順序

ServiceProvider 新增可選方法 Relationship() binding.Relationship,用於聲明當前 ServicerProvider 的依賴關係,設置了該方法的 ServiceProvider 將不依賴註冊順序,未設置的 ServiceProvider 將被最後註冊,例如:

go
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 語言遷移。遷移步驟: 遷移步驟:

  1. 移除 config/database.go 中的 migrations.driver 鍵;
go
// config/database.go
"migrations": map[string]any{
--  "driver": "sql",
  "table":  "migrations",
},
  1. database/migrations 目錄下的 SQL 遷移文件轉換為 Go 語言遷移文件:
go
// Up 運行遷移。
func (r *M20241207095921CreateUsersTable) Up() error {
    return facades.Schema().Sql({Original SQL})
}

// Down 反轉遷移。
func (r *M20241207095921CreateUsersTable) Down() error {
    return facades.Schema().Sql({Original SQL})
}
  1. database/kernel.go 文件中註冊遷移文件;

優化 Config 模組方法默認值類型

之前 GetStringGetIntGetBool 方法的默認值類型為 any,從 v1.16 開始,默認值類型為 stringintbool,以保證類型安全。

diff
-- 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 方法

  • 優化 CountExists 方法的返回值:
diff
-- 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 方法支持閉包:
go
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 方法
go
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 方法

  1. 修改 InputMap 方法的默認值類型:
diff
-- ctx.Request().InputMap(key string, defaultValue ...map[string]string) map[string]string
++ ctx.Request().InputMap(key string, defaultValue ...map[string]any) map[string]any
  1. 新增 InputMapArray 方法,用於獲取數組類型的 Map:
go
ctx.Request().InputMapArray(key string, defaultValue ...[]map[string]any) []map[string]any
  1. 新增 Files 方法,用於獲取多個文件:
go
ctx.Request().Files(name string) ([]filesystem.File, error)

優化 console Confirm 方法

修改 Confirm 方法的返回值,簡化判斷邏輯:

diff
-- Confirm(question string, option ...ConfirmOption) (bool, error)
++ Confirm(question string, option ...ConfirmOption) bool

優化 Session 自定義驅動方式

之前,你需要通過 facades.Session().Extend 方法註冊驅動。 從 v1.16 開始,你只需要將其添加到 config/session.go 配置文件中即可:

diff
// 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 方法

優化 WithCookiesWithCookie 方法的入參:

diff
-- 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 文件中的配置:

diff
// 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 文件中的配置:

diff
// 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") // ` + "`redis`" + ` 值是 ` + "`connections`" + ` 的鍵
++  },
  },
},

新的 Redis 隊列驅動與原 machinery 隊列驅動的任務都保存在同一個 Redis 中,但使用不同的隊列名稱。即使你切換為新的 Redis 隊列驅動,框架會繼續讀取原 Machinery 隊列驅動的任務,直到 Machinery 中所有任務執行完畢。同時,新的隊列任務不再寫入 Machinery 隊列中,而是寫入新的 Redis 隊列,並被新的 Redis 隊列驅動消費。以實現兩個驅動間的無縫切換。 即使你切換到新的 Redis 隊列驅動,框架將繼續讀取原始 Machinery 隊列驅動任務直到完成所有任務。 同時,新的隊列任務不再寫入 Machinery 隊列,而是寫入新的 Redis 隊列,並由新的 Redis 隊列驅動消費。 實現兩個驅動之間的無縫切換。

你可以檢查 Redis 中兩個驅動的數據,以查看它們是否正確寫入和消費:

shell
redis-cli

# 獲取 Redis 中所有的鍵
keys

# 查看 Machinery 隊列驅動數據(替換 {} 中的值)
LRANGE {app_name}_queues:{queue_name} 0 -1

# 查看 Redis 隊列驅動數據(替換 {} 中的值)
LRANGE {app_name}_queues:{connection}_{queue} 0 -1

Fix bcc and cc cannot be set expectly when sending mail

goravel/framework: v1.16.1

Issue: #737

Fix sending mail via queue returns incorrect error

goravel/framework: v1.16.1

PR: #1148

Fix the orm create events can be triggered when creating multiple records

goravel/framework: v1.16.1

Issue: #738

Fix the make:package command generates incorrect code

goravel/framework: v1.16.1

Issue: #743

Fix the path is incorrect when publishing package files

goravel/framework: v1.16.1

Issue: #749

基於 MIT 许可發佈