Standar PSR-4 Autoloader PHP
PSR-4 Autoloader adalah standar yang ditetapkan oleh PHP-FIG (PHP Framework Interoperability Group) untuk mengatur cara pemuatan otomatis (autoloading) kelas-kelas PHP. PSR-4 adalah salah satu standar autoloading yang memungkinkan pemrograman PHP lebih efisien dengan mengurangi beban pengelolaan file secara manual dan memastikan struktur direktori yang konsisten untuk kelas-kelas yang ada.
Ada beberapa point penting yang menurut saya psr-4 ini merupakan standar autoloading yang lebih modern dan fleksibel dibandingkan dengan psr-0 yakni :
- Namespace dan Struktur Direktori
PSR-4 mengharuskan bahwa namespace yang ada pada sebuah kelas harus mencerminkan struktur direktori tempat kelas itu berada. Artinya, namespace pada kelas menjadi petunjuk untuk menemukan file kelas tersebut. - Mapping Namespace ke Direktori
PSR-4 menetapkan bahwa setiap namespace yang diawali dengan nama tertentu harus dipetakan ke sebuah direktori dalam sistem file. Sebagai contoh, namespace Acme\Library mungkin dipetakan ke direktori src/Acme/Library. - Konversi dari Namespace ke Nama File
Namespace dan nama kelas dikonversi menjadi nama file. Misalnya: Namespace Acme\Library Kelas Book Maka nama file yang terkait adalah src/Acme/Library/Book.php. - Tanpa Kode Manual untuk Mengimpor Kelas
Dengan PSR-4, autoloader akan otomatis mencari dan memuat file kelas sesuai dengan aturan yang sudah ditetapkan, sehingga Anda tidak perlu lagi menggunakan require atau include secara manual.
Contoh Implementasi PSR-4
Misalkan Anda memiliki struktur direktori sebagai berikut:
/src
/Acme
/Library
Book.phpDan kelas Book di dalam namespace Acme\Library:
<?php
// src/Acme/Library/Book.php
namespace Acme\Library;
class Book {
public function __construct() {
echo "This is a book!";
}
}Nah dengan autoloader maka file tersebut akan dipanggil secara otomatis ketika dibutuhkan (mis. oleh router). Dalam praktiknya saya sering kali menggunakan autoloader bersamaan dengan php router agar setiap module atau kode yang ada pada kelas - kelas bisa dialamatkan atau dipanggil menggunakan php router
Contoh lain misal saya punya direktori kerja seperti berikut
/app
/Autoloader
Psr4Autoloader.php
/Models
/Controllers
/Validate
/Helper
/views
/html1
main.phtml
/html2
main.phtml
/html3
main.phtml
Dengan autolder saya bisa memanggil file atau fungsi dari direktori Helper yang dibutuhkan oleh file main.phtml hanya dengan memanggil file tersebut dengan parameter seperti contoh berikut :
use Helper\Helper;
$app = new Helper;Contoh Autoloader Standar PSR-4
Setidaknya ada dua buah contoh yang kita implementasikan berdasarkan refrensi dari laman github https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md
1. Autoloader dengan spl_autoload_register
Di bawah ini adalah contoh implementasi fungsi autoload secara manual yang sesuai dengan standar PSR-4. Fungsi autoloader ini akan mencari dan memuat kelas-kelas berdasarkan namespace dan struktur direktori yang sesuai.
spl_autoload_register(function ($class) {
// Prefix namespace proyek yang digunakan
$prefix = 'Foo\\Bar\\';
// Direktori dasar untuk prefix namespace
$base_dir = __DIR__ . '/src/';
// Mengecek apakah kelas menggunakan prefix namespace yang sesuai
$len = strlen($prefix);
if (strncmp($prefix, $class, $len) !== 0) {
// Jika tidak, lanjutkan ke autoloader lainnya
return;
}
// Ambil nama kelas relatif (setelah prefix namespace)
$relative_class = substr($class, $len);
// Ganti prefix namespace dengan direktori dasar dan ganti separator namespace menjadi separator direktori
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
// Jika file ditemukan, muat file tersebut
if (file_exists($file)) {
require $file;
}
});
Keterangan:
- Fungsi spl_autoload_register mendaftarkan fungsi untuk mencari dan memuat file kelas secara otomatis.
- Autoloader akan mencari kelas dengan namespace yang diawali dengan Foo\Bar\ dan mencari file yang sesuai di direktori /src/.
- Jika ditemukan, file kelas tersebut akan dimuat menggunakan require.
Contoh implemntasi
new \Foo\Bar\Baz\Qux; // Mencari file /src/Baz/Qux.php2. Autoloader multiple namespace
Di bawah ini adalah contoh implementasi autoloader yang lebih kompleks, yang mendukung banyak direktori untuk satu prefix namespace. Ini memungkinkan Anda untuk mengatur beberapa direktori untuk satu namespace.
namespace Example;
class Psr4AutoloaderClass
{
protected $prefixes = array();
// Mendaftarkan autoloader
public function register()
{
spl_autoload_register(array($this, 'loadClass'));
}
// Menambahkan direktori dasar untuk namespace tertentu
public function addNamespace($prefix, $base_dir, $prepend = false)
{
$prefix = trim($prefix, '\\') . '\\'; // Normalisasi prefix
$base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/'; // Normalisasi direktori dasar
if (!isset($this->prefixes[$prefix])) {
$this->prefixes[$prefix] = array();
}
if ($prepend) {
array_unshift($this->prefixes[$prefix], $base_dir);
} else {
array_push($this->prefixes[$prefix], $base_dir);
}
}
// Memuat kelas berdasarkan namespace
public function loadClass($class)
{
$prefix = $class;
// Menelusuri namespace untuk menemukan file yang sesuai
while (false !== $pos = strrpos($prefix, '\\')) {
$prefix = substr($class, 0, $pos + 1);
$relative_class = substr($class, $pos + 1);
// Coba memuat file yang sudah dipetakan
$mapped_file = $this->loadMappedFile($prefix, $relative_class);
if ($mapped_file) {
return $mapped_file;
}
// Menghapus separator namespace untuk iterasi berikutnya
$prefix = rtrim($prefix, '\\');
}
// Jika tidak ditemukan, kembalikan false
return false;
}
// Memuat file yang dipetakan berdasarkan prefix namespace dan nama kelas relatif
protected function loadMappedFile($prefix, $relative_class)
{
if (!isset($this->prefixes[$prefix])) {
return false;
}
// Mencari file di direktori basis namespace
foreach ($this->prefixes[$prefix] as $base_dir) {
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
if ($this->requireFile($file)) {
return $file;
}
}
return false;
}
// Memeriksa apakah file ada, dan jika ada, memuatnya
protected function requireFile($file)
{
if (file_exists($file)) {
require $file;
return true;
}
return false;
}
}
Keterangan:
- addNamespace(): Menambahkan direktori dasar untuk namespace tertentu. Dapat menambahkan beberapa direktori untuk satu namespace.
- loadClass(): Fungsi ini berfungsi untuk menelusuri namespace dan mencoba memuat kelas yang sesuai dari direktori yang telah ditambahkan.
- loadMappedFile(): Memetakan namespace dan nama kelas ke file yang sesuai dalam direktori dasar yang ditambahkan sebelumnya.
- requireFile(): Mengecek apakah file kelas ada dan jika ada, akan dimuat menggunakan require.
Contoh implemnetasi :
$loader = new \Example\Psr4AutoloaderClass;
$loader->register();
// Menambahkan beberapa direktori untuk namespace Foo\Bar
$loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src');
$loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/tests');
// Mencoba memuat kelas
new \Foo\Bar\Qux\Quux; // Memuat dari /path/to/packages/foo-bar/src/Qux/Quux.php
new \Foo\Bar\Qux\QuuxTest; // Memuat dari /path/to/packages/foo-bar/tests/Qux/QuuxTest.php
Penjelasan Umum
- PSR-4 memungkinkan Anda untuk memetakan namespace ke struktur direktori. Setiap bagian namespace yang dipisahkan oleh tanda \ akan diterjemahkan menjadi subdirektori.
- Autoloader ini secara otomatis mencari dan memuat file kelas sesuai dengan namespace yang digunakan tanpa perlu menyertakan file secara manual.
- Anda bisa mengonfigurasi autoloader untuk mencari kelas di berbagai direktori yang berbeda.
Kesimpulan
Implementasi PSR-4 autoloading di PHP sangat bermanfaat dalam mengelola file-file kelas secara otomatis dan terstruktur. Dengan menggunakan Composer atau implementasi manual seperti di atas, Anda dapat memastikan bahwa kelas-kelas PHP dimuat secara efisien, sesuai dengan standar yang ada, dan menghindari penggunaan require atau include secara manual di setiap file.