دوستان و همراهان عزیز به قسمت هفتم جت کد کست خوش اومدین، این قسمت میخوایم به بررسی تغییرات ورژن جدید PHP یعنی PHP8 بپردازیم. همونطور که سایت خود PHP هم گفته، این نسخه، یه Major Update هست که تغییرات زیادی شامل امکانات جدید و بهینه سازی رو در بر میگیره.

قبل از اینکه بخوایم شروع کنیم به بررسی این تغییرات، بزارین یه توضیح خیلی مختصر راجع به خود این زبان برنامه نویسی ارائه بدیم برای دوستانی که آشنایی ندارن. PHP که مخفف PHP Hypertext Processor هست، یه زبان برنامه نویسی از نوع اسکریپتی و مفسریه و برای بک اند وب هست که با C نوشته شده و توسط Rasmus Lerdorf سال ۱۹۹۴ منتشر شده و یه جورایی سال هاست که سر دسته زبان های بک اند برای توسعه هست و الانی که دارم این اپیزود رو ضبط میکنم ورژن ۸٫۰٫۲ هم ریلیز شده و در دسترسه.

خب حالا بریم سراغ اصل مطلب یعنی بررسی تغییرات PHP8. تو این ورژن ما شاهد تغییرات زیادی در هسته این زبان هستیم که منطقیه چون همونطور که کمی قبل گفتم این یه Major update هست.

از جمله این تغییرات میشه به:

Union Type، NamedArguments, Match Expressions، constructor Property Promotion، Nullsafe Operator, Weak Maps Just In Time Compilation که اهمیت فوق العاده ای در بهینه شدن سرعت این ورژن پی اچ پی داره و حتما بهش می پردازیم.

Named arguments

خب بیاین با Named arguments شروع کنیم. اول از همه بگم که احتمالا میدونید این چه فیچریه چون تو پایتون هم ما داشتیم. در واقع Named arguments همون Keyword parameter هست که ما توی توابعمون میتونیم تعریف کنیم هر آرگومان یا پارامتر چه اسمی داره و بعد موقع صدا زدن اون تابع، مقدایر آرگومان ها رو جلو اسمشون می نویسم.

این فیچر واقعا Life Saver هست و من نمیدونم چرا قبلا اینو نداشتیم. برای من یکی که این قابلیت به تنهایی کافیه برای اینکه پروژه رو به سمت PHP8 هل بدم جلو. چون میدونید دیگه مثلا یه تابع سه تا آرگومان داره که وسطیش اختیاریه! قبلا موقع صدا زدن همچین تابعی باید هر سه آرگومان رو وارد میکردیم و مثلا وسطی رو میتونستیم Null یا Empty String بزنیم و تو فانکشن اینو هندل میکردیم. اما الان میشه آرگومان های اختیاری رو اصلا وارد نکرد و به اصلاح به جای Positional Argument که میگه باید پارامتر ها رو به ترتیب وارد کنی، از روش Named arguments استفاده میکنیم.

مثال PHP7:

htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);

مثال PHP8:

htmlspecialchars($string, double_encode: false);

Constructor property promotion

Constructor property promotion چیه؟ این قابلیت به ما این امکان رو میده که ویژگی های یک کلاس رو با کد کمتری تعریف و مقدار دهی کنیم. به عنوان مثال فرض کنید ما یه کلاس User داریم که یک ویژگی داره به اسم isAdmin و میخوایم پیش فرض false باشه اما اگر موقع ساختن نمونه از کلاس مقداری برای آرگومان isAdmin وارد شده بود، اون مقدار در پراپرتی isAdmin ذخیره بشه.

مثال PHP7:

class User {
  public bool $isAdmin;

  public function __construct(
    bool $isAdmin = false
  ) {
    $this->isAdmin = $isAdmin;
  }
}

مثال PHP8:

class User {
  public function __construct(
    public bool $isAdmin = false
  ) {}
}

برای اینکه بهتر متوجه این ویژگی بشین حتما مقاله مرتبط با این اپیزود رو که لینکش رو توی توضیحات پادکست میزارم مطالعه کنید و به مثال ها دقت کنید.

Union types

به کمک این ویژگی جدید میتونیم چند نوع داده برای یک متغیر تعریف کنیم و اگر نوع داده ی اون متغیر هیچ کدوم از اونها نبود، خطای از نوع Type Error میده. البته قبلا هم میتونستیم این کار رو انجام بدیم اما با استفاده از PHPDoc annotation. الان میشه خیلی راحت میشه از این قابلیت استفاده کرد. چطوری؟ فرض کنید میخایم ویژگی وزن در کلاس User از نوع Int یا Float باشه، برای اینکار میایم از این سینتکس استفاده می کنیم:

class User {
  public function __construct(
    private int|float $weight
  ) {}
}

Match expression

مچ اکسپرشن ها تقریبا شبیه همون Switch ها هستند اما با یه سری تفاوت. شما میتونید رو یه چیزی سوییچ کنید و بگید اگر مقدارش فلان چیز بود این چیز رو برگردون. اما دیگه break نمیخواد و اینکه به ازای هر مچ فقط میتونید یک خط کد بنویسید. اما این خیلی جا ها بدرد میخوره. یه مقال واضحش تبدیل روز های هفته از عدد به متنه. یادتون نره که خروجی این تابع match رو میشه echo کرد، توی یه متغیر ریخت و یا return کرد، چون این یک expression حساب میشه.

