لاراول 10 و مهم‌ترین ویژگی‌های آن

What’s New in Laravel 10: A Deep Dive Into the Latest Updates and Features

01 مرداد 1402
Whats-new-in-laravel-10-min-1024x596

لاراول 10 منتشر شده است و شامل به‌روزرسانی‌ها و امکانات جذاب بسیاری است که علاقه‌مندان لاراول را شگفت‌زده خواهد کرد. این نسخه نیز مانند نسخه‌های قبلی، ویژگی‌ها و قابلیت‌های جدیدی را معرفی کرده است. در این مقاله قصد داریم شما را با مهم‌ترین به‌روزرسانی‌ها و امکانات جدید لاراول 10 آشنا کنیم. پس با ما همراه باشید.

زمان‌بندی انتشار نسخه‌های لاراول

قبلاً، لاراول در هر شش ماه یکبار نسخه‌های اصلی خود را منتشر می‌کرد، اما با لاراول ۹، تیم توسعه‌دهنده لاراول تمایل پیدا کرد که سالانه نسخه‌های جدید منتشر کند. با این وجود، تاریخ انتشار لاراول 10 در ۱۴ فوریه ۲۰۲۳ بود و این نسخه به‌روزرسانی‌های جدیدی را به همراه داشت.

لاراول 10 همانند سایر نسخه‌های جدید، دو سند رسمی را برای کمک به به‌روزرسانی ارائه کرده است:

۱) راهنمای به‌روزرسانی - این راهنما برای کاربرانی که قصد به‌روزرسانی از لاراول ۹ یا نسخه‌های قدیمی‌تر را دارند، فراهم شده و یک راهنمای ساده و کوتاه برای آپدیت فراهم می‌کند.

دو تغییر مهم در این راهنما، به‌روزرسانی وابستگی‌ها و حداقل نیازمندی‌های سیستمی است که الزام به PHP ۸.۱+ و Composer ۲.۲+ دارد. همچنین باید تنظیمات را برای "minimum-stability" بر روی "stable" قرار دهید. سایر تغییرات تأثیر متوسط، کم یا اختیاری دارند.

۲) یادداشت‌های انتشار - این یادداشت‌ها حاوی به‌روزرسانی‌ها و ویژگی‌های جدید لاراول 10 نسبت به نسخه‌های قدیمی‌تر می‌باشد.

ویژگی‌ها و به‌روزرسانی‌های لاراول 10

حمایت از نسخه‌های PHP

شما نمی‌توانید لاراول 10 را با نسخه‌های PHP ۸.۰ یا قدیمی‌تر اجرا کنید. لاراول 10 تنها نسخه‌های PHP ۸.۱ و جدیدتر را پشتیبانی می‌کند، بنابراین با آخرین نسخه PHP ۸.۲ نیز سازگار است. همچنین اگر از لاراول ۹ استفاده می‌کنید، PHP ۸.۲ همچنان یک انتخاب مناسب برای پروژه شماست.

Native Type Declarations

لاراول 10 ساختار برنامه و تمام کلاس‌های مورد استفاده stubs را به‌روزرسانی کرده تا انواع آرگومان‌ها و مقادیر بازگشتی در تمام توابع مشخص شود. همچنین اطلاعات "DOC-TYPE" حذف شده‌اند. به مثال زیر توجه کنید:

لاراول ۹:

/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param  \Illuminate\Http\Request  $request
* @return string|null
*/
protected function redirectTo($request)
{
   if (! $request->expectsJson()) {
       return route('login');
   }
}

و در لاراول 10:

/**
* Get the path the user should be redirected to when they are not authenticated.
*/
protected function redirectTo(Request $request): ?string
{
   return $request->expectsJson() ? null : route('login');
}

با توجه به مثال‌های ارائه شده، مشاهده می‌کنیم که در نسخه جدید، انواع پارامتر و مقدار بازگشتی به تمام متدها اضافه شده‌اند. این کار باعث افزایش خوانایی، درک بهتر و جلوگیری از خطاها می‌شود. همچنین پیشنهاد می‌شود در نوشتن روش‌های خودتان نیز از این ویژگی‌ها استفاده کنید.

