
PHP 8 هو بالفعل في مرحلة الإصدار المرشح ، الإصدار RC 3 تم إصداره في 29 أكتوبر ، ومن المقرر الإصدار الكامل في 26 نوفمبر. لذا حان الوقت لإلقاء نظرة على الميزات الجديدة التي تنتظرنا في PHP 8. يمكن الاطلاع على جدول الإصدار هنا . والدليل الرسمي للتحديث إلى إصدار جديد موجود هنا .
دعم إضافي لأنواع الاتحاد ( RFC )
يقبل نوع الاتحاد قيمًا من أنواع أخرى مختلفة ، وليس نوعًا واحدًا فقط.
<?php
declare(strict_types=1);
class Number {
private int|float $number;
public function setNumber(int|float $number): void {
$this->number = $number;
}
public function getNumber(): int|float {
return $this->number;
}
}
/**
* We can pass both floats or integer values
* to the number object. Try passing a string.
*/
$number = new Number();
$number->setNumber(5);
dump($number->getNumber());
$number->setNumber(11.54);
dump($number->getNumber());
exit;
تمت إضافة WeakMap ( RFC )
تسمح لك الخرائط الضعيفة بإنشاء علاقات بين الكائنات والقيم العشوائية (وكذلك SplObjectStorage) ، في حين أن الكائنات المستخدمة كمفاتيح ليست محمية من أداة تجميع البيانات المهملة. إذا قام المجمع بتدمير مثل هذا الكائن ، فسيتم إزالته ببساطة من الخريطة.
هذه هي ميزة مفيدة جدا. يتيح لنا التفكير بشكل أقل في تسرب الذاكرة في التعليمات البرمجية الخاصة بنا. على الرغم من أن هذا لا يمثل مشكلة بالنسبة لمعظم مطوري PHP ، إلا أنه يستحق النظر فيه عند إنشاء عمليات طويلة الأمد ، على سبيل المثال باستخدام ReactPHP. باستخدام WeakMaps ، يتم جمع مراجع الكائنات تلقائيًا بواسطة جامع البيانات المهملة عندما يصبح الكائن غير متاح.
إذا فعلت الشيء نفسه مع مصفوفة ، ستستمر مراجع الكائنات ، مما يؤدي إلى تسرب الذاكرة.
<?php
declare(strict_types=1);
class FooBar {
public WeakMap $cache;
public function __construct() {
$this->cache = new WeakMap();
}
public function getSomethingWithCaching(object $obj) {
return $this->cache[$obj] ??= $this->computeSomethingExpensive($obj);
}
public function computeSomethingExpensive(object $obj) {
dump("I got called");
return rand(1, 100);
}
}
$cacheObject = new stdClass;
$obj = new FooBar;
// "I got called" only will be printed once
$obj->getSomethingWithCaching($cacheObject);
$obj->getSomethingWithCaching($cacheObject);
dump(count($obj->cache));
// When unsetting our object, the WeakMap frees up memory
unset($cacheObject);
dump(count($obj->cache));
exit;
استثناء جديد ValueError
يقدم PHP 8 فئة استثناء مضمنة جديدة
ValueError. يكمل نفسه \Exception. تطرح PHP هذا الاستثناء في كل مرة تقوم فيها بتمرير قيمة من النوع الصحيح إلى دالة ، ولكن لا يمكن استخدامها في هذه العملية. في السابق ، كان يتم إصدار تحذير في مثل هذه الحالات. أمثلة:
<?php
declare(strict_types=1);
/**
* We pass an array to array_rand,
* which is of the correct type. But
* array_rand expects non-empty arrays.
*
* This throws a ValueError exception.
*/
array_rand([], 0);
/**
* The depth argument for json_decode is a
* valid integer, but it must be greater than 0
*/
json_decode('{}', true, -1);
عند تعريف الوظائف ، يمكنك استخدام وسيطة متغيرة
يمكن الآن استبدال أي عدد من معلمات الوظيفة بحجة متغيرة إذا كانت أنواعها متوافقة. على سبيل المثال ، الكود التالي غير صحيح:
<?php
declare(strict_types=1);
class A {
public function method(int $many, string $parameters, $here) {
}
}
class B extends A {
public function method(...$everything) {
dd($everything);
}
}
$b = new B();
$b->method('i can be overwritten!');
exit;
نوع الإرجاع ثابت ( RFC )
يمكن الآن استخدام نوع الإرجاع الثابت لتحديد ما إذا كانت الطريقة تُرجع الفئة التي تم استدعاء الطريقة من أجلها ، حتى لو كانت موروثة (الربط الثابت المتأخر).
<?php
declare(strict_types=1);
class Test {
public function doWhatever(): static {
// Do whatever.
return $this;
}
}
exit;
اسم فئة الكائن الحرفي ( RFC )
الآن يمكنك استرداد اسم فئة الكائن باستخدام
$object::class. ستكون النتيجة هي نفسها مع get_class($object).
<?php
declare(strict_types=1);
auth()->loginUsingId(1);
dump(auth()->user()::class);
// Or with a temporary variable
$user = auth()->user();
dump($user::class);
exit;
إعدادات بناء الجملة المتغيرة ( RFC )
Newو instanceofيمكن أن تستخدم الآن مع تعسفي التعابير: new ()(...$args)و $obj instanceof ().
<?php
declare(strict_types=1);
class Foo {}
class Bar {}
$class = new (collect(['Foo', 'Bar'])->random());
dd($class);
exit;
واجهة قابلة للربط ( RFC )
يقدم PHP 8 واجهة جديدة
Stringableتتم إضافتها تلقائيًا بمجرد أن تنفذ الفئة طريقة __toString. لا تحتاج إلى تنفيذ هذه الواجهة بشكل صريح.
<?php
declare(strict_types=1);
class Foo {
public function __toString() {
return 'I am a class';
}
}
$obj = new Foo;
dump($obj instanceof Stringable);
exit;
يمكن للسمات الآن تحديد الأساليب الخاصة المجردة ( RFCs )
<?php
declare(strict_types=1);
trait MyTrait {
abstract private function neededByTheTrait(): string;
public function doSomething() {
return strlen($this->neededByTheTrait());
}
}
class TraitUser {
use MyTrait;
// This is allowed:
private function neededByTheTrait(): string { }
// This is forbidden (incorrect return type)
// private function neededByTheTrait(): stdClass { }
// This is forbidden (non-static changed to static)
// private static function neededByTheTrait(): string { }
}
exit;
يمكن الآن استخدام رمي كتعبير ( RFC )
التعبير
throwيمكن أن تستخدم الآن حيث يسمح تعبيرات فقط: في وظائف السهم، ومشغلي تتجمع ومشغلي الشرطية الثلاثي (الثلاثي / ألفيس).
<?php
declare(strict_types=1);
$callable = fn() => throw new Exception();
$nullableValue = null;
// $value is non-nullable.
$value = $nullableValue ?? throw new \InvalidArgumentException();
exit;
يُسمح الآن بفاصلة معلقة اختيارية ( RFC ) في معلمات القائمة
بالتشابه مع الفاصلة المعلقة في المصفوفات ، يمكنك الآن تحديدها في معلمات القائمة.
<?php
declare(strict_types=1);
function method_with_many_arguments(
$a,
$b,
$c,
$d,
) {
dump("this is valid syntax");
}
method_with_many_arguments(
1,
2,
3,
4,
);
exit;
اصطياد الاستثناءات دون التخزين في متغير ( RFC )
الآن يمكنك الكتابة
catch ()لالتقاط الاستثناءات دون تخزينها في متغير.
<?php
declare(strict_types=1);
$nullableValue = null;
try {
$value = $nullableValue ?? throw new \InvalidArgumentException();
} catch (\InvalidArgumentException) {
dump("Something went wrong");
}
exit;
دعم إضافي لنوع مختلط ( RFC )
يقدم PHP 8 نوعًا جديدًا يسمى مختلط. يمكن أن تكون مكافئة لأنواع المصفوفة ، bool ، callable ، int ، float ، null ، object ، Resource ، string.
<?php
declare(strict_types=1);
function debug_function(mixed ...$data) {
dump($data);
}
debug_function(1, 'string', []);
exit;
دعم إضافي للسمات
هناك عدة اقتراحات لتطبيق السمات في PHP 8:
- https://wiki.php.net/rfc/attributes_v2
- https://wiki.php.net/rfc/attribute_amendments
- https://wiki.php.net/rfc/shorter_attribute_syntax
- https://wiki.php.net/rfc/shorter_attribute_syntax_change
يعد هذا أحد أكبر التغييرات في PHP 8. قد لا يكون من السهل اكتشافه في البداية. باختصار ، تسمح لك السمات بإضافة بيانات وصفية إلى وظائف PHP ، والمعلمات ، والفئات ، وما إلى ذلك. يمكن بعد ذلك استرداد هذه البيانات الوصفية برمجيًا. إذا احتجت في الإصدار 7 من PHP أو أقل إلى تحليل doclocks ، فستساعدك السمات في الوصول إلى هذه المعلومات ، المدمجة بعمق في PHP نفسها.
لتوضيح الأمر ، تخيل أنك تريد أن يتمكن المستخدمون لديك من إضافة برمجية وسيطة إلى فئة أو وحدة تحكم أسلوب باستخدام سمة.
<?php
declare(strict_types=1);
// First, we need to define the attribute. An Attribute itself is just a plain PHP class, that is annotated as an Attribute itself.
#[Attribute]
class ApplyMiddleware
{
public array $middleware = [];
public function __construct(...$middleware) {
$this->middleware = $middleware;
}
}
// This adds the attribute to the MyController class, with the "auth" middleware as an argument.
#[ApplyMiddleware('auth')]
class MyController
{
public function index() {}
}
// We can then retrieve all ApplyMiddleware attributes on our class using reflection
// And read the given middleware arguments.
$reflectionClass = new ReflectionClass(MyController::class);
$attributes = $reflectionClass->getAttributes(ApplyMiddleware::class);
foreach ($attributes as $attribute) {
$middlewareAttribute = $attribute->newInstance();
dump($middlewareAttribute->middleware);
}
exit;
دعم إضافي لإعادة توجيه خصائص المُنشئ ( RFCs )
يُقترح إضافة بناء جملة بسيط لدمج المُنشئ مع تعريف الخاصية:
<?php
declare(strict_types=1);
class User {
public function __construct(
public int $id,
public string $name,
) {}
}
$user = new User(1, 'Marcel');
dump($user->id);
dump($user->name);
exit;
دعم إضافي لتعبير المطابقة ( RFC )
يُقترح إضافة تعبير جديد
matchمشابه switch، فقط مع دلالات أكثر أمانًا والقدرة على إرجاع القيم.
<?php
declare(strict_types=1);
echo match (1) {
0 => 'Foo',
1 => 'Bar',
2 => 'Baz',
};
exit;
دعم إضافي لمشغل nullsafe (؟ ->) ( RFC )
عندما تكون نتيجة الجانب الأيسر من المشغل فارغة ، يتم إيقاف تنفيذ السلسلة بأكملها ، ويتم تعيين نتيجتها على قيمة خالية. خلاف ذلك ، تتصرف السلسلة كعامل عادي ->.
<?php
declare(strict_types=1);
class User {
public function getAddress() {}
}
$user = new User();
$country = $user?->getAddress()?->country?->iso_code;
dump($country);
exit;
دعم إضافي للوسائط المسماة ( RFCs )
تسمح لك التسمية بتمرير الوسائط إلى وظيفة بناءً على اسم المعلمة ، وليس على موقعها. أي أن قيم الوسائط تصبح ذاتية التوثيق ، ولم تعد الوسائط تعتمد على ترتيب التعداد ، لذا يمكنك تخطي القيم الافتراضية بشكل عشوائي.
<?php
declare(strict_types=1);
array_fill(start_index: 0, num: 100, value: 50);
exit;