تبنَّ PHP اليوم: الأنواع الصارمة، والدوال السهمية، ومُعامِل الأمان من null، والتعدادات، وتعبير match.
افتح هذا الدرس في Kodokonتحتضن PHP الحديثة التنميط. تعطّل declare(strict_types=1)، الموضوعة كأول تعليمة في الملف، التحويلات الضمنية: فتمرير السلسلة '10' إلى وسيط من النوع float يُطلق TypeError بدلًا من تحويلها بصمت. حدِّد أنواع الوسائط والقيم المُرجَعة: فتظهر أخطاؤك مبكرًا، في المكان الصحيح، بدلًا من أن تظهر بعد ثلاثة ملفات.
<?php
declare(strict_types=1);
function applyDiscount(
float $price,
float $rate = 0.1
): float {
return round($price * (1 - $rate), 2);
}
echo applyDiscount(49.99);
echo PHP_EOL;
echo applyDiscount(100.0, 0.25);تختصر الدوال السهمية fn الدوال المجهولة ذات التعبير الواحد. وميزتها الكبرى مقارنة بالإغلاقات التقليدية: أنها تلتقط تلقائيًا متغيرات النطاق الأب، دون عبارة use. وهي تتألق مع array_map() وarray_filter().
<?php
declare(strict_types=1);
$prices = [12.5, 49.9, 8.0, 120.0];
$rate = 0.2;
$discounted = array_map(
fn (float $p): float => round($p * (1 - $rate), 2),
$prices
);
$affordable = array_filter(
$discounted,
fn (float $p): bool => $p < 50
);
print_r($affordable);يقطع مُعامِل الأمان من null ?-> الاستدعاء حالما تكون إحدى الحلقات في السلسلة null، بدلًا من التسبب في خطأ فادح. وعند دمجه مع ??، يستبدل بأهرام من عبارات if سطرًا واحدًا سهل القراءة.
<?php
declare(strict_types=1);
class Address
{
public function __construct(
public readonly string $city
) {
}
}
class User
{
public function __construct(
public readonly ?Address $address = null
) {
}
}
$alice = new User(new Address('Lyon'));
$bob = new User();
echo $alice->address?->city ?? 'Unknown city';
echo PHP_EOL;
echo $bob->address?->city ?? 'Unknown city';تمنح التعدادات نوعًا حقيقيًا لمجموعات القيم المغلقة (الحالات، الأدوار): فيصبح من المستحيل إنشاء حالة غير موجودة. وmatch تحسين واضح على switch: مقارنة صارمة، ونتيجة تُرجَع كقيمة، وUnhandledMatchError إذا لم تطابق أيّ حالة - وهي حماية من السهو.
<?php
declare(strict_types=1);
enum OrderStatus: string
{
case Pending = 'pending';
case Shipped = 'shipped';
case Delivered = 'delivered';
public function label(): string
{
return match ($this) {
self::Pending => 'Pending',
self::Shipped => 'Shipped',
self::Delivered => 'Delivered',
};
}
}
$status = OrderStatus::from('shipped');
echo $status->label();