Upgrading To v1.16 From v1.15
Exciting New Features 🎉
- Add facades.DB()
- Add facades.Http()
- Reconstruct facades.Queue()
- facades.Auth() supports custom driver
- make:* commands support automatic registration
- Goravel Installer supports selecting driver
Enhancements 🚀
- Split Database Driver
- Orm adds features
- Support creating Model based on data table
- Support runtime dynamic SQL statement
- Migration adds features
- Grpc adds Shutdown method
- Artisan adds disable print colors option
- Encrypt and decrypt env file
- Send email supports setting Header
- Installer supports self upgrade
- Localization supports embed loading
- Schedule adds features
- Request adds features
- Route adds features
- Testing supports creating Cache image
- Different JWT Guard supports different configurations
- ServiceProvider no longer depends on order
Breaking Changes 🛠
- Remove SQL Migration
- Optimize Config module methods default value type
- Optimize Orm methods
- Optimize Path methods
- Optimize Request methods
- Optimize console Confirm methods
- Optimize Session custom driver
- Optimize Testing.Request methods
- Optimize Carbon methods
- Optimize str.Snake methods
- goravel/cloudinary is no longer maintained
v1.16.1
- Fix bcc and cc cannot be set expectly when sending mail
- Fix sending mail via queue returns incorrect error
- Fix the orm create events can be triggered when creating multiple records
- Fix the make:package command generates incorrect code
- Fix the path is incorrect when publishing package files
v1.16.3
- Fix Transaction does not rollback when panic in closure
- Fix errors if adding or removing a column with a separate migration script
- Fix the breaking change of Orm Select method
v1.16.4
v1.16.5
Upgrade Guide
As Golang v1.22 is no longer maintained, the Golang version of Goravel supports has been upgraded from 1.22 to 1.23.
goravel/example project from v1.15 to v1.16 PR can be used as an upgrade reference: goravel/example#68.
1. Update Dependencies
go get github.com/goravel/framework@latest
// If using gin
go get github.com/goravel/gin@latest
// If using fiber
go get github.com/goravel/fiber@latest
// If using redis
go get github.com/goravel/redis@latest
// If using S3
go get github.com/goravel/s3@latest
// If using Oss
go get github.com/goravel/oss@latest
// If using Cos
go get github.com/goravel/cos@latest
// If using Minio
go get github.com/goravel/minio@latest
go mod tidy2. Modify Database Configuration
Delete the connections in the database configuration file config/database.go that you don't need, and install the database driver you need.
For example, Postgres:
- Install the driver package
go get github.com/goravel/postgres- Add
postgres.ServiceProviderto theconfig/app.gofile
// config/app.go
import "github.com/goravel/postgres"
"providers": []foundation.ServiceProvider{
...
&postgres.ServiceProvider{},
},- Modify the configuration in the
config/database.gofile
// 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. Modify auth.go configuration file
// 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. Modify session.go configuration file
// 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. Modify queue.go configuration file
If you are using the Redis driver of the Queue module, you need to modify accordingly: Optimize Queue module configuration.
If you are not using it or want to use the database driver in the future, you need to modify the configuration in the
config/queue.gofile:
// 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",
++ },Add the migration file required for the database driver: database/migrations/20210101000002_create_jobs_table.go, and register the migration file in the database/kernel.go file.
6. If you need to use HTTP Client
Add the HTTP Client configuration item in the config/http.go file:
// 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. If using goravel/redis driver
Need to modify the configuration in the config/cache.go file:
// 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. If using carbon.DateTime etc. methods
Need to modify accordingly: Optimize Carbon methods
9. If using session custom driver
Need to modify accordingly: Optimize Session custom driver
10. If using methods of facades.Config()
Need to modify accordingly: Modify Config module methods default value type
11. If Using SQL Migrations
Need to modify accordingly: Remove SQL Migration
12. If Using Orm
Need to modify accordingly: Optimize Orm methods
13. If Using Path Method
The path method returns the absolute path, if you are using it, you need to check if you need to modify: Optimize Path method
14. If Using ctx.Request().InputMap Method
Need to modify accordingly: Optimize Request method
15. If Using console.Confirm Method
Need to modify accordingly: Optimize console Confirm method
16. If Using Testing.Request method
Need to modify accordingly: Optimize Testing.Request method
Feature Introduction
Add facades.DB()
Add the facades.DB() module, which is convenient for performing native database operations, faster than ORM.
Add facades.Http()
Add the facades.Http() module, which is convenient for performing HTTP operations.
Reconstruct facades.Queue()
Before v1.15, Queue only supported sync and Redis drivers, starting from v1.16, it supports database and custom driver.
Add
jobsandfailed_jobstable, used to store tasks and failed tasks.Add
queue:retrycommand, used to retry failed tasks.Add
queue:failedcommand, used to view failed tasks.Support setting the number of retries when starting the queue task.
facades.Auth() supports custom driver
Before v1.15, Auth only supported JWT driver, starting from v1.16, it supports Session and custom driver, please view document.
make:* commands support automatic registration
The filesmake:migration and make:seeder, etc. commands generated files will be automatically registered to the framework after generation, no longer need to manually register like before.
Goravel Installer supports selecting driver
When installing a new project using Goravel Installer, you can select different drivers, such as: you can choose to install goravel/gin or goravel/fiber, etc.
Split Database Driver
Before multiple database drivers were integrated in the framework, which increased the software package size. Starting from v1.16, the database driver will be a separate package, so you only need to install the database driver you need.
| Database Type | Driver Package |
|---|---|
| Postgres | github.com/goravel/postgres |
| MySQL | github.com/goravel/mysql |
| Sqlserver | github.com/goravel/sqlserver |
| SQLite | github.com/goravel/sqlite |
Orm adds features
Support querying JSON fields, view document.
Support updating JSON fields, view document.
Model supports setting the
GlobalScopemethod, which restricts the scope of the query, update, and delete operations:
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")
},
}
}Support creating Model based on data table
make:model command adds --table option, used to create Model based on data table:
./artisan make:model --table=users User
// If the Model already exists, you can use the -f option to force overwrite
./artisan make:model --table=users -f UserSupport runtime dynamic SQL statement
Add the EnableQueryLog method, which is used to enable query log:
ctx := db.EnableQueryLog(ctx)
facades.Orm().WithContext(ctx).Query()
facades.DB().WithContext(ctx).Table()
queryLogs := db.GetQueryLog(ctx)
ctx := db.DisableQueryLog(ctx)Migration adds features
- Add the
Changemethod to modify the table structure(Apply to Postgres, MySQL, Sqlserver):
table.String("name").Change()- Add the
RenameColumnmethod, for renaming the table column:
table.RenameColumn("old_name", "new_name")- Add the
Commentmethod, for adding a comment to the table (Apply to Postgres, MySQL):
table.Comment("user table")- Add the
Firstmethod, for setting the field as the first field of the table (Apply to MySQL):
table.String("name").First()- Add the
Aftermethod, for setting the field as the last field of the table (Apply to MySQL):
table.String("name").After("id")- Add the
Morphs,NullableMorphs,NumericMorphs,UuidMorphs,UlidMorphsmethods, used to create polymorphic association fields:
table.Morphs("morphable")
// morphable_type, morphable_id- Add the
Uuid,Ulidmethods, used to create UUID and ULID fields:
table.Uuid("uuid")
table.Ulid("ulid")- Add the
GeneratedAsandAlwaysmethods, used to create generated columns (only PostgreSQL):
table.String("name").GeneratedAs().Always()Grpc adds Shutdown method
Add the Shutdown method to gracefully shut down Grpc, View Document.
Artisan adds disable print colors option
Some commands print colors by default, such as the list command. However, in some terminals or logs, the color values may be garbled. You can use the --no-ansi option to disable the print colors:
go run . artisan list --no-ansiEncrypt and decrypt env file
You may want to add the production environment env file to version control, but you don't want to expose sensitive information, you can encrypt and decrypt the env file:
Send email supports setting Header
Add the Headers method, which is used to set the Header of the email.
facades.Mail().Headers(map[string]string{"X-Mailer": "Goravel"})Installer supports self upgrade
goravel/installer adds upgrade command, which is used to upgrade the installer itself:
goravel upgrade
goravel upgrade v1.1.1Localization supports embed loading
When using embed loading, the language files will be compiled into the binary file and no longer need to be deployed.
Schedule adds features
Add the
EverySecondmethod, etc., please view document.Add the
schedule:runcommand, which is used to manually run tasks.Add the
schedule:listmethod, which is used to view all tasks.
Request adds features
- Before v1.15, the following
Requestbinding will report an error, starting from v1.16, it supports binding multiple files:
type StoreMediaRequest struct {
Files []*multipart.FileHeader `form:"files" json:"files"`
}- Add the
OriginPathmethod, which is used to get the original route path:
ctx.Request().OriginPath()- Add the
Infomethod, which is used to get the route information:
info := ctx.Request().Info()- Add the
Namemethod, which is used to get the route name:
name := ctx.Request().Name()- When the
http.request_timeoutconfiguration item is set to0, the request will not timeout.
Route adds features
- Add the
GetRoutesmethod, which is used to get all routes:
routes := facades.Route().GetRoutes()- Add the
Namemethod, which is used to set the route name:
facades.Route().Get("users", usersController.Index).Name("users.index")Then you can use the Info method to get the route information:
route := facades.Route().Info("users.index")- Add the
route:listcommand, which is used to view all routes:
./artisan route:listTesting supports creating Cache image
Add the Cache method, which is used to create Cache image:
cache, err := facades.Testing().Docker().Cache()Different JWT Guard supports different configurations
Before v1.15, the ttl and secret configuration items of the JWT Guard were global configurations, starting from v1.16, you can set different ttl and secret for different JWT Guards, View Document.
ServiceProvider no longer depends on order
ServiceProvider adds an optional method Relationship() binding.Relationship, used to declare the dependency relationship of the current ServicerProvider, the ServiceProvider that sets this method will not depend on the registration order, and the ServiceProvider that does not set it will be registered last, for example:
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) {}Remove SQL Migration
SQL migrations have been completely removed, please use Go language migrations. Migration steps:
- Remove the
migrations.driverkey inconfig/database.go;
// config/database.go
"migrations": map[string]any{
-- "driver": "sql",
"table": "migrations",
},- Convert the SQL migration files in the
database/migrationsdirectory to Go language migration files:
// 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})
}- Register the migration files in the
database/kernel.gofile;
Optimize Config module methods default value type
Before the GetString、GetInt、GetBool method of the Config module had a default value type of any, starting from v1.16, the default value type is string、int、bool, to ensure type safety.
-- 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) boolOptimize Orm methods
- Optimize the return value of the
Count,Existsmethod:
-- 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)- The
Wheremethod supports closures:
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);Optimize Path methods
- Add the
Resourcemethod
path.Resource("views/welcome.tmpl")- The
pathmethod returns the absolute path
Before the path method returned the relative path of the root directory, for example, path.Config("app.go") == config/app.go. Starting from v1.16, the path method returns the absolute path, for example, path.Config("app.go") == /Users/goravel/workspace/goravel/config/app.go.
Optimize Request methods
- Modify the default value type of the
InputMapmethod:
-- ctx.Request().InputMap(key string, defaultValue ...map[string]string) map[string]string
++ ctx.Request().InputMap(key string, defaultValue ...map[string]any) map[string]any- Add the
InputMapArraymethod, which is used to get the array type of Map:
ctx.Request().InputMapArray(key string, defaultValue ...[]map[string]any) []map[string]any- Add the
Filesmethod, which is used to get multiple files:
ctx.Request().Files(name string) ([]filesystem.File, error)Optimize console Confirm methods
Modify the return value of the Confirm method, simplifying the judgment logic:
-- Confirm(question string, option ...ConfirmOption) (bool, error)
++ Confirm(question string, option ...ConfirmOption) boolOptimize Session custom driver
Before, you needed to register the driver through the facades.Session().Extend method. Starting from v1.16, you only need to add it to the config/session.go configuration file:
// 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
},
}
},Optimize Testing.Request methods
Optimize the parameters of the WithCookies and WithCookie methods:
-- WithCookies(cookies map[string]string) Request
++ WithCookies(cookies []*http.Cookie) Request
-- WithCookie(key, value string) Request
++ WithCookie(cookie *http.Cookie) RequestOptimize Carbon methods
Previously, the carbon.NewDateTime, etc. methods return a struct instance, starting from v1.16, it returns a pointer, if you define the carbon.DateTime type, etc., you need to modify it to *carbon.DateTime etc. pointer type.
Optimize str.Snake methods
The str.Snake method previously converted userID to user_i_d, starting from v1.16, it will be converted to user_id.
goravel/cloudinary is no longer maintained
goravel/cloudinary is no longer maintained, please use goravel/s3 or other drivers instead.
Optimize Queue module configuration
Before v1.15, the Redis driver of the Queue module was implemented using RichardKnop/machinery. Starting from v1.16, the Redis driver is officially supported in goravel/redis.
You can still use the Machinery driver in v1.16, but it will be removed in v1.17, it is recommended to use the Redis driver. The following provides two upgrade methods:
Continue using Machinery driver
Modify the configuration in the config/queue.go file:
// config/queue.go
"connections": map[string]any{
...
"redis": map[string]any{
-- "driver": "redis",
++ "driver": "machinery",
"connection": "default",
"queue": config.Env("REDIS_QUEUE", "default"),
},
},Use Redis queue driver
Modify the configuration in the config/queue.go file:
// 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`" + `
++ },
},
},The new Redis queue driver and the original machinery queue driver tasks are stored in the same Redis, but use different queue names. Even if you switch to the new Redis queue driver, the framework will continue to read the original Machinery queue driver tasks until all tasks in Machinery are completed. At the same time, the new queue tasks are no longer written to the Machinery queue, but written to the new Redis queue, and consumed by the new Redis queue driver. To achieve seamless switching between two drivers.
You can check the data of the two drivers in Redis to see if they are correctly written and consumed:
redis-cli
# Get all keys in Redis
keys
# View Machinery queue driver data (replace {} with the value)
LRANGE {app_name}_queues:{queue_name} 0 -1
# View Redis queue driver data (replace {} with the value)
LRANGE {app_name}_queues:{connection}_{queue} 0 -1Fix 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
Fix Transaction does not rollback when panic in closure
goravel/framework: v1.16.3
Issue: #762
Fix errors if adding or removing a column with a separate migration script
goravel/framework: v1.16.3
goravel/postgres: v1.4.1
If adding or removing a column with a separate migration script and the application doesn't restart, the following two errors will occur:
- The DB facade will panic.
- The Postgres driver will report an error:
cached plan must not change result type.
Issue: #768
Fix the breaking change of Orm Select method
goravel/framework: v1.16.3
There is a breaking change when upgrading the Orm Select method to v1.16 from v1.15. Select no longer supports db.Raw(), hence add the new SelectRaw method to avoid the breaking change.
Issue: #770
Fix commands cannot be run concurrently
goravel/framework: v1.16.4
When running commands concurrently in the Schedule module, it may cause chaos or a panic due to concurrent writes.
Fix Queue cannot be shut down as expected
goravel/framework: v1.16.5
Previously, when the Queue worker is running, sending a SIGTERM signal will shut down the worker immediately. Fix it to wait for the current job to complete before shutting down.
Issue: #807
