Artisan là một giao diện dòng lệnh đi kèm với Laravel. Artisan tồn tại ở gốc của ứng dụng của bạn dưới dạng một tập lệnh artisan và cung cấp một số lệnh hữu ích có thể hỗ trợ bạn trong khi bạn xây dựng application. Để xem danh sách tất cả các lệnh Artisan có sẵn, bạn có thể sử dụng lệnh list:
php artisan list
Mỗi lệnh cũng chứa một lệnh "help" để hiển thị và mô tả các tùy chọn và các tham số dành cho lệnh đó. Để xem lệnh help, hãy set help vào trước tên của command:
php artisan help migrate
Nếu bạn đang sử dụng Laravel Sail làm môi trường phát triển local của bạn, hãy nhớ sử dụng dòng lệnh sail để gọi các lệnh Artisan. Sail sẽ thực hiện các lệnh Artisan của bạn trong các Docker container của ứng dụng của bạn:
./vendor/bin/sail artisan list
Laravel Tinker là một REPL mạnh mẽ cho Laravel framework, cung cấp bởi package PsySH.
Mặc định tất cả các ứng dụng Laravel đều chứa Tinker. Tuy nhiên, bạn có thể cài đặt Tinker thông qua Composer nếu trước đó bạn đã xóa nó ra khỏi ứng dụng của bạn:
composer require laravel/tinker
[!NOTE] Nếu bạn đang tìm một công cụ hot reloading, sửa code multiline, và autocompletion khi tương tác với ứng dụng Laravel của bạn? Hãy xem Tinkerwell!
Tinker cho phép bạn tương tác trực tiếp với toàn bộ application Laravel của bạn trên command line, bao gồm cả model Eloquent, job, event, vv... Để vào được môi trường Tinker, hãy chạy lệnh Artisan tinker:
php artisan tinker
Bạn có thể export file cấu hình của Tinker bằng lệnh vendor:publish:
php artisan vendor:publish --provider="Laravel\Tinker\TinkerServiceProvider"
[!WARNING] Hàm helper
dispatchvà phương thứcdispatchtrên classDispatchablephụ thuộc vào việc thu gom rác để set job vào queue. Do đó, khi sử dụng Tinker, bạn nên sử dụngBus::dispatchhoặcQueue::pushđể điều phối job.
Tinker có sử dụng một danh sách "allow" để xác định các lệnh Artisan nào được phép chạy. Mặc định, bạn có thể chạy các lệnh clear-compiled, down, env, inspire, migrate, migrate:install, up, và optimize. Nếu bạn muốn cho phép thêm các lệnh khác, bạn có thể thêm chúng vào mảng commands trong file cấu hình tinker.php của bạn:
'commands' => [
// App\Console\Commands\ExampleCommand::class,
],
Thông thường, Tinker sẽ tự động đặt bí danh cho các class khi bạn tương tác với chúng trong Tinker. Tuy nhiên, bạn có thể muốn không đặt bí danh cho một số class. Bạn có thể thực hiện điều này bằng cách thêm các class đó vào trong mảng dont_alias của file cấu hình tinker.php của bạn:
'dont_alias' => [
App\Models\User::class,
],
Ngoài các lệnh được cung cấp với Artisan, bạn có thể tự xây dựng các lệnh của riêng bạn. Các lệnh thường được lưu trữ trong thư mục app/Console/Commands; tuy nhiên, bạn cũng có thể thoải mái chọn vị trí lưu trữ miễn là bạn hướng dẫn Laravel tìm các thư mục đó để tìm các lệnh Artisan.
Để tạo một lệnh mới, bạn có thể sử dụng lệnh Artisan make:command. Lệnh này sẽ tạo một class command mới trong thư mục app/Console/Commands. Đừng lo lắng nếu thư mục này không tồn tại trong application của bạn, vì nó sẽ được tạo vào lần đầu tiên bạn chạy lệnh Artisan make:command:
php artisan make:command SendEmails
Sau khi đã tạo xong command, bạn hãy định nghĩa định dạng và mô tả của command bằng cách sử dụng các thuộc tính Signature và Description. Thuộc tính Signature cũng cho phép bạn định nghĩa kỳ vọng input đầu vào cho command của bạn. Phương thức handle sẽ được gọi khi lệnh của bạn được thực thi. Bạn có thể cài đặt logic của bạn vào trong phương thức này.
Chúng ta hãy xem một ví dụ về command. Lưu ý rằng chúng ta có thể yêu cầu bất kỳ service nào mà chúng ta muốn thông qua hàm handle của command. Laravel service container sẽ tự động inject tất cả các phụ thuộc đã được khai báo có trong phương thức đó:
<?php
namespace App\Console\Commands;
use App\Models\User;
use App\Support\DripEmailer;
use Illuminate\Console\Attributes\Description;
use Illuminate\Console\Attributes\Signature;
use Illuminate\Console\Command;
#[Signature('mail:send {user}')]
#[Description('Send a marketing email to a user')]
class SendEmails extends Command
{
/**
* Execute the console command.
*/
public function handle(DripEmailer $drip): void
{
$drip->send(User::find($this->argument('user')));
}
}
[!NOTE] Để code của bạn có thể tái sử dụng tốt hơn, thì cách tốt nhất là giữ cho các command của bạn được "nhẹ" và hãy để các application service hoàn thành nhiệm vụ đó cho bạn. Trong ví dụ dưới trên, hãy chú ý rằng chúng ta sẽ inject một service class để thực hiện một "công việc nặng" như việc gửi e-mail.
Nếu không có gì được trả về từ phương thức handle và command sẽ được chạy thành công, và command sẽ exit với exit code là 0, thể hiện sự thành công. Tuy nhiên, phương thức handle có thể tùy ý trả về một số integer để chỉ định exit code của command:
$this->error('Something went wrong.');
return 1;
Nếu bạn muốn command "thất bại" từ bất kỳ phương thức nào có trong command, bạn có thể sử dụng phương thức fail. Phương thức fail sẽ ngay lập tức ngừng chạy command và trả về exit code là 1:
$this->fail('Something went wrong.');
Các command được tạo dựa trên closure sẽ cung cấp thêm một giải pháp để định nghĩa các command. Giống như cách mà các closure route làm, là tạo thêm một cách định nghĩa cho controller, bạn hãy nghĩ các closure command này như là một cách định nghĩa khác cho các class command, thay vì phải tạo ra một file command mới.
Mặc dù file routes/console.php không định nghĩa các HTTP route, nhưng nó định nghĩa các console dựa theo format của route vào trong application của bạn. Trong file này, bạn có thể định nghĩa tất cả các closure dựa trên lệnh console của bạn bằng phương thức Artisan::command. Phương thức command chấp nhận hai tham số: một là một command signature và hai là một closure để nhận vào các tham số và các option của command:
Artisan::command('mail:send {user}', function (string $user) {
$this->info("Sending email to: {$user}!");
});
Closure sẽ được liên kết với một instance command cơ bản, nên bạn có toàn quyền truy cập vào tất cả các phương thức helper mà bạn thường dùng trên một class command cơ bản.
Ngoài việc nhận vào các tham số và các option của command, closure command cũng có thể khai báo thêm các phụ thuộc mà bạn muốn resolve từ service container:
use App\Models\User;
use App\Support\DripEmailer;
use Illuminate\Support\Facades\Artisan;
Artisan::command('mail:send {user}', function (DripEmailer $drip, string $user) {
$drip->send(User::find($user));
});
Khi định nghĩa một command dựa trên closure, bạn có thể sử dụng phương thức purpose để thêm mô tả cho command. Mô tả này sẽ được hiển thị khi bạn chạy lệnh php artisan list hoặc lệnh php artisan help:
Artisan::command('mail:send {user}', function (string $user) {
// ...
})->purpose('Send a marketing email to a user');
[!WARNING] Để sử dụng tính năng này, ứng dụng của bạn phải sử dụng driver cache
memcached,redis,dynamodb,database,filehoặcarraylàm driver cache mặc định cho ứng dụng của bạn. Ngoài ra, tất cả các server phải giao tiếp cùng với một server cache trung tâm.
Thỉnh thoảng bạn có thể muốn đảm bảo rằng một instance của một command chỉ được chạy trong một thời điểm. Để thực hiện điều này, bạn có thể implement interface Illuminate\Contracts\Console\Isolatable trên class command của bạn:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\Isolatable;
class SendEmails extends Command implements Isolatable
{
// ...
}
Khi bạn đánh dấu một command là Isolatable, Laravel sẽ tự động tạo tùy chọn --isolated cho command mà không cần phải định nghĩa nó trong options của command. Khi command được gọi với tùy chọn đó, Laravel sẽ đảm bảo là sẽ không có instance nào khác của command đó được đang chạy. Laravel thực hiện điều này bằng cách thử lấy khóa atomic bằng driver cache mặc định của ứng dụng của bạn. Nếu một instance khác của command này đang chạy, thì command này sẽ không thực hiện; tuy nhiên, command vẫn sẽ được exit với một mã trạng thái thành công:
php artisan mail:send 1 --isolated
Nếu bạn muốn chỉ định một mã trạng thái cụ thể mà command sẽ trả về nếu nó không thể thực hiện, thì bạn có thể cung cấp mã trạng thái đó thông qua tùy chọn isolated:
php artisan mail:send 1 --isolated=12
Mặc định, Laravel sẽ sử dụng tên của command để tạo khóa sẽ được sử dụng để lấy khóa atomic trong bộ nhớ cache của ứng dụng. Tuy nhiên, bạn có thể tùy chỉnh khóa này bằng cách định nghĩa thêm phương thức isolatableId trên class command Artisan của bạn, cho phép bạn tích hợp thêm các tham số hoặc tùy chọn của command vào khóa:
/**
* Get the isolatable ID for the command.
*/
public function isolatableId(): string
{
return $this->argument('user');
}
Mặc định, khóa isolation sẽ hết hạn sau khi command kết thúc. Hoặc nếu command bị lỗi và không thể hoàn thành, thì khóa đó sẽ hết hạn sau một giờ. Tuy nhiên, bạn có thể điều chỉnh thời gian hết hạn của khóa này bằng cách định nghĩa phương thức isolationLockExpiresAt trên command của bạn:
use DateTimeInterface;
use DateInterval;
/**
* Determine when an isolation lock expires for the command.
*/
public function isolationLockExpiresAt(): DateTimeInterface|DateInterval
{
return now()->plus(minutes: 5);
}
Khi viết một lệnh console, thường thu nhận các dữ liệu đầu vào từ người dùng thông qua các tham số hoặc các option. Laravel làm cho nó rất thuận tiện để xác định đầu vào mà bạn mong muốn từ người dùng bằng cách sử dụng thuộc tính signature trên mỗi lệnh của bạn. Thuộc tính signature cho phép bạn định nghĩa tên, tham số và các option cho lệnh theo một cú pháp đơn giản, dễ hiểu, giống như cú pháp trên route.
Tất cả các tham số và các tùy chọn do người dùng cung cấp được wrap trong một dấu ngoặc nhọn. Trong ví dụ sau, lệnh sẽ định nghĩa một tham số bắt buộc: user:
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'mail:send {user}';
Bạn cũng có thể tạo ra tham số tùy chọn hoặc định nghĩa giá trị mặc định cho các tham số đó:
// Optional argument...
'mail:send {user?}'
// Optional argument with default value...
'mail:send {user=foo}'
Tùy chọn, giống như một tham số, là một dạng khác của input user. Các tùy chọn sẽ được gán tiền tố với hai dấu gạch nối (--) khi chúng được cung cấp thông qua cửa sổ dòng lệnh. Có hai loại tùy chọn: loại tùy chọn nhận một giá trị và loại tùy chọn không nhận giá trị nào. Các tùy chọn không nhận giá trị đóng vai trò như là một "switch" boolean. Chúng ta hãy xem một ví dụ về loại tùy chọn này:
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'mail:send {user} {--queue}';
Trong ví dụ này, switch --queue có thể được chỉ định khi gọi lệnh Artisan. Nếu switch --queue được thông qua, giá trị của tùy chọn sẽ là true. Nếu không, giá trị sẽ là false:
php artisan mail:send 1 --queue
Tiếp theo, chúng ta hãy xem một tùy chọn nhận một giá trị. Nếu người dùng phải chỉ định một giá trị cho một tùy chọn, thì bạn hãy thêm hậu tố vào tên của tùy chọn đó bằng dấu =:
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'mail:send {user} {--queue=}';
Trong ví dụ này, người dùng có thể truyền một giá trị cho tùy chọn đó như sau. Nếu tùy chọn không được truyền vào khi chạy command, thì giá trị của nó sẽ là null:
php artisan mail:send 1 --queue=default
Bạn cũng có thể gán một giá trị mặc định cho các tùy chọn này bằng cách chỉ định giá trị mặc định sau tên mỗi tùy chọn. Nếu không có giá trị tùy chọn nào được người dùng truyền vào, thì giá trị mặc định sẽ được sử dụng:
'mail:send {user} {--queue=default}'
Để gán một shortcut khi định nghĩa một tùy chọn, bạn có thể chỉ định nó vào phía trước tên của một tùy chọn và sử dụng ký tự | như một dấu để phân tách shortcut khỏi toàn bộ tên tùy chọn:
'mail:send {user} {--Q|queue=}'
Khi gọi command trên terminal của bạn, các shortcut tùy chọn phải được set bằng một dấu gạch ngang ở đằng trước và không nên có dấu = khi chỉ định giá trị cho tùy chọn:
php artisan mail:send 1 -Qdefault
Nếu bạn muốn định nghĩa các tham số hoặc tùy chọn để nhận vào nhiều giá trị, bạn có thể sử dụng ký tự *. Đầu tiên, chúng ta hãy xem một ví dụ định nghĩa một tham số như sau:
'mail:send {user*}'
Khi chạy lệnh này, các tham số user có thể được truyền theo dòng lệnh. Ví dụ: lệnh sau sẽ set giá trị của user thành một mảng với foo và bar là các giá trị của nó:
php artisan mail:send 1 2
Ký tự * này có thể được kết hợp với một định nghĩa tùy chọn tham số để cho phép nhập từ không đến nhiều instance tham số:
'mail:send {user?*}'
Khi định nghĩa một tùy chọn yêu cầu nhiều giá trị input, mỗi giá trị tùy chọn đó được truyền đến command phải được đặt tên tùy chọn đó ở đằng trước:
'mail:send {--id=*}'
Một command như vậy có thể được gọi bằng cách truyền nhiều tham số --id:
php artisan mail:send --id=1 --id=2
Bạn có thể gán một mô tả cho các input đầu vào như tham số hoặc tùy chọn bằng cách tách tên tham số đó ra khỏi mô tả bằng dấu hai chấm. Nếu bạn cần thêm một chút chỗ trống để định nghĩa thêm cho lệnh của mình, hãy định nghĩa nó trên nhiều dòng:
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'mail:send
{user : The ID of the user}
{--queue : Whether the job should be queued}';
Nếu command của bạn chứa các tham số sẽ bắt buộc phải nhập, thì người dùng sẽ nhận được một thông báo lỗi khi chúng không được nhập. Ngoài ra, bạn có thể cấu hình command của bạn sẽ tự động nhắc người dùng khi các tham số bắt buộc bị nhập thiếu bằng cách implement interface PromptsForMissingInput:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\PromptsForMissingInput;
class SendEmails extends Command implements PromptsForMissingInput
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'mail:send {user}';
// ...
}
Nếu Laravel cần yêu cầu một tham số bắt buộc từ người dùng, nó sẽ tự động yêu cầu người dùng cung cấp tham số đó bằng cách hỏi một câu hỏi thông qua tên của tham số hoặc mô tả của nó. Nếu bạn muốn tùy chỉnh câu hỏi được sử dụng để yêu cầu tham số bắt buộc đó, bạn có thể implement phương thức promptForMissingArgumentsUsing, trả về một mảng các câu hỏi có khóa là tên các tham số:
/**
* Prompt for missing input arguments using the returned questions.
*
* @return array<string, string>
*/
protected function promptForMissingArgumentsUsing(): array
{
return [
'user' => 'Which user ID should receive the mail?',
];
}
Bạn cũng có thể cung cấp một text gợi ý bằng cách sử dụng một bộ dữ liệu chứa câu hỏi và text gợi ý:
return [
'user' => ['Which user ID should receive the mail?', 'E.g. 123'],
];
Nếu bạn muốn hoàn toàn kiểm soát câu hỏi và text gợi ý, bạn có thể cung cấp một closure để thực hiện việc đó và trả về câu trả lời của người dùng:
use App\Models\User;
use function Laravel\Prompts\search;
// ...
return [
'user' => fn () => search(
label: 'Search for a user:',
placeholder: 'E.g. Taylor Otwell',
options: fn ($value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: []
),
];
[!NOTE] Tài liệu Laravel Prompts đã có chứa thêm các thông tin thêm về các lời nhắc có sẵn và cách sử dụng chúng.
Nếu bạn muốn nhắc người dùng về chọn lựa hoặc nhập options, bạn có thể thêm lời nhắc vào trong phương thức handle của command. Tuy nhiên, nếu bạn chỉ muốn nhắc người dùng khi họ vừa bị nhắc về các tham số còn thiếu, thì bạn có thể implement phương thức afterPromptingForMissingArguments:
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use function Laravel\Prompts\confirm;
// ...
/**
* Perform actions after the user was prompted for missing arguments.
*/
protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void
{
$input->setOption('queue', confirm(
label: 'Would you like to queue the mail?',
default: $this->option('queue')
));
}
Trong khi lệnh của bạn đang thực thi, bạn có thể sẽ cần truy cập vào các giá trị của các tham số và các tùy chọn đã được khai báo trong lệnh của bạn. Để làm như vậy, bạn có thể sử dụng các phương thức argument và option. Nếu một tham số hoặc tùy chọn không tồn tại, thì giá trị null sẽ được trả về:
/**
* Execute the console command.
*/
public function handle(): void
{
$userId = $this->argument('user');
}
Nếu bạn cần lấy ra tất cả các tham số dưới dạng một array, hãy gọi phương thức arguments:
$arguments = $this->arguments();
Các tùy chọn có thể được lấy ra dễ dàng như các tham số bằng cách sử dụng phương thức option. Để lấy tất cả các tùy chọn dưới dạng một mảng, hãy gọi phương thức options:
// Retrieve a specific option...
$queueName = $this->option('queue');
// Retrieve all options as an array...
$options = $this->options();
[!NOTE] Laravel Prompts là một package PHP để thêm các form đẹp mắt và thân thiện với người dùng vào ứng dụng command-line của bạn, với các tính năng giống như trình duyệt như text gợi ý và validation.
Ngoài việc hiển thị output, bạn cũng có thể yêu cầu người dùng cung cấp thêm thông tin trong quá trình đang thực thi lệnh. Phương thức ask sẽ hỏi người dùng với một câu hỏi có sẵn, chấp nhận thông tin nhập thêm của người dùng và sau đó truyền lại thông tin mới nhập thêm đó cho lệnh của bạn:
/**
* Execute the console command.
*/
public function handle(): void
{
$name = $this->ask('What is your name?');
// ...
}
Phương thức ask cũng chấp nhận tham số thứ hai tùy chọn để chỉ định giá trị mặc định sẽ được trả về nếu không có dữ liệu đầu vào nào của người dùng được đưa vào:
$name = $this->ask('What is your name?', 'Taylor');
Phương thức secret tương tự như phương thức ask, nhưng đầu vào của người dùng sẽ không được hiển thị cho họ khi họ gõ vào console. Phương thức này hữu ích khi yêu cầu thông tin nhạy cảm như mật khẩu:
$password = $this->secret('What is the password?');
Nếu bạn cần yêu cầu người dùng xác nhận "yes hoặc no", bạn có thể sử dụng phương thức confirm. Mặc định, phương thức này sẽ trả về false. Tuy nhiên, nếu người dùng nhập y hoặc yes để trả lời confirm, thì phương thức sẽ trả về true.
if ($this->confirm('Do you wish to continue?')) {
// ...
}
Nếu cần thiết, bạn có thể chỉ định rằng mặc định confirm sẽ trả về giá trị true bằng cách truyền giá trị true làm tham số thứ hai cho phương thức confirm:
if ($this->confirm('Do you wish to continue?', true)) {
// ...
}
Phương thức anticipate có thể được sử dụng để cung cấp một auto-completion cho các lựa chọn. Người dùng vẫn có thể cung cấp bất kỳ câu trả lời nào, cho dù có gợi ý auto-completion:
$name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']);
Ngoài ra, bạn có thể truyền một closure làm tham số thứ hai cho phương thức anticipate. closure sẽ được gọi mỗi khi người dùng nhập một ký tự vào. closure phải chấp nhận một tham số string có chứa các ký tự nhập vào của người dùng và trả về một loạt các tùy chọn để tự động hoàn thành:
use App\Models\Address;
$name = $this->anticipate('What is your address?', function (string $input) {
return Address::whereLike('name', "{$input}%")
->limit(5)
->pluck('name')
->all();
});
Nếu bạn cần cung cấp cho người dùng một danh sách các lựa chọn khi hỏi một câu hỏi, thì bạn có thể sử dụng phương thức choice. Bạn có thể set giá trị mặc định cho phương thức này thông qua index của mảng, và nó sẽ được trả về nếu người dùng không chọn bất kỳ tùy chọn nào của bạn index này có thể được chỉ định qua tham số thứ ba:
$name = $this->choice(
'What is your name?',
['Taylor', 'Dayle'],
$defaultIndex
);
Ngoài ra, phương thức choice chấp nhận tham số thứ tư và tùy chọn thứ năm để xác định số lần thử tối đa và có cho phép chọn nhiều hay không:
$name = $this->choice(
'What is your name?',
['Taylor', 'Dayle'],
$defaultIndex,
$maxAttempts = null,
$allowMultipleSelections = false
);
Để gửi một output đến console, hãy sử dụng các phương thức line, newLine, info, comment, question, warn, alert, và error. Mỗi phương thức này sẽ sử dụng một màu ANSI thích hợp cho mục đích của chúng. Ví dụ: Để hiển thị một thông tin chung cho người dùng. Thì thông thường, phương thức info sẽ hiển thị trong console dưới dạng màu xanh lá cây:
/**
* Execute the console command.
*/
public function handle(): void
{
// ...
$this->info('The command was successful!');
}
Để hiển thị một thông báo lỗi, sử dụng phương thức error. Thông báo lỗi đó sẽ được hiển thị màu đỏ:
$this->error('Something went wrong!');
Bạn có thể sử dụng phương thức line để hiển thị đoạn text, không có màu:
$this->line('Display this on the screen');
Bạn có thể sử dụng phương thức newLine để hiển thị một dòng trống:
// Write a single blank line...
$this->newLine();
// Write three blank lines...
$this->newLine(3);
Phương thức table giúp bạn dễ dàng định dạng chính xác nhiều hàng / cột dữ liệu. Tất cả những gì bạn cần làm là cung cấp tên cột và dữ liệu cho bảng và Laravel sẽ tự động tính toán chiều rộng và chiều cao thích hợp cho bảng của bạn:
use App\Models\User;
$this->table(
['Name', 'Email'],
User::all(['name', 'email'])->toArray()
);
Đối với các tác vụ chạy dài, có thể bạn sẽ cần hiển thị một thanh tiến trình thông báo cho người dùng biết mức độ hoàn thành của tác vụ. Sử dụng phương thức withProgressBar, Laravel sẽ hiển thị một thanh tiến trình và tăng tiến trình đó thông qua mỗi lần lặp của một giá trị lặp nhất định:
use App\Models\User;
$users = $this->withProgressBar(User::all(), function (User $user) {
$this->performTask($user);
});
Thỉnh thoảng, bạn có thể cần kiểm soát nhiều hơn đối với cách tăng của thanh tiến trình. Đầu tiên, định nghĩa tổng số các bước mà tiến trình sẽ lặp. Sau đó, tăng thanh tiến trình sau khi xử lý xong từng bước:
$users = App\Models\User::all();
$bar = $this->output->createProgressBar(count($users));
$bar->start();
foreach ($users as $user) {
$this->performTask($user);
$bar->advance();
}
$bar->finish();
[!NOTE] Để biết các tùy chọn nâng cao, hãy xem tài liệu component Symfony Progress Bar.
Mặc định, Laravel sẽ tự động đăng ký tất cả các command có trong thư mục app/Console/Commands. Tuy nhiên, bạn có thể tùy chỉnh Laravel sẽ đọc các thư mục khác để tìm command Artisan bằng phương thức withCommands trong file bootstrap/app.php của ứng dụng của bạn:
->withCommands([
__DIR__.'/../app/Domain/Orders/Commands',
])
Nếu cần thiết, bạn cũng có thể đăng ký command theo cách thủ công bằng cách cung cấp tên class của command cho phương thức withCommands:
use App\Domain\Orders\Commands\SendEmails;
->withCommands([
SendEmails::class,
])
Khi Artisan được khởi động, tất cả các command có trong ứng dụng của bạn sẽ được resolve bởi service container và được đăng ký cùng với Artisan.
Thỉnh thoảng bạn có thể muốn chạy một command Artisan bên ngoài CLI. Ví dụ: bạn có thể chạy một command Artisan từ route hoặc controller. Bạn có thể sử dụng phương thức call trên facade Artisan để thực hiện điều này. Phương thức call chấp nhận tên một command hoặc tên một class làm tham số đầu tiên và một mảng các tham số của command đó làm tham số thứ hai. Exit code sẽ được trả về:
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Route;
Route::post('/user/{user}/mail', function (string $user) {
$exitCode = Artisan::call('mail:send', [
'user' => $user, '--queue' => 'default'
]);
// ...
});
Ngoài ra, bạn có thể truyền toàn bộ lệnh Artisan sang phương thức call dưới dạng một chuỗi:
Artisan::call('mail:send 1 --queue=default');
Nếu command của bạn định nghĩa một tùy chọn là một mảng, bạn có thể truyền một mảng các giá trị cho tùy chọn đó:
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Route;
Route::post('/mail', function () {
$exitCode = Artisan::call('mail:send', [
'--id' => [5, 13]
]);
});
Nếu bạn cần định nghĩa một giá trị cho một tùy chọn không nhận giá trị, chẳng hạn như một flag --force trong lệnh migrate:refresh, bạn có thể truyền true hoặc false:
$exitCode = Artisan::call('migrate:refresh', [
'--force' => true,
]);
Sử dụng phương thức queue trên facade Artisan, bạn thậm chí có thể queue các lệnh Artisan để chúng được xử lý trong background bởi queue worker của bạn. Trước khi sử dụng phương thức này, hãy đảm bảo là bạn đã cấu hình queue của bạn và đang chạy một queue listener:
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Route;
Route::post('/user/{user}/mail', function (string $user) {
Artisan::queue('mail:send', [
'user' => $user, '--queue' => 'default'
]);
// ...
});
Sử dụng phương thức onConnection và onQueue, bạn có thể chỉ định kết nối hoặc queue nào mà lệnh Artisan sẽ được gửi tới:
Artisan::queue('mail:send', [
'user' => 1, '--queue' => 'default'
])->onConnection('redis')->onQueue('commands');
Thỉnh thoảng bạn có thể muốn gọi các lệnh khác từ một lệnh Artisan hiện có. Bạn có thể làm như vậy bằng cách sử dụng phương thức call. Phương thức call này nhận vào tên của command và một mảng các tham số của command đó:
/**
* Execute the console command.
*/
public function handle(): void
{
$this->call('mail:send', [
'user' => 1, '--queue' => 'default'
]);
// ...
}
Nếu bạn muốn gọi một command khác và xoá đi tất cả các output của nó, bạn có thể sử dụng phương thức callSilent. Phương thức callSilent có cùng cách khai báo với phương thức call:
$this->callSilently('mail:send', [
'user' => 1, '--queue' => 'default'
]);
Như bạn có thể biết, hệ điều hành cho phép gửi tín hiệu đến các process đang chạy. Ví dụ: tín hiệu SIGTERM là cách hệ điều hành yêu cầu một chương trình kết thúc. Nếu bạn muốn listen các tín hiệu này trong lệnh Artisan console và chạy code khi chúng xảy ra, bạn có thể sử dụng phương thức trap:
/**
* Execute the console command.
*/
public function handle(): void
{
$this->trap(SIGTERM, fn () => $this->shouldKeepRunning = false);
while ($this->shouldKeepRunning) {
// ...
}
}
Để listen nhiều tín hiệu cùng một lúc, bạn có thể cung cấp một mảng tín hiệu cho phương thức trap:
$this->trap([SIGTERM, SIGQUIT], function (int $signal) {
$this->shouldKeepRunning = false;
dump($signal); // SIGTERM / SIGQUIT
});
Lệnh make của Artisan console sẽ được sử dụng để tạo nhiều class khác nhau, chẳng hạn như controller, job, migration và các bài test. Các class này được tạo ra bằng cách sử dụng các file "stub" được điền sẵn các giá trị dựa trên đầu vào mà bạn đưa vào. Tuy nhiên, thỉnh thoảng bạn có thể muốn thực hiện các thay đổi nhỏ đối với các file do Artisan tạo ra. Để thực hiện điều này, bạn có thể sử dụng lệnh stub:publish để export ra các stub cơ bản nhất để tùy chỉnh:
php artisan stub:publish
Các file stub đã được export sẽ nằm trong thư mục stubs trong thư mục gốc của ứng dụng của bạn. Bất kỳ thay đổi nào mà bạn thực hiện đối với các file stub này sẽ được phản ánh khi bạn tạo các class tương ứng khi sử dụng lệnh Artisan make.
Artisan gửi ba event khi chạy các lệnh: Illuminate\Console\Events\ArtisanStarting, Illuminate\Console\Events\CommandStarting, và Illuminate\Console\Events\CommandFinished. Event ArtisanStarting được gửi ngay lập tức khi Artisan bắt đầu chạy. Tiếp theo, event CommandStarting sẽ được gửi ngay trước khi lệnh được chạy. Cuối cùng, event CommandFinished sẽ được gửi sau khi một lệnh đã chạy xong.
entry