طراح لاراول (nunomaduro) با ارائه یک درخواست ادغام جامع، اعلام نوع پارامترها، مقادیر بازگشتی و توضیحات را در تمامی فایل‌ها و مخازن مربوط به لاراول به‌روزرسانی کرد که این کار بسیار ارزشمند و مهم تلقی می‌شود.

Facade جدید Process در لاراول 10

فاساد جدید Process به ما اجازه می‌دهد تا هر فرایند خارجی مانند فراخوانی اسکریپت‌های خط فرمان را اجرا کنیم. همانطور که فاساد HTTP کار با APIها را آسان‌تر می‌کند، فاساد Process هم کار با تست و اجرای فرایندهای CLI را ساده خواهد کرد.

ساده‌ترین روش استفاده از این ویژگی:

use Illuminate\Support\Facades\Process;

$result = Process::run('ls -la');
$result->successful(); // اجرای موفقیت آمیز فرایند را بررسی می‌کند
$result->failed(); // شکست فرایند را بررسی می‌کند
$result->exitCode(); // خروجی کد فرایند را برمی‌گرداند
$result->output(); // خروجی استاندارد فرایند را برمی‌گرداند
$result->errorOutput(); // خروجی خطای فرایند را برمی‌گرداند
$result->throw(); // اگر فرایند شکست خورده، استثنا می‌اندازد
$result->throwIf(condition); // اگر شرط برقرار باشد و فرایند شکست خورده باشد، استثنا می‌اندازد

به عنوان مثال، می‌توانیم دستور pwd را اجرا کنیم و دایرکتوری جاری را چاپ کنیم:

$result = Process::run('pwd');
return $result->output();

اگر خروجی را بررسی کنیم مسیر فعلی را می‌بینیم: /pathtoproject/projectname/public

اگر دستوری که وجود ندارد را اجرا کنیم:

$result = Process::run('ll');
return $result->errorOutput();

خطای زیر را مشاهده می‌کنیم: sh: ll: command not found

لایه Process شامل ویژگی‌های زیادی از جمله:

  • مدیریت خروجی فرایند به محض دریافت
  • فرایندهای غیرهمزمان
  • Process Pools
  • ویژگی‌های غنی تست از طریق fake()
  • جلوگیری از فرایندهای ناخواسته در حین تست

اگر نیاز به اجرای فرایندهای طولانی مدت مانند npm run build داشته باشیم، می‌توانیم آن‌ها را پایش کنیم و وضعیت اجرا را بررسی نماییم.

همچنین روش fake() برای شبیه‌سازی فرایندها در تست‌ها موجود است. به طور مثال اجرای دستور زیر چند ثانیه طول می‌کشد:

\Illuminate\Support\Facades\Process::run('npm run build')->output();

اما با کد زیر بلافاصله اجرا می‌شود:

\Illuminate\Support\Facades\Process::fake();
$this->info(\Illuminate\Support\Facades\Process::run('npm run build')->output());

به طور خلاصه، Facad جدید Process به ما این امکان را می‌دهد تا هر دستور CLI مورد نیاز را برنامه‌ای از فایل PHP فراخوانی کنیم.

پکیج جدید Laravel Pennant

Laravel Pennant یک First Party Package است که توسط Tim McDonald از تیم اصلی لاراول نگهداری و توسعه داده می‌شود. این بسته چالش مدیریت feature flags در پروژه‌هایی که به‌طور مکرر به‌روزرسانی می‌شوند را ساده می‌کند. این بسته یک راهکار ساده‌ کاربردی شامل درایور آرایه حافظه‌ای و دیتابیس ارائه می‌دهد.

برای شروع کافی است:

  1. بسته را نصب کنید
  2. فایل پیکربندی را منتشر کنید
  3. مهاجرت‌ها را اجرا کنید

پس از اجرای Migration ها، جدول جدیدی به نام features به دیتابیس اضافه می‌شود. Pennant می‌تواند از آرایه حافظه‌ای یا دیتابیس برای حل feature flags استفاده کند که پیش‌فرض دیتابیس است.

پرچم ویژگی یا Feature flags چیست؟ پرچم‌های ویژگی لاراول یا Laravel Feature flags به تست سبک‌ها، صفحات یا قابلیت‌های جدید که فقط برای گروه‌های خاصی از کاربران مانند کارمندان یا مدیران قابل مشاهده است، کمک می‌کند. در واقع آن‌ها امکان فعال‌سازی انتخابی قابلیت‌ها در زمان اجرا بدون ایجاد تغییر در کد را فراهم می‌کنند.

