اذهب إلى المحتوى

تمهيد لعمليتي التحميل والتنزيل التلقائي في PHP


سارة محمد2

التحميل التلقائي (autoloading) كجزء من حل إطار العمل

ملف autoload.php:

spl_autoload_register(function ($class) {
    require_once "$class.php";
});

ملف Animal.php:

class Animal {
    public function eats($food) {
        echo "Yum, $food!";
    }
}

ملف Ruminant.php:

class Ruminant extends Animal {
    public function eats($food) {
        if ('grass' === $food) {
            parent::eats($food);
        } else {
            echo "Yuck, $food!";
        }
    }
}

ملف Cow.php:

class Cow extends Ruminant {
}

ملف pasture.php:

require 'autoload.php';
$animal = new Cow;
$animal->eats('grass');

يمكننا الوصول إلى أي صنف يتبع اصطلاحات التسمية الموجودة في المحمِّل التلقائي وذلك بفضل المحمل التلقائي العام. اصطلاحاتنا في هذا المثال بسيطة: يجب أن يكون للصنف المطلوب ملف في نفس المجلد يُسمّى بنفس اسم الصنف وتُضاف له اللاحقة ‎.php، يجب أن يكون اسم الصنف مطابقًا تمامًا لاسم الملف.

بدون التحميل التلقائي، يجب أن نضيف الأصناف الأساسية يدويًا باستخدام require، إذا كنا نبني حديقة حيوانات كاملة سيكون لدينا الآلاف من تعليمات require التي يمكن استبدالها بسهولة بمحمِّل تلقائي واحد.

في التحليل النهائي، يعدّ التحميل التلقائي في PHP آلية تساعدك على كتابة شيفرة بآلية أقل لذا يمكنك التركيز على حل مشاكل العمل، كل ماعليك فعله هو تحديد استراتيجية تربط اسم الصنف باسم الملف، يمكنك تنفيذ استراتيجية تحميل تلقائي خاصة بك كما هو الحال هنا، أو يمكنك استخدام أي من المعايير التي تتبناها PHP: ‏PSR-0 أو‏PSR-4 أو يمكنك استخدام المُنشئ لتعريف الاعتماديات وإدارتها بشكلٍ عام.

تعريف صنف مضمَّن بدون الحاجة للتحميل

ملف zoo.php:

class Animal {
    public function eats($food) {
        echo "Yum, $food!";
    }
}

$animal = new Animal();
$animal->eats('meat');

تعلم PHP ماهو الصنف Animal قبل تنفيذ التعليمة new Animal لأن PHP تقرأ الملفات المصدرية من الأعلى إلى الأسفل، لكن ماذا لو أردنا إنشاء كائنات من الصنف Animal في عدة أماكن ليس فقط في الملف المصدري الذي عُرِّف فيه، نحتاج للقيام بذلك إلى تحميل تعريف الصنف.

تحميل يدوي للصنف باستخدام require

ملف Animal.php:

class Animal {
    public function eats($food) {
        echo "Yum, $food!";
    }
}

ملف zoo.php:

require 'Animal.php';
$animal = new Animal;
$animal->eats('slop');

ملف aquarium.php:

require 'Animal.php';
$animal = new Animal;
$animal->eats('shrimp');

لدينا ثلاثة ملفات، يعرّف الملف الأول "Animal.php" الصنف، ويجمع كل المعلومات المتعلقة بالحيوان في مكان واحد بشكلٍ أنيق، ليس لهذا الملف آثار جانبية، هذه نسخة قابلة للتحكم ويمكن إعادة استخدامها بسهولة.

يستخدم الملفان الآخران هذا الملف بتضمينه يدويًا، وبما أنّ PHP تقرأ الملف المصدري من الأعلى إلى الأسفل فإنّ تعليمة require ستجد الملف "Animal.php" وتجعل تعريف الصنف Animal متوفرًا قبل استدعاء new Animal.

