Apa itu Autoloading; Bagaimana Anda menggunakan spl_autoload, __autoload dan spl_autoload_register?

204

Saya belajar standar PHP lanjutan dan mencoba menerapkan metode baru dan berguna. Sebelumnya saya menggunakan __autoloadhanya untuk melarikan diri termasuk beberapa file pada setiap halaman, tetapi baru-baru ini saya telah melihat tip__autoload manual

spl_autoload_register () memberikan alternatif yang lebih fleksibel untuk kelas autoloading. Karena alasan ini, menggunakan __autoload () tidak disarankan dan mungkin tidak digunakan lagi atau dihapus di masa mendatang.

tapi saya benar-benar tidak tahu cara mengimplementasikan spl_autoloaddanspl_autoload_register

diEcho
sumber

Jawaban:

335

spl_autoload_register() memungkinkan Anda untuk mendaftarkan banyak fungsi (atau metode statis dari kelas Autoload Anda sendiri) yang akan dimasukkan PHP ke dalam tumpukan / antrian dan memanggil secara berurutan ketika "Kelas baru" dideklarasikan.

Jadi misalnya:

spl_autoload_register('myAutoloader');

function myAutoloader($className)
{
    $path = '/path/to/class/';

    include $path.$className.'.php';
}

//-------------------------------------

$myClass = new MyClass();

Pada contoh di atas, "MyClass" adalah nama kelas yang Anda coba instantiate, PHP meneruskan nama ini sebagai string spl_autoload_register(), yang memungkinkan Anda untuk mengambil variabel dan menggunakannya untuk "memasukkan" kelas / file yang sesuai . Akibatnya Anda tidak perlu secara khusus menyertakan kelas itu melalui pernyataan sertakan / memerlukan ...

Cukup panggil saja kelas yang ingin Anda instantiate seperti pada contoh di atas, dan karena Anda mendaftarkan fungsi (via spl_autoload_register()) Anda sendiri yang akan mencari tahu di mana semua kelas Anda berada, PHP akan menggunakan fungsi itu.

Manfaat menggunakan spl_autoload_register()adalah tidak seperti __autoload()Anda tidak perlu menerapkan fungsi pengisian otomatis di setiap file yang Anda buat. spl_autoload_register()Anda juga dapat mendaftarkan beberapa fungsi pengisian otomatis untuk mempercepat autoloading dan membuatnya lebih mudah.

Contoh:

spl_autoload_register('MyAutoloader::ClassLoader');
spl_autoload_register('MyAutoloader::LibraryLoader');
spl_autoload_register('MyAutoloader::HelperLoader');
spl_autoload_register('MyAutoloader::DatabaseLoader');

class MyAutoloader
{
    public static function ClassLoader($className)
    {
         //your loading logic here
    }


    public static function LibraryLoader($className)
    {
         //your loading logic here
    }

Sehubungan dengan spl_autoload , manual menyatakan:

Fungsi ini dimaksudkan untuk digunakan sebagai implementasi standar untuk __autoload(). Jika tidak ada yang ditentukan dan spl_autoload_register()dipanggil tanpa parameter apa pun maka fungsi ini akan digunakan untuk panggilan selanjutnya __autoload().

Dalam istilah yang lebih praktis, jika semua file Anda berada dalam satu direktori dan aplikasi Anda tidak hanya menggunakan file .php, tetapi file konfigurasi khusus dengan ekstensi .inc misalnya, maka salah satu strategi yang dapat Anda gunakan adalah menambahkan direktori Anda yang berisi semua file ke jalur sertakan PHP (via set_include_path()).
Dan karena Anda juga memerlukan file konfigurasi, Anda akan gunakan spl_autoload_extensions()untuk membuat daftar ekstensi yang Anda inginkan dari PHP.

Contoh:

set_include_path(get_include_path().PATH_SEPARATOR.'path/to/my/directory/');
spl_autoload_extensions('.php, .inc');
spl_autoload_register();

Karena spl_autoload adalah implementasi default __autoload()metode sulap, PHP akan memanggil spl_autoload ketika Anda mencoba dan membuat instance kelas baru.

Semoga ini membantu...

Brownbay
sumber
35
Ini mungkin salah satu jawaban terbaik dalam sejarah jawaban yang pernah ada. Menghormati. Saya memiliki salah satu dari "OMG! Semuanya masuk akal sekarang!" saat karena Anda, pria baik saya. Saya pikir saya mungkin baru saja memulai sebuah klub penggemar.
Just Plain High
2
Untuk menjadikan ini jawaban terbaik dari semua jawaban yang pernah ada di alam semesta alternatif, harap tambahkan spl_autoload sangat, um, "sangat membantu" (?) Mengonversi semua nama file menjadi huruf kecil (lihat komentar saya ke @user di bawah). Tidak dapat menggunakan vanilla spl_autoload_register () jika Anda suka CapitalLettersAndStuff Anda.
Just Plain High
6
@Just Plain High Saya tidak mengalami masalah itu dan semua file kelas saya adalah camelcased. BTW, ini jawaban yang bagus. Ini membantu saya memahami konsep sederhana yang tidak dapat saya mengerti sampai saya membaca posting ini! Baris 85 (dan terus bertambah) saya termasuk file yang mencakup semua file kelas saya sekarang 7 baris!
kyle
2
Ini memang jawaban yang bagus tapi saya kehilangan satu hal. Apa fungsi default aktual? Dengan kelas yang saya tahu, ia menggunakan namespace sebagai jalur dan nama kelas sebagai nama file. Meskipun saya tidak tahu cara kerjanya dengan fungsi.
SiXoS
2
Bukankah salah satu manfaat besar untuk menggunakan spl_autoload_register()(dan __autoload()secara umum) bahwa itu memuat malas termasuk file / kelas? Ini tersirat oleh jawabannya, tetapi tidak secara eksplisit dinyatakan. Bagi saya, ini adalah informasi penting yang sempurna untuk dimasukkan dalam jawaban Anda! :)
rinogo
13

