Kodokon kodokon.com

الجودة: PHPUnit وPHPStan ومعايير PSR

جهِّز كودك بالأدوات مثل المحترفين عبر اختبارات PHPUnit، والتحليل الساكن بأداة PHPStan عند المستوى 9، ومعايير PSR.

10 دقيقة · 3 أسئلة

افتح هذا الدرس في Kodokon

يُعرَف الكود على مستوى الخبراء بشبكة أمانه أكثر مما يُعرَف بحيله الذكية. ثلاث ركائز متكاملة: الاختبارات (PHPUnit) التي تتحقق من السلوك بتشغيل الكود، والتحليل الساكن (PHPStan) الذي يُثبِت خصائص دون تشغيل أيّ شيء، والمعايير المشتركة (PSR) التي تجعل المنظومة قابلة للتشغيل البيني. ويُثبَّت كل ذلك باستخدام Composer، كتبعيات تطوير.

BASH
composer require --dev phpunit/phpunit
composer require --dev phpstan/phpstan
./vendor/bin/phpunit --testdox tests
./vendor/bin/phpstan analyse src --level=9
يعرض الخيار --testdox الاختبارات على شكل مواصفة قابلة للقراءة.

منذ PHPUnit 10، تُكتب البيانات الوصفية على شكل سمات PHP: إذ يحل #[DataProvider] محل تعليق docblock الوسمي @dataProvider. ويجب أن يكون مزوّد البيانات عامًّا وساكنًا (public and static)، لأن PHPUnit يقرؤه حتى قبل إنشاء نسخة من صنف الاختبار. وتحمل كل مجموعة بيانات مفتاحًا وصفيًا، يُعرَض كما هو عند فشل الحالة - فيُحدَّد فشل accents فورًا.

PHP
<?php
declare(strict_types=1);

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

final class SlugifierTest extends TestCase
{
    #[DataProvider('provideTitles')]
    public function testSlugify(
        string $input,
        string $expected
    ): void {
        $this->assertSame($expected, slugify($input));
    }

    public static function provideTitles(): array
    {
        return [
            'simple' => [
                'Hello World', 'hello-world'
            ],
            'accents' => [
                'Déjà vu', 'deja-vu'
            ],
        ];
    }
}
يختبر دالة slugify مُعرَّفة في مكان آخر من مشروعك.

يُدرِّج PHPStan صرامته على مستويات، من 0 إلى 9 (ويوجد مستوى 10 في الإصدارات الحديثة): عند المستوى 9، تصبح أيّ قيمة من نوع mixed غير قابلة للاستخدام دون تضييق نطاقها أولًا بفحوص صريحة. وتأتي قوّته الحقيقية من أنواع docblock التي يتجاهلها محرّك PHP لكن المُحلِّل يتحقق منها: أشكال المصفوفات array{email: string}، والقوائم list<int>، والأنواع المُعمَّمة (generics). فهي توثّق وتُثبِت في آنٍ واحد.

PHP
<?php
declare(strict_types=1);

function findEmail(?array $user): string
{
    return $user['email'];
}

/**
 * @param array{email: string}|null $user
 */
function findEmailSafe(?array $user): string
{
    return $user === null
        ? 'n/a'
        : $user['email'];
}
المستوى 9: تُرفض الدالة الأولى (وصول محتمل على null، ومفتاح ونوع غير معروفين)، وتنجح الثانية.

إن معايير PSR (توصيات معايير PHP) هي أعراف مجموعة PHP-FIG. يوحّد PSR-1 وPSR-12 الأسلوب: المحاذاة، والأقواس المعقوفة، وترتيب الاستيراد - تطبّقها تلقائيًا php-cs-fixer أو phpcs. ويعرّف PSR-4 التحميل التلقائي: إذ ترتبط بادئة مساحة أسماء بمجلد، ما يتيح لـ Composer تحديد موقع أيّ صنف دون require يدوي. وأخيرًا، تتيح لك معايير PSR الخاصة بالواجهات - PSR-3 للمسجّلات، وPSR-7 لرسائل HTTP - استبدال مكتبة بأخرى دون المساس بالكود الذي يستهلكها.

اختبار المعرفة

تأكّد من أنك تذكّرت النقاط الأساسية في هذا الدرس.

  1. منذ PHPUnit 10، ما القيد الذي ينطبق على دالة مزوّد بيانات مُشار إليها بـ #[DataProvider]؟
    • يجب أن تكون عامة وساكنة، لأن PHPUnit يقرؤها قبل إنشاء نسخة من صنف الاختبار
    • يجب أن تُرجِع مولِّدًا (generator)، لا مصفوفة أبدًا
    • يجب أن تحمل الاسم نفسه للاختبار، مع إضافة اللاحقة Provider
  2. ماذا يفرض المستوى 9 من PHPStan؟
    • منع docblocks لصالح الأنواع الأصيلة فقط
    • معالجة صارمة لـ mixed: لا يمكنك استخدام قيمة كهذه دون تضييق نطاقها أولًا
    • تغطية اختبارية بنسبة 100% للكود المُحلَّل
  3. ماذا يعرّف معيار PSR-4؟
    • صيغة رسائل سجلّ التطبيق
    • الربط بين بادئة مساحة أسماء ومجلد، الذي يستخدمه مُحمِّل Composer التلقائي
    • أسلوب المحاذاة وموضع الأقواس المعقوفة