Artisan Console
Introduction
Artisan is the CLI tool that comes with Goravel for interacting with the command line. You can access it using facades.Artisan()
. This tool has several useful commands that can assist you in the development of your application. Utilize the following command to view all available commands.
go run . artisan list
Each command also has a "help" feature that shows and explains the arguments and options associated with the command. To see the help screen, just add "help" before the command name.
go run . artisan help migrate
Instead of repeating go run . artisan ...
command, you may want to add an alias to your shell configuration with the terminal command below:
echo -e "\r\nalias artisan=\"go run . artisan\"" >>~/.zshrc
Then you can simply run your commands like this:
artisan make:controller DemoController
Generating Commands
You can use the make:command
command to create a new command in the app/console/commands
directory. Don't worry if this directory does not exist in your application, it will be created the first time you run the make:command
command:
go run . artisan make:command SendEmails
go run . artisan make:command user/SendEmails
Command Structure
After generating your command, assign suitable values to the signature and description properties of the struct. The Handle
method will be called when your command is executed. You need to implement your logic in this method.
package commands
import (
"github.com/goravel/framework/contracts/console"
"github.com/goravel/framework/contracts/console/command"
)
type SendEmails struct {
}
// Signature The name and signature of the console command.
func (receiver *SendEmails) Signature() string {
return "send:emails"
}
// Description The console command description.
func (receiver *SendEmails) Description() string {
return "Send emails"
}
// Extend The console command extend.
func (receiver *SendEmails) Extend() command.Extend {
return command.Extend{}
}
// Handle Execute the console command.
func (receiver *SendEmails) Handle(ctx console.Context) error {
return nil
}
Command I/O
Retrieving Input
When you write console commands, it's typical to collect user input through arguments
or options
. With Goravel, it's extremely easy to retrieve the arguments and options that the user provides.
Arguments
Follow the arguments after the command:
go run . artisan send:emails NAME EMAIL
Get arguments:
func (receiver *SendEmails) Handle(ctx console.Context) error {
name := ctx.Argument(0)
email := ctx.Argument(1)
all := ctx.Arguments()
return nil
}
Options
Options, like arguments, are another form of user input. Options are prefixed by two hyphens (--) when they are provided via the command line.
Definition:
func (receiver *ListCommand) Extend() command.Extend {
return command.Extend{
Flags: []command.Flag{
&command.StringFlag{
Name: "lang",
Value: "default",
Aliases: []string{"l"},
Usage: "language for the greeting",
},
},
}
}
Get:
func (receiver *ListCommand) Handle(ctx console.Context) error {
lang := ctx.Option("lang")
return nil
}
Usage:
go run . artisan emails --lang Chinese
go run . artisan emails -l Chinese
Notice: When using both arguments and options, define the options before the arguments. Example:
// Right
go run . artisan emails --lang Chinese name
// Wrong
go run . artisan emails name --lang Chinese name
Except command.StringFlag
, we can also use other type Flag
and Option*
: StringSliceFlag
, BoolFlag
, Float64Flag
, Float64SliceFlag
, IntFlag
, IntSliceFlag
, Int64Flag
, Int64SliceFlag
.
Prompting For Input
Asking Questions
In addition to arguments and options, you may also prompt the user for input during the execution of a command. The Ask
method will prompt the user with the given question and return their response:
func (receiver *SendEmails) Handle(ctx console.Context) error {
name := ctx.Ask("What is your name?")
email := ctx.Ask("What is your email address?")
return nil
}
Additionally, you can pass options to the Ask
method as optional second argument:
func (receiver *SendEmails) Handle(ctx console.Context) error {
name := ctx.Ask("What is your name?", console.AskOption{
Default: "Krishan",
})
return nil
}
// Available options
type AskOption struct {
// Default the default value for the input.
Default string
// Description the input description.
Description string
// Lines the number of lines for the input.(use for multiple lines text)
Lines int
// Limit the character limit for the input.
Limit int
// Multiple determines if input is single line or multiple lines text
Multiple bool
// Placeholder the input placeholder.
Placeholder string
// Prompt the prompt message.(use for single line input)
Prompt string
// Validate the input validation function.
Validate func(string) error
}
Sometimes you may need to hide the user input, such as when prompting for a password. You can use the Secret
method to hide the user input:
func (receiver *SendEmails) Handle(ctx console.Context) error {
password := ctx.Secret("What is the password?", console.SecretOption{
Validate: func (s string) error {
if len(s) < 8 {
return errors.New("password length should be at least 8")
}
return nil
},
})
return nil
}
// Available options
type SecretOption struct {
// Default the default value for the input.
Default string
// Description the input description.
Description string
// Limit the character limit for the input.
Limit int
// Placeholder the input placeholder.
Placeholder string
// Validate the input validation function.
Validate func(string) error
}
Confirming Actions
If you need to ask the user to confirm an action before proceeding, you may use the Confirm
method. By default, this method will return false
unless the user select affirmative option.
if !ctx.Confirm("Do you wish to continue?") {
// ...
}
You can also pass a second argument to the Confirm
method to customize the default value, label of the affirmative and negative buttons:
if !ctx.Confirm("Do you wish to continue?", console.ConfirmOption{
Default : true,
}) {
// ...
}
// Available options
type ConfirmOption struct {
// Affirmative label for the affirmative button.
Affirmative string
// Default the default value for the input.
Default bool
// Description the input description.
Description string
// Negative label for the negative button.
Negative string
}
Single Select Questions
If you need to ask the user to select an option from a list of options, you may use the Choice
method. The Choice
method will return the value of the selected option:
question := "What is your favorite programming language?"
options := []console.Choice{
{Key: "go", Value: "Go"},
{Key: "php", Value: "PHP"},
{Key: "python", Value: "Python"},
{Key: "cpp", Value: "C++", Selected: true},
}
color, err := ctx.Choice(question, options)
Additionally, you can pass options to the Choice
method as optional second argument:
question := "What is your favorite programming language?"
options := []console.Choice{
{Key: "go", Value: "Go"},
{Key: "php", Value: "PHP"},
{Key: "python", Value: "Python"},
{Key: "cpp", Value: "C++", Selected: true},
}
color, err := ctx.Choice(question, options, console.ChoiceOption{
Default: "go",
})
// Available options
type ChoiceOption struct {
// Default the default value for the input.
Default string
// Description the input description.
Description string
// Validate the input validation function.
Validate func(string) error
}
Multiple Select Questions
If you need to ask the user to select multiple options from a list of options, you may use the MultiSelect
method. The MultiSelect
method will return the values of the selected options:
question := "What are your favorite programming languages?"
options := []console.Choice{
{Key: "go", Value: "Go"},
{Key: "php", Value: "PHP"},
{Key: "python", Value: "Python"},
{Key: "cpp", Value: "C++", Selected: true},
}
colors, err := ctx.MultiSelect(question, options)
Additionally, you can pass options to the MultiSelect
method as optional second argument:
question := "What are your favorite programming languages?"
options := []console.Choice{
{Key: "go", Value: "Go"},
{Key: "php", Value: "PHP"},
{Key: "python", Value: "Python"},
{Key: "cpp", Value: "C++", Selected: true},
}
colors, err := ctx.MultiSelect(question, options, console.MultiSelectOption{
Default: []string{"go", "php"},
})
// Available options
type MultiSelectOption struct {
// Default the default value for the input.
Default []string
// Description the input description.
Description string
// Filterable determines if the choices can be filtered, type `/` to starting filter.
Filterable bool
// Limit the number of choices that can be selected.
Limit int
// Validate the input validation function.
Validate func([]string) error
}
Writing Output
Sometimes you may need to write output to the console. Goravel provides several methods to assist you in writing output to the console. Each of the method have their appropriate colorized output. For example, Error
will display the text in red.
func (receiver *SendEmails) Handle(ctx console.Context) error {
ctx.Comment("This is a comment message")
ctx.Info("This is an info message")
ctx.Error("This is an error message")
ctx.Line("This is a line message")
ctx.Warning("This is a warning message")
return nil
}
You can use the NewLine
method to write a new line to the console:
// write single blank line
ctx.NewLine()
// write multiple blank lines
ctx.NewLine(2)
Progress Bars
For long-running tasks, it is often helpful to provide the user with some indication of how much time the task will take. You may use the WithProgressBar
method to display a progress bar.
items := []any{"item1", "item2", "item3"}
_, err := ctx.WithProgressBar(items, func(item any) error {
// performTask(item)
return nil
})
Sometimes you may need to update the progress bar manually. You can use the CreateProgressBar
method to update the progress bar:
users := []string{"user1", "user2", "user3"}
bar := ctx.CreateProgressBar(len(users))
err := bar.Start()
for _, user := range users {
// process user
bar.Advance()
// sleep for a while to simulate processing
time.Sleep(time.Millisecond * 50)
}
err = bar.Finish()
Spinner
If you need to display a spinner while a task is running, you may use the Spinner
method.
err := ctx.Spinner("Loading...", console.SpinnerOption{
Action: func() error {
// when to stop the spinner
time.Sleep(2 * time.Second)
return nil
},
})
Category
You can set a set of commands to the same category, convenient in go run . artisan list
:
// Extend The console command extend.
func (receiver *ConsoleMakeCommand) Extend() command.Extend {
return command.Extend{
Category: "make",
}
}
Registering Commands
All of your console commands need to be registered within the Commands
function in app\console\kernel.go
.
func (kernel Kernel) Commands() []console.Command {
return []console.Command{
&commands.SendEmails{},
}
}
Programmatically Executing Commands
Sometimes you may wish to execute an Artisan command outside of the CLI, you can use the Call
method on the facades.Artisan()
to operate this.
facades.Route().Get("/", func(c *gin.Context) {
facades.Artisan().Call("emails")
facades.Artisan().Call("emails --lang Chinese name") // With arguments and options
})