echo match(0){
    ۰ => 'شنبه',
    ۱ => 'یکشنبه',
    ,...
};
// نتیجه این کد نمایش "شنبه" هست

Nullsafe operator

عملگر نال سیف یکی از فیچر هاییه که کار رو برای توسعه دهنده ها راحت میکنه. فرض کنید شما میخواهید کشور زندگی کاربر رو بگیرید، قبلا برای اینکار اول چک می کردیم آیا $user نال هست یا نه، اگر نال نبود حالا اگر فیلد کشور داخلش هم نال نبود از متغیر $user، آدرس رو و از آدرس، کشور رو میگرفتیم.

مثال PHP7:

if ($user !== null) {
    $address = $user->getAddress();

    if ($address !== null) {
      $country = $address->country;
    }
  }

مثال PHP8:

$country = $user?->getAddress()?->country;

Non-capturing catches

تا قبل از PHP8 اگر میخواستیم به Exception رو بگیری باید توی یه متغیر میریختی مثلا به اسم $error یا $exception، حتی اگر از اون متغیر استفاده هم نمیکردی و صرفا برای هندل کردن خطا بوده. اما الان با استفاده از قابلیت Non-capturing catches این امکان وجود داره که اگر نخواستی اون متغیر رو نسازی.

مثال PHP7:

try {
    // Something goes wrong
} catch (MySpecialException $exception) {
    Log::error("Something went wrong");
}

مثال PHP8:

try {
    // Something goes wrong
} catch (MySpecialException) {
    Log::error("Something went wrong");
}

Trailing comma in parameter lists

از این به بعد میتونید بعد از آخرین آرگومان داخل تابع هم یه کاما بزارین. چیز خاصی نیست اما خوبه که باشه. تو زبان های دیگه مثل پایتون هم ما همچین چیزی رو داریم.

public function add(
    string $name,
    int $age,
) {
    // کد های بدنه تابع
}

تابع str_contains

با استفاده از این تابع میتونید چک کنید آیا درون یک رشته، رشته ی دیگری پیدا میشه یا نه. قبلا این کار رو با strpos میکردیم ولی الان یه تابع مخصوص این کار دست شده که یه Boolean برمیگردونه و خیلی ساده تر شده.

if (str_contains('Test Hello World Test', 'Hello')) { echo "Found!" }

تابع str_starts_with() و str_ends_with()

با استفاده از تابع str_starts_with() میتونیم چک کنیم ابتدای یک رشته، با یه رشته خاصی شروع میشه یا نه. و تابع str_ends_with() هم این کار رو به نسبت آخر یک رشته انجام میده. خروجی این دو تابع Boolean هست و میتونید ازش توی دستورات شرطی و… استفاده کنید.

مثال PHP8:

str_starts_with('haystack', 'hay'); // true
str_ends_with('haystack', 'stack'); // true

از اونجایی که لیست تغییرات این نسخه خصوصا چیزای جزیی زیادن، به سری از تغییرات جزیی و بهبود ها رو به صورت لیست وار مرور میکنیم:

  • Stable sorting
  • Saner string to number comparisons
  • Saner numeric strings
  • Stricter type checks for arithmetic and bitwise operators
  • Concatenation precedence
  • The @ operator no longer silences fatal errors
    روی پروداکشن اگر display_errors=Off رو تنظیم کنید تا اگر قبلا خطایی با @ مخفی شده بوده، الان هم نمایش داده نشه!
  • Consistent type errors
  • New mixed type
  • New static return type

خب از اونجاییکه حرفمون یکم طولانی شد، یه break بدیم و برگردیم راجع به JIT صحبت کنیم.

JIT (The Just in Time Compiler)

JIT یه تکنولوژیه که مثل یه مفسر عادی در زمان اجرا کد ها رو به زبان ماشین تبدیل میکنه اما با این تفاوت که اگر دید یه تیکه کدی چند بار فراخوانی شده سعی میکنه اون رو کش کنه تا پروفرمنس بهتری داشته باشیم و این فرایند بهینه بشه. در نتیجه تکه کد های از قبل کامپایل شده رو در صورتی که تغییر نکرده باشند در زمان اجرا استفاده می کنه.

ظاهرا JIT قراره پروفرمنس بهتری داشته باشه اما در عمل برای نرم افزارهای تحت وب مثل وردپرس، تفاوت چشمگیری در سرعتشون دیده نمیشه. اما JIT بخاطر ساختارش مزایای دیگه ای هم داره و در آبنده میتونه فرصت های خیلی خوبی رو برای زبانی مثل PHP ایجاد کنه. از جمله اینکه Cross platform هست و از این جهت که PHP ادعا میکنه General Purpose هست خب میتونه برای مفید باشه و بتونه از این طریق برای فضای خارج از وب هم خودش رو بهینه تر کنه.

خب به همین مقدار بسنده می کنیم. در مورد JIT و فیچر های دیگه ی PHP8 خیلی بیشتر میشه حرف زد اما از طرفی از حوصله ی من و شما تو این پادکست و مقاله خارج میشه و از سمتی دانش فنی بیشتری نیازداره.

امیدوارم مطالب این پادکست و مقاله به کارتون بیاد. مواظب خودتون باشین و پیش به سوی PHP8!

لینک ها و منابع