برای تعریف یک ویژگی، از روش define روی فاساد Feature استفاده کنید. نام ویژگی و کلوژر مقدار اولیه را مشخص کنید. ویژگی‌ها باید در یک سرویس پروایدر مثل AppServiceProvider تعریف شوند:

public function boot(): void
{
   Feature::define('new-dashboard-text, function () {
       return true;
   });
}

اینجا ما ویژگی جدید به نام “new-dashboard-text” را تعریف کردیم. اگر مقدار true را از کلوژر برگردانیم، به این معنی است که همه به این ویژگی دسترسی دارند. اگر نیاز باشد این ویژگی را فقط برای برخی افراد مثلا کارمندان و مدیران فعال کنیم، می‌توانیم این‌گونه تعریفش کنیم:

Feature::define('new-dashboard-text', fn (User $user) => $user->isAdmin() || $user->isEmployee());

در ‌Blade می‌توانیم از دیرکتیو @feature برای مشخص کردن بخشی از کد که محدود به ویژگی است استفاده کنیم:

<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
    @feature('new-dashboard-text')
    <!-- 'new-style' is active -->
    <div class="p-6 text-gray-500">
        {{ __("Welcome to the page!") }}
    </div>
    @else
    <!-- 'new-style' is inactive -->
    <div class="p-6 text-gray-900">
        {{ __("You're logged in!") }}
    </div>
    @endfeature
</div>

اگر با کاربر مدیر یا کارمند وارد شویم، "Welcome to the page!" را می‌بینیم و بقیه کاربران "You're logged in!" را مشاهده خواهند کرد. اما این چطور کار می‌کند؟ ابتدا باید به جدول features نگاهی بیندازیم که به این شکل است:

Feature Flag in laravel

اینجا می‌بینیم کاربر با شناسه 1 که مدیر است، مقدار true دارد. یعنی این کاربر به این ویژگی دسترسی دارد. کاربر دیگر با شناسه 2 که کارمند است هم به این ویژگی دسترسی دارد. اگر با کاربری که نه مدیر است و نه کارمند، وارد شوم، رکورد جدیدی به جدول اضافه می‌شود:

حال اگر کاربر 22 کارمند شد و نیاز به دسترسی به این ویژگی داشت، اما رکوردش در دیتابیس مقدار false داشت، با ورود او به‌روزرسانی نمی‌شد. به جای آن باید:

  1. رکورد موجود را دستی از جدول حذف کنیم یا
  2. با کد زیر ویژگی را برای این کاربر فعال کنیم:
\Laravel\Pennant\Feature::activate('new-dashboard-text');

پس از بازدید مجدد از صفحه داشبورد، متن جدید نمایش داده می‌شود و رکورد دیتابیس هم به‌روزرسانی می‌شود.

همچنین می‌توانیم با شرط زیر بررسی کنیم آیا ویژگی برای کاربر جاری فعال است یا خیر:

if (Feature::active('new-dashboard-text')) {
   return to_route('dashboard');
}

خلاصه اینکه الان یک بسته خوب ساخته شده و تست شده با قابلیت‌های عالی داریم. در ادامه به صورت خلاصه و تیتر وار ویژگی های لاراول Feature flags رو می‌نویسم:

  • مدیریت و کنترل پرچم‌های ویژگی (Feature Flags) در پروژه‌های لاراول - امکان فعال و غیرفعال کردن ویژگی‌های جدید برای گروه‌های مختلف کاربران
  • آزمون ویژگی‌ها و قابلیت‌های جدید قبل از انتشار نهایی آن‌ها برای همه کاربران
  • انتشار تدریجی ویژگی‌های جدید برای دسته‌های مختلف کاربران
  • امکان بازگشت ویژگی‌ها در صورت بروز مشکل در مراحل آزمون
  • ساده‌سازی فرایند توسعه ویژگی‌های جدید با امکان آزمون و انتشار تدریجی
  • کاهش ریسک انتشار ویژگی‌های ناقص یا با باگ
  • تسهیل مدیریت نسخه‌ها و ویژگی‌ها در پروژه‌های بزرگ و پیچیده

گزینهٔ Profile برای تست‌ها

