نسخه:

فرآیندها

معرفی

لاراول یک 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');