PHP، یکی از محبوبترین زبانهای برنامهنویسی سمت سرور، همچنان به تکامل خود ادامه میدهد تا نیازهای توسعه وب مدرن را برآورده کند. انتشار PHP 8.3 مجموعهای از ویژگیها و پیشرفتهای هیجانانگیز را به همراه دارد که زندگی توسعهدهندگان را آسانتر و کد آنها را کارآمدتر میکند. در این مقاله، ما به نکات کلیدی PHP 8.3 می پردازیم و بررسی می کنیم که چگونه می توانند برای توسعه دهندگان و صاحبان وب سایت مفید باشند.. اگر می خواهید به روز بمانید، با آنوفل همراه باشید.
PHP 8.3 در 23 نوامبر 2023 منتشر خواهد شد. بهبودهایی در کلاسهای فقط خواندنی، تابع جدید ()json_validate
، اضافهشده به کلاس Randomizer
که اخیراً اضافهشده، تشخیص stack overflow و موارد دیگر دارد.
اصلاحات فقط خواندنی
این RFC دو تغییر را پیشنهاد کرد، اما تنها یکی پذیرفته شد: قادر به شروع مجدد خصوصیات فقط خواندنی در حین شبیهسازی یا همان کلون کردن. این ممکن است بسیار بزرگ به نظر برسد، اما این RFC فقط به یک مورد لبه (edge) بسیار خاص اما مهم می پردازد: بازنویسی مقادیر ویژگی در ()clone__
، به منظور امکان شبیه سازی عمیق خواص فقط خواندنی.
readonly class Post
{
public function __construct(
public string $title,
public string $author,
public DateTime $createdAt,
) {}
public function __clone()
{
$this->createdAt = new DateTime();
// This is allowed,
// even though `createdAt` is a readonly property.
}
}
ثابت های کلاس
اکنون می توانید ثابت های کلاس را تایپ کنید:
class Foo
{
const string BAR = 'baz';
}
ویژگی [Override]#
ویژگی جدید [Override]#
برای نشان دادن قصد برنامه نویس استفاده می شود. اساساً می گوید "من می دانم که این متد یک متد والد را نادیده می گیرد. اگر زمانی تغییر کرد، لطفاً به من اطلاع دهید".
در اینجا یک مثال است:
abstract class Parent
{
public function methodWithDefaultImplementation(): int
{
return 1;
}
}
final class Child extends Parent
{
#[Override]
public function methodWithDefaultImplementation(): int
{
return 2; // The overridden method
}
}
حال، بیایید تصور کنیم در یک نقطه متد والد نام متد خود را تغییر دهد:
abstract class Parent
{
public function methodWithNewImplementation(): int
{
return 1;
}
}
به لطف ویژگی [Override]#
، PHP میتواند تشخیص دهد که ()Child::methodWithDefaultImplementation
دیگر هیچ چیزی را override نمیکند و یک خطا ایجاد میکند و میتواند منجر به باگهای پیشبینی نشده شود.
ایندکس های منفی در آرایه ها
اگر یک آرایه خالی دارید، یک مورد با ایندکس منفی اضافه کنید، و سپس یک مورد دیگر اضافه کنید، آن وقت آیتم دوم همیشه با ایندکس 0 شروع می شود:
$array = [];
$array[-5] = 'a';
$array[] = 'b';
var_export($array);
//array (
// -5 => 'a',
// 0 => 'b',
//)
با شروع از PHP 8.3، مورد بعدی در ایندکس 4-
اضافه می شود:
//array (
// -5 => 'a',
// -4 => 'b',
//)
کلاس های فقط خواندنی ناشناس
قبلاً نمیتوانستید کلاسهای ناشناس را فقط خواندنی علامتگذاری کنید. که در PHP 8.3 این مشکل درست شده است:
$class = new readonly class {
public function __construct(
public string $foo = 'bar',
) {}
};
و
$class = new readonly class {
public function __construct(
public string $foo = 'bar',
) {}
};
تابع جدید ()json_validate
پیش از این، تنها راه برای تأیید اعتبار یک رشته JSON، رمزگشایی آن و تشخیص وجود خطا بود. این تابع جدید ()json_validate
مفید است اگر فقط نیاز داشته باشید که بدانید ورودی JSON معتبر است، زیرا در مقایسه با رمزگشایی رشته از حافظه کمتری استفاده می کند.
json_validate(string $json, int $depth = 512, int $flags = 0): bool
اضافه شدن های Randomizer
PHP 8.2 کلاس جدید Randomizer را اضافه کرد. این به روز رسانی مقداری افزودنی کوچک را به همراه داشت:
Randomizer::getBytesFromString(string $string, int $length): string
این روش به شما امکان می دهد رشته ای با طول معین تولید کنید که شامل بایت هایی است که به طور تصادفی از یک رشته مشخص انتخاب شده اند.
Randomizer::getFloat(
float $min,
float $max,
IntervalBoundary $boundary = IntervalBoundary::ClosedOpen
): float
()getFloat
یک اعشار بین min$
و max$
برمی گرداند. شما می توانید تعیین کنید که آیا min$
و max$
باید به لطف شماره IntervalBoundary
گنجانده شوند یا خیر. Closed
به این معنی است که مقدار گنجانده شده است، در حالی که Open
به معنای حذف شده است.
Randomizer::nextFloat(): float {}
در نهایت، ()nextFloat
مخفف getFloat(0, 1, IntervalBoundary::ClosedOpen)
است، به عبارت دیگر: به شما یک اعشار تصادفی بین 0 و 1 می دهد که در آن 1 حذف می شود.
Dynamic class constant fetch
PHP 8.3 به شما این امکان را می دهد که ثابت ها را با سینتکس پویاتر فتچ کنید:
class Foo
{
const BAR = 'bar';
}
$name = 'BAR';
// Instead of this:
constant(Foo::class . '::' . $name);
// You can now do this:
Foo::{$name};
استثناهای تاریخ/زمان مناسب تر
در بسیاری از موارد، PHP به سادگی یک شی Exception
یا Error
را پرتاب می کند. یا هنگامی که مشکلی در برخورد با تاریخ ها و زمان ها پیش آمد، هشدار یا خطا به وجود می آمد. این RFC تمام آن موارد لبه را بررسی می کند و استثناهای اختصاصی مناسب را برای آنها اضافه می کند.
اکنون استثناهایی مانند DateMalformedIntervalStringException
، DateInvalidOperationException
و DateRangeError
داریم.
به طور کلی، این اضافات هیچ کدی را نمیشکنند، زیرا این استثناها و خطاهای جدید اضافهشده، کلاسهای Exception
و Error
را زیرکلاس میکنند. با این حال، سه تغییر کوچک کوچک با این RFC وجود دارد:
Epoch doesn't fit in a PHP integer
، اکنون به جای یک ValueError
عمومی، یک DateRangeError
جدید را برمیگرداند، که آن را زیرکلاس نمیکند. این مشکل فقط برای پلتفرم های 32 بیتی است.
The Only non-special relative time specifications are supported for subtraction
با ()DateTime::sub
و ()date_sub
تبدیل به یک DateInvalidOperationException
جدید می شود.
Unknown or bad format (%s) at position %d (%c): %s
و String '%s' contains non-relative elements
اخطارهای غیرنسبی است که هنگام تجزیه رشتههای DateInterval
اشتباه/شکسته ایجاد میشوند، اکنون یک DateMalformedIntervalStringException
جدید ایجاد میکنند. با رابط OO، به جای نشان دادن یک هشدار و بازگشت نادرست.
مدیریت خطای ()unserialize بهبود یافته است
()unserialize
اکنون همیشه در هنگام مواجه شدن با مشکلات به جای گاهی اوقات یک E_NOTICE
یک E_WARNING
منتشر می کند.
این RFC همچنین اضافه کردن استثناهای بیشتری را هنگام اجرای ()unserialize
پیشنهاد کرد، اما آن بخش پذیرفته نشد.
تابع ()range را تغییر می دهد
از تغییرات:
اکنون یک TypeError
هنگام ارسال اشیا، منابع یا آرایه ها به عنوان ورودی های مرزی پرتاب می شود.
هنگام عبور از 0 برای step$
، یک ValueError
توصیفی تر پرتاب می شود
اکنون هنگام استفاده از step$
منفی برای افزایش محدوده، یک ValueError
پرتاب می شود
اگر step$
یک اعشار است که می تواند به عنوان int
تفسیر شود، اکنون این کار انجام می شود
اگر آرگومان بی نهایت یا NAN
باشد، اکنون یک ValueError
پرتاب می شود
اگر start$
یا end$
رشته خالی باشد، اکنون یک E_WARNING
منتشر میشود. مقدار همچنان به مقدار 0
ریخته می شود.
اگر start$
یا end$
بیش از یک بایت داشته باشد، اکنون یک E_WARNING
منتشر می شود، فقط اگر یک رشته غیر عددی باشد.
اگر start$
یا end$
به یک عدد صحیح فرستاده شود، اکنون یک E_WARNING
منتشر می شود زیرا ورودی مرزی دیگر یک عدد است. (به عنوان مثال محدوده ؛(z'،5')
)
اگر step$
هنگام تلاش برای تولید طیفی از کاراکترها یک اعشار باشد، اکنون یک E_WARNING
منتشر میشود، به جز اگر هر دو ورودی مرزی رشتههای عددی باشند (مثلاً ؛range('5', '9', 0.5)
اخطاری تولید نمیکند)
()range
اکنون لیستی از کاراکترها را تولید می کند اگر یکی از ورودی های مرزی یک عدد رشته ای باشد به جای ارسال ورودی دیگر به int
(به عنوان مثال range('5', ;'z')
)
صفات و خواص استاتیک
از تغییرات:
استفاده از صفات با ویژگی های استاتیک اکنون ویژگی های استاتیک به ارث رسیده از کلاس والد را مجدداً اعلام می کند. این یک ذخیره سازی خصوصیات ثابت جداگانه برای کلاس فعلی ایجاد می کند. این مشابه با اضافه کردن ویژگی استاتیک به کلاس به طور مستقیم بدون صفات است.
تشخیص Stack overflow
PHP 8.3 دو دستورالعمل ini
جدید به نامهای zend.max_allowed_stack_size
و zend.reserved_stack_size
اضافه میکند. برنامههایی که نزدیک به پر شدن استک تماس هستند، ممکن است هنگام استفاده از تفاوت بین zend.max_allowed_stack_size
و zend.reserved_stack_size
، خطا ایجاد کنند.
مزیت این ویژگی این است که خطاهای تقسیمبندی ناشی از استک اورفلو دیگر منجر به خطای Segfault
نمیشوند و اشکالزدایی را بسیار آسانتر میکنند.
مقدار پیش فرض zend.max_allowed_stack_size
برابر 0 است، به این معنی که PHP به طور خودکار یک مقدار را تعیین می کند. همچنین می توانید 1-
را برای نشان دادن محدودیت یا تعداد خاصی از بایت ها ارائه دهید. دستور zend.reserved_stack_size
برای تعیین "ناحیه بافر" استفاده می شود، به طوری که PHP می تواند به جای اینکه حافظه واقعی تمام شود، همچنان خطا ایجاد کند. مقدار در اینجا باید تعدادی بایت باشد، اما PHP یک پیشفرض معقول را برای شما تعیین میکند، بنابراین لزوماً نیازی به تنظیم آن ندارید، مگر اینکه در حال اجرا در موارد لبه برای برنامههای خاص باشید.
در نکته پایانی، برای فیبرها، دستورالعمل fiber.stack_size
موجود به عنوان حداکثر اندازه مجاز استک استفاده می شود.
zend.max_allowed_stack_size=128K
تابع mb_str_pad جدید
از RFC:
در PHP، توابع رشته های مختلف در دو نوع موجود هستند: یکی برای رشته های بایت و دیگری برای رشته های چند بایتی. با این حال، یک غیبت قابل توجه در میان توابع رشته چند بایتی معادل ()mbstring str_pad
است. تابع ()str_pad
فاقد پشتیبانی از کاراکترهای چند بایتی است و در هنگام کار با زبانهایی که از رمزگذاریهای چند بایتی مانند UTF-8 استفاده میکنند، مشکلاتی ایجاد میکند. این RFC اضافه کردن چنین تابعی را به PHP پیشنهاد میکند که آن را ()mb_str_pad
مینامیم.
تابع به شکل زیر است:
function mb_str_pad(
string $string,
int $length,
string $pad_string = " ",
int $pad_type = STR_PAD_RIGHT,
?string $encoding = null,
): string {}
کلاسور های متد جادویی و آرگومان های نامگذاری شده
فرض کنید کلاسی دارید که از متدهای جادویی پشتیبانی می کند:
class Test {
public function __call($name, $args)
{
var_dump($name, $args);
}
public static function __callStatic($name, $args) {
var_dump($name, $args);
}
}
PHP 8.3 به شما این امکان را میدهد که کلاسور هایی را از آن متدها ایجاد کنید و سپس آرگومانهای نامگذاری شده را به آن کلاسور ها ارسال کنید. قبلا این امکان وجود نداشت.
$test = new Test();
$closure = $test->magic(...);
$closure(a: 'hello', b: 'world');
دید تغییر ناپذیر ثابت
پیش از این، هنگام پیادهسازی یک رابط، قابلیت مشاهده برای ثابتها بررسی نمیشد. PHP 8.3 این باگ را برطرف میکند، اما اگر از این رفتار آگاه نبودید ممکن است در برخی مکانها منجر به شکستن کد شود.
interface I {
public const FOO = 'foo';
}
class C implements I {
private const FOO = 'foo';
}
کاهش های کوچک RFC
همانطور که در هر نسخه معمولی است، یک RFC واحد وجود دارد که تعدادی از کاهش های کوچک را اضافه می کند. به خاطر داشته باشید که تحریفها هیچ خطایی ندارند و اینها به طور کلی چیز خوبی برای پیشرفت زبان هستند. این موارد منسوخ شده هستند، می توانید جزئیات بیشتر در مورد آنها را در RFC بخوانید:
رد کردن widths$
منفی به ()mb_strimwidth
ثابت NumberFormatter::TYPE_CURRENCY
را منسوخ کرده و حذف کنید
منسوخ کردن و حذف اجرای شکسته قبل از PHP 7.1 Mt19937 (MT_RAND_PHP)
فراخوانی ()ldap_connect
را با دو پارامتر host$
و port$
منسوخ و حذف کنید
تغییرات کوچک، اما قابل توجه
هر تغییری در PHP از فرآیند RFC عبور نمی کند. در واقع، اکثر تغییرات شامل تعمیر و نگهداری و رفع اشکال است و نیازی به RFC ندارد. همه این تغییرات در سند UPGRADING
ذکر شده است. من برخی از برجستهترین آنها را فهرست میکنم، اما اگر میخواهید در مورد کوچکترین جزئیات بدانید، حتماً باید کل فهرست را بخوانید.
هنگام استفاده از FFI، توابع C که نوع بازگشتی از void
دارند، به جای برگرداندن FFI\CData:void
، اکنون null
را برمیگردانند.
()posix_getrlimit
اکنون یک پارامتر اختیاری res$
می گیرد تا امکان واکشی یک محدودیت منبع را فراهم کند.
()gc_status
دارای چهار فیلد جدید است: در حال اجرا، محافظت شده، کامل و buffer_size
.
()class_alias
اکنون از ایجاد نام مستعار یک کلاس داخلی پشتیبانی می کند.
اکنون ()mysqli_poll
یک ValueError
را زمانی که آرگومانهای read nor error
ارسال میشوند، افزایش میدهد.
()array_pad
اکنون فقط با حداکثر تعداد عناصری که یک آرایه می تواند داشته باشد محدود شده است. پیش از این، تنها امکان افزودن حداکثر 1048576 عنصر در یک زمان وجود داشت.
توابع جدید posix: posix_sysconf()، posix_pathconf()، posix_fpathconf() و ()posix_eaccess
چندین بار اجرای ()proc_get_status
اکنون همیشه مقدار مناسب را در سیستم های posix برمی گرداند.
دستور ini opcache.consistency_checks
حذف شد.
() array_sum
و ()array_product
بهبود یافته
نتیجه
در نتیجه، PHP 8.3 بسیاری از پیشرفت ها و ویژگی های جدید را به ارمغان می آورد و آن را به یک ارتقاء هیجان انگیز برای توسعه دهندگان تبدیل می کند. فرقی نمیکند به افزایش عملکرد، ایمنی نوع بهبودیافته یا مدیریت خطای پیشرفتهتر علاقهمند باشید، PHP 8.3 چیزی برای همه دارد.