دستور artisan test یک گزینهٔ جدید به نام profile دارد که به ما کمک می‌کند تست‌های کندتر برنامه را پیدا کرده و آن‌ها را بهبود دهیم.

برای مثال اگر داشته باشیم:

test('sleep for 3 seconds', function () {
   sleep(3);
});

اگر php artisan test –profile را اجرا کنیم، می‌توانیم شناسایی کنیم کدام تست‌ها زمان بیشتری برای اجرا گرفته‌اند و به این ترتیب کندترین‌ها را پیدا کنیم.

Generator CLI prompts

پس از انتشار لاراول 10، دستورات build-in نیازی به ورودی اولیه ندارند. وقتی این دستورات را بدون ورودی صدا می‌زنیم، برای استدلال‌های مورد نیاز مانند زیر مورد سوال قرار می‌گیریم:

➜ php artisan make:model
  What should the model be named?

❯ Post

  Would you like any of the following? [none]

  none …… 0  
  all ……… 1  
  factory ………… 2  
  form requests …………… 3  
  migration ………… 4  
  policy …………… 5  
  resource controller …………… 6
  seed ………… 7  

❯ 2,3,4

   INFO  Model [app/Models/Post.php] created successfully.  
   INFO  Factory [database/factories/PostFactory.php] was created successfully.  
   INFO  Migration [database/migrations/2023_03_27_151438_create_posts_table.php] was created successfully.

به این ترتیب دیگر نیازی به مشخص کردن تمام پارامترها در خط فرمان نیست و کاربر می‌تواند با راحتی گزینه‌های مورد نیاز را انتخاب کند.

روش جدید کمکی گذرواژه در کلاس String

روش Str::password می‌تواند یک گذرواژه تصادفی و امن با طول مشخص تولید کند. این گذرواژه شامل ترکیبی از حروف، اعداد، نمادها و فاصله خواهد بود. به طور پیش‌فرض طول گذرواژه 32 کاراکتر است و شامل حروف، اعداد و نمادها می‌شود. می‌توانیم دلخواه با یا بدون حروف، اعداد و نمادها تولید کنیم. ب

نحوه تعریف این متد به صورت زیر هست:

public static function password($length = 32, $letters = true, $numbers = true, $symbols = true, $spaces = false)

حال به این مثال توجه کنید:

> Str::password(10)
= "L>e~8Ns9;!"

> Str::password(letters: false)  
= "{/\\18{\]69~\_>:)%4//%61\\9-%.-{~%|&"

> Str::password(numbers: false)
= "OomXSZUnWA,jWTgise%>hcEsQnB,D.\\!"

به جای کلاس Str هم می‌توانیم از تابع کمکی str() استفاده کنیم:

> str()->password()
= "ZmJn^dib)GO)qutEER%QXmgt)fqJ\\PiC"

کاربردهای متعددی برای این روش وجود دارد مثل تولید گذرواژه موقت برای کاربر.

ساخت سریع‌تر پروژه در لاراول 10

قبل از لاراول 10، اگر می‌خواستیم پروژه جدیدی با Laravel Breeze و Pest ایجاد کنیم، باید چند مرحله را طی می‌کردیم:

  1. نصب پروژه تازه‌ ایجاد شده لاراول
  2. نصب Laravel Breeze
  3. نصب Laravel Pest

نصب‌کننده لاراول دو ویژگی کوچک مهم جدید دارد. هنگام ایجاد پروژه جدید لاراول با دستور «laravel new» می‌توانیم از گزینه «–breeze» استفاده کنیم تا پروژه‌ای با Laravel Breeze ایجاد شود.

همچنین اگر به جای phpunit از فریمورک تست Pest استفاده می‌کنیم، تغییر کوچک دیگری هم وجود دارد. دیگر نیاز نیست ابتدا «laravel new example-app» سپس «composer require pestphp/pest» را اجرا کنیم. بلکه می‌توانیم از «laravel new example-app –pest» استفاده کنیم.

مثال نصب پروژه جدید با breeze و pest در یک دستور:

Laravel Breeeze

Database & Migration

Native Column Modification Support