تخيل الآن أنّه لديك عشرات أو مئات الحالات التي تريد فيها إنشاء كائنات جديدة من الصنف Animal قد يتطلب ذلك الكثير من تعليمات require المملة.

التحميل التلقائي بديلًا لتحميل تعريف الصنف يدويًا

ملف autoload.php:

spl_autoload_register(function ($class) {
    require_once "$class.php";
});

ملف Animal.php:

class Animal {
    public function eats($food) {
        echo "Yum, $food!";
    }
}

ملف zoo.php:

require 'autoload.php';
$animal = new Animal;
$animal->eats('slop');

ملف aquarium.php:

require 'autoload.php';
$animal = new Animal;
$animal->eats('shrimp');

وازن هذا المثال مع الأمثلة الأخرى، ولاحظ كيف استبدلنا التعليمة require "Animal.php‎"‎ بالتعليمة require "autoload.php"‎، مازلنا نضمن الملف الخارجي في وقت التنفيذ لكن بدلًا من تضمين تعريف صنف معين نضمّن منطق يمكن أن يحتوي على أي صنف وهذا يسهّل عملية التطوير،إذ نكتب تعليمة require واحدة لكل الأصناف بدلًا من كتابتها لكل صنف على حدة.

يحدث السحر باستخدام spl_autoload_register، إذ تأخذ هذه الدالة مغلِّف وتضيفه إلى رتل من المغلِّفات، عندما تصادف PHP صنفًا ليس له تعريف فإنها تعطي اسم الصنف إلى كل مغلِّف في الرتل، إذا وِجد الصنف بعد استدعاء مغلِّف ما فإنّ PHP تعود إلى عملها السابق، وإذا لم يوجد الصنف بعد تجربة كامل الرتل تتعطل PHP وتطلق الخطأ "Class 'Whatever' not found.‎"

التحميل التلقائي مع المُنشِئ

يولِّد المُنشئ الملف vendor/autoload.php، يمكنك تضمين هذا الملف ببساطة وستحصل على التحميل التلقائي مجانًا.

require __DIR__ . '/vendor/autoload.php';

وهذا يجعل العمل مع اعتماديات من طرف ثالث (third-party dependencies) سهل جدًا، ويمكنك أن تضيف أيضًا شيفرتك الخاصة إلى المحمِّل التلقائي بإضافة قسم تحميل تلقائي إلى composer.json.

{
    "autoload": {
        "psr-4": {"YourApplicationNamespace\\": "src/"}
    }
}

تحدد في هذا القسم رابط التحميل التلقائي، يربط هذا المثال PSR-4 فضاء اسم إلى مجلد، يبقى المجلد ‎/src في المجلد الجذر لمشاريعك في نفس المستوى الموجود فيه المجلد ‎/vendor، يمكن أن يكون لديك اسم الملف src/Foo.php مثلًا والذي يحتوي على الصنف YourApplicationNamespace\Foo.

ملاحظة: بعد إضافة مداخل جديدة إلى قسم التحميل التلقائي يجب إعادة تنفيذ الأمر dump-autoload لإعادة توليد وتحديث الملف vendor/autoload.php بالمعلومات الجديدة.

يدعم المُنشئ التحميل التلقائي للمعيار PSR-0 وclassmap وfiles بالإضافة إلى PSR-4، يمكنك الاطلاع على مرجع التحميل التلقائي لمزيد من المعلومات.

عند تضمين الملف vendor/autoload.php ستُرجع نسخة من المحمِّل التلقائي للمُنشئ، يمكنك تخزين القيمة المُرجعة من استدعاء التضمين في متغير وإضافة المزيد من فضاءات الأسماء، يمكن أن يكون هذا مفيدًا في التحميل التلقائي للأصناف في مجموعة الاختبار، مثال:

$loader = require __DIR__ . '/vendor/autoload.php';
$loader->add('Application\\Test\\', __DIR__);

إنشاء ملفات PDF في PHP