Sejak PHP 5.3, Anda dapat menggunakan spl_autoload_register()namespaces, yang berarti bahwa Anda dapat mengatur proyek Anda dan secara otomatis memuat kelas php Anda tanpa perlu atau menyertakan dan tanpa mendefinisikan ulang suatu __autoload()fungsi.

Untuk menunjukkan perilaku ini, cukup buat file bernama index.php:

<?php
spl_autoload_register();
var_dump(new Main\Application);

Kemudian buat folder bernama Main yang terletak tepat di sebelah file index.php. Terakhir, buat file bernama Application.php yang terletak di Main dan tempel kode berikut ke dalamnya:

<?php namespace Main;
class Application{}
pengguna1974206
sumber
9
Sebuah catatan dari mengutak-atik saya dengan semua ini: spl_autoload () - dan dengan demikian spl_autoload_register () - mengubah nama file menjadi huruf kecil (meskipun ada laporan bug, permohonan dan pemungutan suara marah). Ini berarti Anda mungkin mencari "Main \ Application" tetapi spl_autoload mencari "main \ application". Jika Anda suka unta, seperti saya, Anda harus menulis fungsi Anda sendiri. Ada contoh pemula yang bagus di sini: github.com/ircmaxell/PHP-CryptLib/blob/…
Just Plain High
1
Kelebihan: spl_autoload_register () adalah metode tercepat autoloading Kontra: ini akan bekerja hanya dengan file / kelas huruf kecil, dan ruang nama juga, yang pada hari ini dan usia hanya sux waktu besar (tidak ada pilihan untuk mengatakannya menggunakan CamelCase dll). Tetapi jika Anda dapat hidup dengan struktur namespace / classname.php, jangan mencari lebih jauh.
stamster
1
spl_autoload_register()implementasi default tidak dapat menemukan kelas yang diwariskan. Jadi menggunakan default, file huruf kecil dan direktori yang mencerminkan jalur namespace, semuanya berfungsi dengan baik kecuali saya memiliki kelas yang memperluas kelas lain (induk). PHP kemudian melempar kesalahan yang tidak dapat menemukan kelas induk itu, bahkan mereka semua berada di direktori / namespace yang sama! Yang membingungkan adalah bahwa secara harfiah hanya kelas tingkat pertama yang ditemukan, jadi saya harus meletakkan yang lain spl_autoload_register()dengan aturan fungsi anonim tepat setelah yang pertama agar secara manual menyertakan orang tua yang hilang / kelas yang diwarisi.
stamster
1

Inilah cara saya menggunakan Autoload. Dalam contoh yang diberikan saya ingin memuat kelas membentuk 3 direktori yang berbeda.

function namespaceAutoload($rawClass){

$class = str_replace('\\', DIRECTORY_SEPARATOR, $rawClass);

$possiblePaths[] = '..\sys\class\file.php';
$possiblePaths[] = '..\sys\class\lib\file.php';
$possiblePaths[] = '..\sys\class\class.file.inc.php';

foreach ($possiblePaths as $templatePath) {
    $path = str_replace(["\\", "file"], [DIRECTORY_SEPARATOR, $class], $templatePath);
    if (file_exists($path)) {
        require_once "$path";
        break;
    }
} spl_autoload_register("namespaceAutoload"); 

Saya contoh yang diberikan, PHP akan mencari kelas namespace \ di tiga direktori ini menggunakan tiga format nama file yang berbeda.

Augusto Santana
sumber