فرآیندها
معرفی
لاراول یک API گویا و حداقلی را در اطراف مؤلفه Symfony Process ارائه میکند که به شما امکان میدهد به راحتی فرآیندهای خارجی را از برنامه لاراول خود فراخوانی کنید. ویژگیهای فرآیند لاراول بر رایجترین موارد استفاده و یک تجربه توسعهدهنده فوقالعاده متمرکز است.
فراخوانی فرآیندها
برای فراخوانی یک فرآیند، میتوانید از روشهای
run
و
start
روشهای ارائهشده توسط
Process
نما استفاده کنید. متد
run
یک فرآیند را فراخوانی می کند و منتظر می ماند تا اجرای فرآیند به پایان برسد، در حالی که این
start
روش برای اجرای فرآیند ناهمزمان استفاده می شود. ما هر دو رویکرد را در این مستند بررسی خواهیم کرد. ابتدا، بیایید نحوه فراخوانی یک فرآیند پایه و همزمان و بررسی نتیجه آن را بررسی کنیم:
use Illuminate\Support\Facades\Process; $result = Process::run('ls -la'); return $result->output();
البته،
Illuminate\Contracts\Process\ProcessResult
نمونه ای که توسط
run
روش برگردانده می شود، انواع روش های مفیدی را ارائه می دهد که ممکن است برای بررسی نتیجه فرآیند استفاده شوند:
$result = Process::run('ls -la'); $result->successful();$result->failed();$result->exitCode();$result->output();$result->errorOutput();
پرتاب استثناها
اگر یک نتیجه فرآیند دارید و میخواهید نمونهای از
Illuminate\Process\Exceptions\ProcessFailedException
بزرگتر بودن کد خروج از صفر (بنابراین نشاندهنده شکست) بیابید، میتوانید از روش
throw
و استفاده کنید
throwIf
. اگر فرآیند شکست نخورد، نمونه نتیجه فرآیند برگردانده می شود:
$result = Process::run('ls -la')->throw(); $result = Process::run('ls -la')->throwIf($condition);
گزینه های فرآیند
البته، ممکن است لازم باشد قبل از فراخوانی یک فرآیند، رفتار آن را سفارشی کنید. خوشبختانه، لاراول به شما اجازه میدهد تا انواع ویژگیهای فرآیند، مانند دایرکتوری کاری، زمانبندی و متغیرهای محیطی را تغییر دهید.
مسیر دایرکتوری کاری
شما می توانید از این
path
روش برای تعیین دایرکتوری کاری فرآیند استفاده کنید. اگر این متد فراخوانی نشود، فرآیند دایرکتوری کاری اسکریپت PHP در حال اجرا را به ارث می برد:
$result = Process::path(__DIR__)->run('ls -la');
ورودی
می توانید ورودی را از طریق "ورودی استاندارد" فرآیند با استفاده از
input
روش زیر ارائه دهید:
$result = Process::input('Hello World')->run('cat');
تایم اوت ها
Illuminate\Process\Exceptions\ProcessTimedOutException
بهطور پیشفرض، فرآیندها پس از اجرای بیش از 60 ثانیه
نمونهای از آن را پرتاب میکنند .
با این حال، می توانید این رفتار را از طریق
timeout
روش سفارشی سازی کنید:
$result = Process::timeout(120)->run('bash import.sh');
یا اگر میخواهید زمان پایان فرآیند را به طور کامل غیرفعال کنید، میتوانید از
forever
روش استفاده کنید:
$result = Process::forever()->run('bash import.sh');
این
idleTimeout
روش ممکن است برای تعیین حداکثر ثانیه هایی که فرآیند ممکن است بدون بازگشت هیچ خروجی اجرا شود استفاده شود:
$result = Process::timeout(60)->idleTimeout(30)->run('bash import.sh');
متغیرهای محیطی
متغیرهای محیطی ممکن است از طریق روش به فرآیند ارائه شوند
env
. فرآیند فراخوانی شده همچنین تمام متغیرهای محیطی تعریف شده توسط سیستم شما را به ارث می برد:
$result = Process::forever() ->env(['IMPORT_PATH' => __DIR__]) ->run('bash import.sh');
اگر می خواهید یک متغیر محیطی ارثی را از فرآیند فراخوانی حذف کنید، می توانید آن متغیر محیطی را با مقدار زیر ارائه دهید
false
:
$result = Process::forever() ->env(['LOAD_PATH' => false]) ->run('bash import.sh');
حالت TTY
این
tty
روش ممکن است برای فعال کردن حالت TTY برای فرآیند شما استفاده شود. حالت TTY ورودی و خروجی فرآیند را به ورودی و خروجی برنامه شما متصل می کند و به فرآیند شما امکان می دهد ویرایشگری مانند Vim یا Nano را به عنوان یک فرآیند باز کند:
Process::forever()->tty()->run('vim');
خروجی فرآیند
همانطور که قبلاً بحث شد، خروجی فرآیند ممکن است با استفاده از روش های
output
(stdout) و
errorOutput
(stderr) در نتیجه فرآیند قابل دسترسی باشد:
use Illuminate\Support\Facades\Process; $result = Process::run('ls -la'); echo $result->output();echo $result->errorOutput();
با این حال، خروجی ممکن است در زمان واقعی با ارسال یک بسته به عنوان آرگومان دوم به
run
روش جمع آوری شود. بسته شدن دو آرگومان دریافت خواهد کرد: "نوع" خروجی (
stdout
یا
stderr
) و خود رشته خروجی:
$result = Process::run('ls -la', function (string $type, string $output) { echo $output;});
لاراول همچنین متدهای
seeInOutput
و را ارائه می دهد
seeInErrorOutput
که روشی مناسب برای تعیین اینکه آیا یک رشته داده شده در خروجی فرآیند وجود دارد یا خیر، ارائه می دهد:
if (Process::run('ls -la')->seeInOutput('laravel')) { // ...}
غیرفعال کردن خروجی فرآیند
اگر فرآیند شما مقدار قابل توجهی از خروجی را می نویسد که به آن علاقه ای ندارید، می توانید با غیرفعال کردن کامل بازیابی خروجی، حافظه را ذخیره کنید. برای انجام این کار،
quietly
در حین ساخت فرآیند، متد را فراخوانی کنید:
use Illuminate\Support\Facades\Process; $result = Process::quietly()->run('bash import.sh');
خطوط لوله
گاهی اوقات ممکن است بخواهید خروجی یک فرآیند را به ورودی یک فرآیند دیگر تبدیل کنید. این اغلب به عنوان "لوله کشی" خروجی یک فرآیند به فرآیند دیگر شناخته می شود. روش
pipe
ارائه شده توسط
Process
نماها انجام این کار را آسان می کند. این
pipe
روش فرآیندهای لوله شده را به صورت همزمان اجرا می کند و نتیجه فرآیند را برای آخرین فرآیند در خط لوله برمی گرداند:
use Illuminate\Process\Pipe;use Illuminate\Support\Facades\Process; $result = Process::pipe(function (Pipe $pipe) { $pipe->command('cat example.txt'); $pipe->command('grep -i "laravel"');}); if ($result->successful()) { // ...}
اگر نیازی به سفارشی کردن فرآیندهای جداگانه ای که خط لوله را تشکیل می دهند ندارید، می توانید به سادگی یک آرایه از رشته های فرمان را به متد ارسال کنید
pipe
:
$result = Process::pipe([ 'cat example.txt', 'grep -i "laravel"',]);
خروجی فرآیند ممکن است در زمان واقعی با ارسال یک بسته به عنوان آرگومان دوم به
pipe
روش جمع آوری شود. بسته شدن دو آرگومان دریافت خواهد کرد: "نوع" خروجی (
stdout
یا
stderr
) و خود رشته خروجی:
$result = Process::pipe(function (Pipe $pipe) { $pipe->command('cat example.txt'); $pipe->command('grep -i "laravel"');}, function (string $type, string $output) { echo $output;});
لاراول همچنین به شما این امکان را می دهد که از طریق متد، کلیدهای رشته ای را به هر فرآیند در یک خط لوله اختصاص دهید
as
. این کلید همچنین به بسته شدن خروجی ارائه شده برای
pipe
متد ارسال می شود و به شما امکان می دهد تعیین کنید که خروجی متعلق به کدام فرآیند است:
$result = Process::pipe(function (Pipe $pipe) { $pipe->as('first')->command('cat example.txt'); $pipe->as('second')->command('grep -i "laravel"');})->start(function (string $type, string $output, string $key) { // ...});
فرآیندهای ناهمزمان
در حالی که این
run
روش فرآیندها را به صورت همزمان فراخوانی می کند، این
start
روش ممکن است برای فراخوانی یک فرآیند به صورت ناهمزمان استفاده شود. این به برنامه شما اجازه میدهد تا زمانی که فرآیند در پسزمینه اجرا میشود، به انجام کارهای دیگر ادامه دهد. هنگامی که فرآیند فراخوانی شد، می توانید از
running
روش برای تعیین اینکه آیا فرآیند هنوز در حال اجرا است استفاده کنید:
$process = Process::timeout(120)->start('bash import.sh'); while ($process->running()) { // ...} $result = $process->wait();
همانطور که ممکن است متوجه شده باشید، ممکن است
wait
متد را فراخوانی کنید تا منتظر بمانید تا اجرای فرآیند به پایان برسد و نمونه نتیجه فرآیند را بازیابی کنید:
$process = Process::timeout(120)->start('bash import.sh'); // ... $result = $process->wait();
شناسه ها و سیگنال های فرآیند
این
id
روش ممکن است برای بازیابی شناسه فرآیند اختصاص داده شده به سیستم عامل از فرآیند در حال اجرا استفاده شود:
$process = Process::start('bash import.sh'); return $process->id();
می توانید از این
signal
روش برای ارسال "سیگنال" به فرآیند در حال اجرا استفاده کنید. لیستی از ثابت های سیگنال از پیش تعریف شده را می توان در
اسناد PHP
یافت :
$process->signal(SIGUSR2);
خروجی فرآیند ناهمزمان
در حالی که یک فرآیند ناهمزمان در حال اجرا است، می توانید با استفاده از روش
output
و به کل خروجی فعلی آن دسترسی داشته باشید
errorOutput
. با این حال، می توانید از
latestOutput
و
latestErrorOutput
برای دسترسی به خروجی فرآیندی که از آخرین بازیابی خروجی رخ داده است استفاده کنید:
$process = Process::timeout(120)->start('bash import.sh'); while ($process->running()) { echo $process->latestOutput(); echo $process->latestErrorOutput(); sleep(1);}
مانند
run
روش، خروجی نیز ممکن است در زمان واقعی از فرآیندهای ناهمزمان با ارسال یک بسته به عنوان آرگومان دوم به
start
روش جمع آوری شود. بسته شدن دو آرگومان دریافت خواهد کرد: "نوع" خروجی (
stdout
یا
stderr
) و خود رشته خروجی:
$process = Process::start('bash import.sh', function (string $type, string $output) { echo $output;}); $result = $process->wait();
فرآیندهای همزمان
لاراول همچنین مدیریت مجموعه ای از فرآیندهای همزمان و ناهمزمان را آسان می کند و به شما این امکان را می دهد که به راحتی بسیاری از وظایف را به طور همزمان انجام دهید. برای شروع،
pool
متد را فراخوانی کنید، که بسته شدنی را میپذیرد که نمونهای از
Illuminate\Process\Pool
.
در این بسته شدن، میتوانید فرآیندهایی را که به استخر تعلق دارند، تعریف کنید. هنگامی که یک مجموعه فرآیند از طریق متد شروع می شود
start
، می توانید از طریق متد به
مجموعه
فرآیندهای در حال اجرا دسترسی داشته باشید
running
:
use Illuminate\Process\Pool;use Illuminate\Support\Facades\Process; $pool = Process::pool(function (Pool $pool) { $pool->path(__DIR__)->command('bash import-1.sh'); $pool->path(__DIR__)->command('bash import-2.sh'); $pool->path(__DIR__)->command('bash import-3.sh');})->start(function (string $type, string $output, int $key) { // ...}); while ($pool->running()->isNotEmpty()) { // ...} $results = $pool->wait();
همانطور که می بینید، ممکن است منتظر بمانید تا اجرای تمام فرآیندهای pool به پایان برسد و نتایج آنها از طریق
wait
متد حل شود. این
wait
متد یک شی قابل دسترسی به آرایه را برمی گرداند که به شما امکان می دهد با کلید آن به نمونه نتیجه فرآیند هر فرآیند در استخر دسترسی داشته باشید:
$results = $pool->wait(); echo $results[0]->output();
یا، برای راحتی،
concurrently
ممکن است از این روش برای شروع یک مجموعه فرآیند ناهمزمان و بلافاصله منتظر نتایج آن استفاده شود. هنگامی که با قابلیتهای تخریب آرایه PHP ترکیب میشود، این میتواند نحو بیانی خاصی ارائه دهد:
[$first, $second, $third] = Process::concurrently(function (Pool $pool) { $pool->path(__DIR__)->command('ls -la'); $pool->path(app_path())->command('ls -la'); $pool->path(storage_path())->command('ls -la');}); echo $first->output();
فرآیندهای نامگذاری استخر
دسترسی به نتایج مجموعه فرآیند از طریق یک کلید عددی چندان گویا نیست. بنابراین، لاراول به شما این امکان را میدهد که از طریق متد، کلیدهای رشتهای را به هر فرآیند در یک Pool اختصاص دهید
as
. این کلید همچنین به بسته شدن ارائه شده برای متد ارسال می شود
start
و به شما امکان می دهد تعیین کنید که خروجی متعلق به کدام فرآیند است:
$pool = Process::pool(function (Pool $pool) { $pool->as('first')->command('bash import-1.sh'); $pool->as('second')->command('bash import-2.sh'); $pool->as('third')->command('bash import-3.sh');})->start(function (string $type, string $output, string $key) { // ...}); $results = $pool->wait(); return $results['first']->output();
شناسهها و سیگنالهای فرآیند استخر
از آنجایی که متد Process Pool
running
مجموعهای از تمام فرآیندهای فراخوانی شده در استخر را فراهم میکند، میتوانید به راحتی به شناسههای فرآیند استخر زیربنایی دسترسی داشته باشید:
$processIds = $pool->running()->each->id();
و برای راحتی، میتوانید
signal
روشی را در یک فرآیند پردازش برای ارسال سیگنال به هر فرآیند درون استخر فراخوانی کنید:
$pool->signal(SIGUSR2);
آزمایش کردن
بسیاری از سرویسهای لاراول عملکردی را ارائه میکنند که به شما کمک میکند تا به آسانی و واضح تستها را بنویسید، و سرویس پردازش لاراول نیز از این قاعده مستثنی نیست. روش
Process
نما
fake
به شما این امکان را می دهد که به لاراول دستور دهید در هنگام فراخوانی فرآیندها، نتایج stubbed/dummy را برگرداند.
جعل فرآیندها
برای کشف توانایی لاراول در جعل فرآیندها، بیایید مسیری را تصور کنیم که یک فرآیند را فراخوانی می کند:
use Illuminate\Support\Facades\Process;use Illuminate\Support\Facades\Route; Route::get('/import', function () { Process::run('bash import.sh'); return 'Import complete!';});
هنگام آزمایش این مسیر، میتوانیم به لاراول دستور دهیم تا با فراخوانی متد
fake
در
Process
نما بدون هیچ آرگومان، یک نتیجه فرآیند جعلی و موفق را برای هر فرآیند فراخوانی شده برگرداند. علاوه بر این، ما حتی می توانیم
ادعا کنیم
که یک فرآیند داده شده "اجرا شده است":
<?php use Illuminate\Process\PendingProcess;use Illuminate\Contracts\Process\ProcessResult;use Illuminate\Support\Facades\Process; test('process is invoked', function () { Process::fake(); $response = $this->get('/import'); // Simple process assertion... Process::assertRan('bash import.sh'); // Or, inspecting the process configuration... Process::assertRan(function (PendingProcess $process, ProcessResult $result) { return $process->command === 'bash import.sh' && $process->timeout === 60; });});
<?php namespace Tests\Feature; use Illuminate\Process\PendingProcess;use Illuminate\Contracts\Process\ProcessResult;use Illuminate\Support\Facades\Process;use Tests\TestCase; class ExampleTest extends TestCase{ public function test_process_is_invoked(): void { Process::fake(); $response = $this->get('/import'); // Simple process assertion... Process::assertRan('bash import.sh'); // Or, inspecting the process configuration... Process::assertRan(function (PendingProcess $process, ProcessResult $result) { return $process->command === 'bash import.sh' && $process->timeout === 60; }); }}
همانطور که بحث شد، فراخوانی
fake
روش در
Process
نما به لاراول دستور می دهد که همیشه یک نتیجه فرآیند موفق را بدون خروجی برگرداند. با این حال، می توانید به راحتی کد خروجی و خروجی فرآیندهای جعلی را با استفاده از روش
Process
نما مشخص کنید
result
:
Process::fake([ '*' => Process::result( output: 'Test output', errorOutput: 'Test error output', exitCode: 1, ),]);
جعل فرآیندهای خاص
همانطور که ممکن است در مثال قبلی متوجه شده باشید،
Process
نما به شما اجازه می دهد تا با ارسال یک آرایه به روش، نتایج جعلی مختلفی را در هر فرآیند مشخص کنید
fake
.
کلیدهای آرایه باید الگوهای دستوری را که می خواهید جعل کنید و نتایج مرتبط با آنها را نشان دهند. این
*
کاراکتر ممکن است به عنوان یک کاراکتر عام استفاده شود. هر دستور پردازشی که جعلی نشده باشد در واقع فراخوانی می شود. می توانید از روش
Process
نما
result
برای ساختن نتایج خرد / جعلی برای این دستورات استفاده کنید:
Process::fake([ 'cat *' => Process::result( output: 'Test "cat" output', ), 'ls *' => Process::result( output: 'Test "ls" output', ),]);
اگر نیازی به سفارشی کردن کد خروج یا خروجی خطای یک فرآیند جعلی ندارید، ممکن است برای شما راحتتر باشد که نتایج جعلی را به صورت رشتههای ساده مشخص کنید:
Process::fake([ 'cat *' => 'Test "cat" output', 'ls *' => 'Test "ls" output',]);
جعل توالی فرآیند
اگر کدی که آزمایش میکنید چندین فرآیند را با یک فرمان فراخوانی میکند، ممکن است بخواهید یک نتیجه فرآیند جعلی متفاوت را به هر فراخوانی فرآیند اختصاص دهید. شما می توانید این کار را از طریق روش
Process
نما انجام دهید
sequence
:
Process::fake([ 'ls *' => Process::sequence() ->push(Process::result('First invocation')) ->push(Process::result('Second invocation')),]);
جعل چرخه حیات فرآیندهای ناهمزمان
تا اینجا، ما در درجه اول فرآیندهای جعلی را که به طور همزمان با استفاده از
run
روش فراخوانی می شوند، مورد بحث قرار داده ایم. با این حال، اگر میخواهید کدی را آزمایش کنید که با فرآیندهای ناهمزمان فراخوانی شده از طریق تعامل دارد
start
، ممکن است به رویکرد پیچیدهتری برای توصیف فرآیندهای جعلی خود نیاز داشته باشید.
برای مثال، بیایید مسیر زیر را تصور کنیم که با یک فرآیند ناهمزمان تعامل دارد:
use Illuminate\Support\Facades\Log;use Illuminate\Support\Facades\Route; Route::get('/import', function () { $process = Process::start('bash import.sh'); while ($process->running()) { Log::info($process->latestOutput()); Log::info($process->latestErrorOutput()); } return 'Done';});
برای جعل صحیح این فرآیند، باید بتوانیم توضیح دهیم که
running
متد چند بار باید برگردد
true
. علاوه بر این، ممکن است بخواهیم چندین خط خروجی را مشخص کنیم که باید به ترتیب برگردانده شوند. برای انجام این کار می توانیم از روش
Process
نما استفاده کنیم
describe
:
Process::fake([ 'bash import.sh' => Process::describe() ->output('First line of standard output') ->errorOutput('First line of error output') ->output('Second line of standard output') ->exitCode(0) ->iterations(3),]);
بیایید به مثال بالا بپردازیم. با استفاده از متدهای
output
و
errorOutput
، ممکن است چندین خط خروجی را مشخص کنیم که به ترتیب برگردانده می شوند. این
exitCode
روش ممکن است برای تعیین کد خروج نهایی فرآیند جعلی استفاده شود. در نهایت، این
iterations
متد ممکن است برای تعیین اینکه متد چند بار
running
باید برگردد استفاده شود
true
.
ادعاهای موجود
همانطور که قبلاً بحث شد ، لاراول چندین ادعای فرآیند را برای آزمایش ویژگی های شما ارائه می دهد. در زیر به هر یک از این ادعاها خواهیم پرداخت.
assertRan
ادعا کنید که یک فرآیند معین فراخوانی شده است:
use Illuminate\Support\Facades\Process; Process::assertRan('ls -la');
این
assertRan
روش همچنین بسته شدن را میپذیرد، که نمونهای از یک فرآیند و نتیجه فرآیند را دریافت میکند و به شما امکان میدهد گزینههای پیکربندیشده فرآیند را بررسی کنید. اگر این بسته شدن برگردد
true
، ادعا "گذر" خواهد کرد:
Process::assertRan(fn ($process, $result) => $process->command === 'ls -la' && $process->path === __DIR__ && $process->timeout === 60);
عبور
$process
به
assertRan
بسته شدن یک نمونه از است
Illuminate\Process\PendingProcess
، در حالی که
$result
یک نمونه از است
Illuminate\Contracts\Process\ProcessResult
.
assertDidntRun
ادعا کنید که فرآیند معینی فراخوانی نشده است:
use Illuminate\Support\Facades\Process; Process::assertDidntRun('ls -la');
مانند
assertRan
روش،
assertDidntRun
متد نیز بسته شدن را میپذیرد که نمونهای از یک فرآیند و نتیجه فرآیند را دریافت میکند و به شما امکان میدهد گزینههای پیکربندیشده فرآیند را بررسی کنید. اگر این بسته شدن برگردد
true
، ادعا "شکست میخورد":
Process::assertDidntRun(fn (PendingProcess $process, ProcessResult $result) => $process->command === 'ls -la');
assertRanTimes
ادعا کنید که یک فرآیند معین چندین بار فراخوانی شده است:
use Illuminate\Support\Facades\Process; Process::assertRanTimes('ls -la', times: 3);
این
assertRanTimes
روش همچنین بسته شدن را میپذیرد، که نمونهای از یک فرآیند و نتیجه فرآیند را دریافت میکند و به شما امکان میدهد گزینههای پیکربندیشده فرآیند را بررسی کنید. اگر این بسته شدن برگردد
true
و فرآیند به تعداد مشخصی بارها فراخوانی شده باشد، ادعا "گذر" خواهد کرد:
Process::assertRanTimes(function (PendingProcess $process, ProcessResult $result) { return $process->command === 'ls -la';}, times: 3);
جلوگیری از فرآیندهای سرگردان
اگر میخواهید مطمئن شوید که تمام فرآیندهای فراخوانی شده در طول آزمایش فردی یا مجموعه آزمایشی کامل شما جعلی شدهاند، میتوانید
preventStrayProcesses
روش را فراخوانی کنید. پس از فراخوانی این روش، هر فرآیندی که نتیجه جعلی مربوطه ندارد، به جای شروع یک فرآیند واقعی، یک استثنا ایجاد می کند:
use Illuminate\Support\Facades\Process; Process::preventStrayProcesses(); Process::fake([ 'ls *' => 'Test output...',]); // Fake response is returned...Process::run('ls -la'); // An exception is thrown...Process::run('bash import.sh');