به منظور حذف نیاز به بسته DBAL (doctrine/dbal) هنگام استفاده از change() برای تغییر ستون‌ها، ویژگی جدیدی در لاراول 10 معرفی شد که به توسعه‌دهندگان اجازه می‌دهد از روش change() بدون نیاز به بسته‌های اضافه برای تغییر ستون‌ها در MySQL، PostgreSQL و SQL Server استفاده کنند. این یک تغییر پرریسک بزرگ محسوب می‌شود، اما ارزش آن را دارد زیرا وابستگی به بسته اضافی دیگری را حذف می‌کند.

برای درک بهتر از این ویژگی جدید، مثال زیر را ببینید:

$table->integer('user_balance')->unsigned()->default(0)->comment('balance'); // `user_balance` is an integer, unsigned, defaults to '0', and column comment is 'balance'

برای درک بهتر، فرض کنید ستون user_balance داریم و می‌خواهیم نوع آن را تغییر دهیم. از لاراول 10 به بعد می‌توانیم ساده این کار را انجام دهیم:

$table->bigInteger('user_balance')->change(); // This will change `user_balance` to bigInteger instead of just integer

کد بالا نوع ستون را به bigInteger تغییر می‌دهد. اما خاصیت‌هایی مانند UNSIGNED، DEFAULT و COMMENT را حذف می‌کند. بنابراین باید هنگام تغییر نوع ستون، تمام خاصیت‌ها را مجددا اضافه کنیم:

$table->bigInteger('user_balance')->unsigned()->default(0)->comment('balance')->change();

در صورت داشتن چند اتصال دیتابیس و نصب قبلی DBAL، توصیه می‌شود در تابع boot کلاس AppServiceProvider از متدSchema::useNativeSchemaOperationsIfPossible() استفاده کنید تا بتوانید از Native Column Modification Support بهره ببرید. برای انجام این کار به صورت زیر عمل کنید:

use IlluminateSupportFacadesSchema;
class AppServiceProvider extends ServiceProvider
{
  public function boot()
  {
    Schema::useNativeSchemaOperationsIfPossible();
  }
}

با استفاده از این روش می‌توانید از Native Column Modification Support بهره ببرید. توجه داشته باشید برخی دیتابیس‌ها مانند SQLite هنوز از این ویژگی پشتیبانی نمی‌کنند.

Column Type Native Retrieval

یکی دیگر از ویژگی‌های قابل توجه لاراول 10، توانایی استفاده از روش Schema::getColumnType بدون نیاز به بسته doctrine/dbal است. در حال حاضر از Schema::getColumnType به همراه DBAL برای دریافت نوع ستون استفاده می‌کنیم.

DBAL هر نوع ستون Native را به نوع معادل خودش در DBAL مپ می‌کند و بسیاری از انواع ستون مورد استفاده در لاراول در دیتابیس‌های مختلف را پشتیبانی نمی‌کند.

اما در لاراول 10، روش جدید Schema::getColumnType نوع ستون واقعی را برمی‌گرداند و نه معادل آن در DBAL. همچنین به شما اجازه می‌دهد تست‌های یکپارچه‌سازی برای ویژگی جدید تغییر ستون‌های Native بنویسید. می‌توانید از این ویژگی برای دریافت نام نوع داده یا تعریف کامل نوع برای ستون مشخص استفاده کنید:

Schema::getColumnType('products', 'price'); // decimal

پشتیبانی از متد whereExists() برای Eloquent Builder

در حال حاضر استفاده از whereExists() نیاز به پیکربندی کوئری تودرتو دارد. خوشبختانه در لاراول 10 امکان استفاده از یک بیلدر Eloquent به عنوان کوئری تودرتو وجود دارد. این امکان استفاده از متدهای سفارشی بیلدر، اسکوپ‌های مدل و غیره را فراهم می‌کند.

به عنوان مثال، در ورژن های قبلی اگر می خواستیم از whereExists() استفاده کنیم باید اینگونه عمل می کردیم:

Order::whereExists(function ($query) {
  $query->from('products')->whereColumn('products.order_id', 'orders.id');
});

اما در لاراول 10 می‌توانیم به این صورت عمل کنیم:

Order::whereExists(
  Product::whereColumn('products.order_id', 'orders.id')
);

بهینه‌سازی Eager Loading در لاراول 10

یکی از ویژگی‌های جالب جدید لاراول 10، بهینه‌سازی Eager Loading زمانی است که کلیدی برای بارگذاری وجود ندارد. این تغییر بیشتر یک اصلاح است تا ویژگی، زیرا مشکل فعلی اجرای کوئری‌های غیرممکن زیاد در Eager Loading روابط را برطرف می‌کند.