مكتبة PDFlib

تتطلب الشيفرة التالية استخدام مكتبة PDFlib لتعمل بشكلٍ صحيح.

<?php
// تهيئة كائن جديد
$pdf = pdf_new();

// ‫إنشاء ملف pdf فارغ جديد
pdf_begin_document($pdf);?
    // ضبط معلومات الملف
    pdf_set_info($pdf, "Author", "John Doe");
    pdf_set_info($pdf, "Title", "HelloWorld");

    // تحديد طول وعرض الصفحة
    pdf_begin_page($pdf, (72 * 8.5), (72 * 11));

        // تحميل خط
        $font = pdf_findfont($pdf, "Times-Roman", "host", 0)
        // ضبط الخط
        pdf_setfont($pdf, $font, 48);

        // تعيين موضع النص
        pdf_set_text_pos($pdf, 50, 700);

        // طباعة النص إلى الموضع المحدد
        pdf_show($pdf, "Hello_World!");

    // نهاية الصفحة
    pdf_end_page($pdf);

// إغلاق الكائن
pdf_end_document($pdf);

// استعادة المحتويات من المخزن المؤقت
$document = pdf_get_buffer($pdf);

// ‫إيجاد طول ملف PDF وتعيين اسم للملف
$length = strlen($document); $filename = "HelloWorld.pdf";

header("Content-Type:application/pdf");
header("Content-Length:" . $length);
header("Content-Disposition:inline; filename=" . $filename);

// إرسال الملف إلى المتصفح
echo($document);

// مسح الذاكرة
unset($document); pdf_delete($pdf);
?>

مكتبة YAML

تثبيت الإضافة YAML

لا تأتي إضافة YAML مع تثبيت PHP القياسي، بل يجب تثبيتها كإضافة PECL، ويمكن القيام بذلك في لينوكس/يونكس ببساطة:

pecl install yaml

لاحظ أنّ الحزمة libyaml-dev يجب أن تكون مثبتة على النظام لأنّ حزمة PECL هي مجرد غلاف لاستدعاءات libYAML.

يختلف التثبيت على ويندوز، إذ يمكنك تحميل DLL المصرَّف مسبقًا أو بناؤه من المصدر.

استخدام YAML لتخزين إعدادات التطبيق

توفر مكتبة YAML طريقةً لتخزين البيانات المهيكلة، يمكن أن تكون البيانات مجموعة بسيطة من الأزواج اسم-قيمة أو بيانات هرمية معقدة مع قيم أو قد تكون مصفوفات.

بفرض لدينا ملف YAML التالي:

database:
    driver: mysql
    host: database.mydomain.com
    port: 3306
    db_name: sample_db
    user: myuser
    password: Passw0rd
debug: true
country: us

بفرض أننا حفظناه كملف config.yaml، لقراءة هذا الملف باستخدام PHP نستخدم الشيفرة التالية:

$config = yaml_parse_file('config.yaml');
print_r($config);

سينتج الخرج التالي:

Array
(
    [database] => Array
    (
        [driver] => mysql
        [host] => database.mydomain.com
        [port] => 3306
        [db_name] => sample_db
        [user] => myuser
        [password] => Passw0rd
    )
    [debug] => 1
    [country] => us
)

يمكن الآن استخدام معاملات الإعدادات ببساطة باستخدام عناصر المصفوفة:

$dbConfig = $config['database'];

$connectString = $dbConfig['driver']
    . ":host={$dbConfig['host']}"
    . ":port={$dbConfig['port']}"
    . ":dbname={$dbConfig['db_name']}"
    . ":user={$dbConfig['user']}"
    . ":password={$dbConfig['password']}";
$dbConnection = new \PDO($connectString, $dbConfig['user'], $dbConfig['password']);

ترجمة -وبتصرف- للفصول [ Autoloading Primer - Create PDF files in PHP - YAML in PHP‎] من كتاب PHP Notes for Professionals book

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...