لاراول 10 ابتدا وجود کلید را بررسی می‌کند و اگر کلیدی وجود نداشته باشد، کالکشن خالی برمی‌گرداند و نیازی به کوئری غیرضروری به دیتابیس نیست.

select * from `table_name` where 0 = 1;

با این حال، به‌روزرسانی جدید لاراول 10 ابتدا بررسی می‌کند که آیا اصلا کلیدی وجود دارد یا خیر، و اگر کلیدی وجود نداشته باشد، یک کالکشن خالی برمی‌گرداند. این کار نیاز به اجرای کوئری‌های غیرضروری به دیتابیس را حذف می‌کند.

Database Expressions and Grammar-Specific Formatting

یک ویژگی بسیار عالی که چالش بزرگ کار با دیتابیس‌های متعدد را برطرف می‌کند، تنها چهار روز قبل از انتشار لاراول 10 توسط تیم اصلی لاراول ادغام شد. در نسخه‌های قبلی، اگر با PostgreSQL و MySQL کار می‌کردیم و می‌خواستیم اولین مقدار یک لیست را به عنوان یک alias برگردانیم، باید کد خام دیتابیس می‌نوشتیم:

DB::table(‘visitors')
->when(isPostgreSQL(), fn ($query) => $query->select(DB::raw('coalesce(NULL, "user", "guest") AS "First Visitor"')))
->when(isMySQL(), fn ($query) => $query->select(DB::raw('coalesce(NULL, `user`, `guest`) AS `First Visitor`')));

در بالا از تابع COALESCE برای برگرداندن اولین مقدار غیر خالی به عنوان alias استفاده کردیم. حالا می‌توانیم کلاس‌های قابل استفاده مجدد برای عبارات خام ایجاد کنیم تا نیاز به نوشتن مجدد کد خام دیتابیس نباشد. برای مثال بالا، ابتدا دو کلاس برای alias و تابع COALESCE ایجاد می‌کنیم:

class Alias implements Expression {

  // ...

}

class Coalesce implements Expression {

  // ...

}

در بالا از تابع COALESCE() برای برگرداندن اولین مقدار غیر خالی به عنوان یک alias به نام first visitor استفاده کرده‌ایم. بنابراین هر بار نیاز به انجام عملیاتی مشابه داشته باشیم، باید دوباره کد خام دیتابیس بنویسیم.

ویژگی جدید امکان ایجاد کلاس‌های قابل استفاده مجدد برای پیاده‌سازی عبارات و دستورات خام مورد نیاز در کوئری‌ها را فراهم می‌کند. این کار نیاز به نوشتن مجدد کدهای خام دیتابیس را حذف می‌کند.

برای مثال بالا، ابتدا باید دو کلاس ایجاد کنیم:

class Alias implements Expression {
  // ... 
}

class Coalesce implements Expression {
  // ...
}

سپس می‌توانیم بدون نیاز به کد خام، عملیات مورد نظر را انجام دهیم:

DB::table('visitors')
  ->select(new Alias(new Coalesce([NULL, 'user', 'guest']), 'First Visitor'));

این ویژگی امکانات زیادی را برای ارائه کلاس‌های رایج عبارات خام توسط بسته‌ها فراهم می‌کند و کدنویسی با دیتابیس‌های چندگانه را ساده‌تر می‌کند.

حذف متدهای منسوخ‌شده

متدهایی که در لاراول ۹ به عنوان منسوخ‌شده علامت‌گذاری شده بودند، در لاراول 10 حذف شده‌اند. اگر قصد به‌روزرسانی یک پروژه فعلی به لاراول 10 را دارید، باید هر بخشی از کد که از متدهای منسوخ‌شده استفاده می‌کند را با رویکرد جدیدی بازنویسی کنید تا همان نتیجه حاصل شود.

برخی از این موارد عبارتند از:

  • Removed deprecated $dates property on Eloquent Models (use $casts instead)
  • Removed deprecated Route::home method
  • Removed deprecated assertTimesSent method
  • Removed deprecated ScheduleListCommand‘s $defaultName property
  • Removed deprecated dispatchNow functionality

منابع: وب سایت kinsta.com و redberry.international

نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.