Selamat datang di Part 75 dari seri tutorial Tutorial Pemrograman! Di part ini, kita akan mempelajari cara membangun sistem plugin sederhana menggunakan PHP. Sistem plugin memungkinkan kita untuk memperluas fungsionalitas aplikasi tanpa mengubah kode inti. Ini sangat berguna untuk membuat aplikasi yang modular dan mudah dikelola.
Prasyarat:
Bayangkan sebuah toko aplikasi (app store). Aplikasi inti adalah kerangka dasar, dan plugin adalah aplikasi tambahan yang dapat diinstal untuk menambahkan fitur baru. Sistem plugin di PHP bekerja dengan cara yang mirip: aplikasi inti menyediakan titik ekstensi (biasanya interface atau abstract class), dan plugin mengimplementasikan atau memperluas titik ekstensi tersebut.
Mari kita buat sebuah interface sederhana sebagai titik ekstensi. Interface ini akan mendefinisikan sebuah metode yang harus diimplementasikan oleh setiap plugin.
namespace MyApp\Plugin;
interface PluginInterface {
public function execute(): string;
}
Kode di atas mendefinisikan sebuah interface bernama PluginInterface di namespace MyApp\Plugin. Interface ini memiliki satu metode, yaitu execute(), yang harus mengembalikan string.
Sekarang, mari kita buat dua contoh plugin yang mengimplementasikan interface PluginInterface.
namespace MyApp\Plugin;
class HelloPlugin implements PluginInterface {
public function execute(): string {
return "Hello from HelloPlugin!";
}
}
namespace MyApp\Plugin;
class GoodbyePlugin implements PluginInterface {
public function execute(): string {
return "Goodbye from GoodbyePlugin!";
}
}
Kedua kelas di atas, HelloPlugin dan GoodbyePlugin, mengimplementasikan interface PluginInterface. Masing-masing kelas mengembalikan string yang berbeda saat metode execute() dipanggil.
Selanjutnya, kita akan membuat kelas PluginManager yang bertanggung jawab untuk menemukan dan memuat plugin.
namespace MyApp;
use MyApp\Plugin\PluginInterface;
use ReflectionClass;
class PluginManager {
private array $plugins = [];
public function __construct(array $pluginPaths) {
foreach ($pluginPaths as $pluginPath) {
$this->loadPlugins($pluginPath);
}
}
private function loadPlugins(string $pluginPath): void {
$files = glob($pluginPath . '/*.php');
foreach ($files as $file) {
require_once $file;
$className = $this->getClassNameFromFile($file);
if ($className) {
$reflection = new ReflectionClass($className);
if (!$reflection->isInterface() && !$reflection->isAbstract() && $reflection->implementsInterface(PluginInterface::class)) {
$this->plugins[] = $reflection->newInstance();
}
}
}
}
private function getClassNameFromFile(string $filePath): ?string {
$php_code = file_get_contents($filePath);
$tokens = token_get_all($php_code);
$namespace = '';
$class = '';
$i = 0;
while ($i < count($tokens)) {
if ($tokens[$i][0] == T_NAMESPACE) {
$i += 2; // Skip namespace keyword and whitespace
while ($tokens[$i][0] == T_STRING || $tokens[$i][0] == T_NS_SEPARATOR) {
$namespace .= $tokens[$i][1];
$i++;
}
} elseif ($tokens[$i][0] == T_CLASS) {
$i += 2; // Skip class keyword and whitespace
if ($tokens[$i][0] == T_STRING) {
$class = $tokens[$i][1];
break;
}
}
$i++;
}
if ($class !== '') {
if ($namespace !== '') {
return $namespace . '\\' . $class;
} else {
return $class;
}
}
return null;
}
public function getPlugins(): array {
return $this->plugins;
}
}
Kode ini melakukan beberapa hal:
loadPlugins memuat semua file PHP dalam direktori yang diberikan dan mencoba untuk instantiate kelas yang mengimplementasikan PluginInterface.getClassNameFromFile menggunakan tokenisasi untuk mengekstrak nama class dari file PHP.getPlugins mengembalikan array dari semua plugin yang di-load.Terakhir, mari kita lihat cara menggunakan sistem plugin yang telah kita buat.
require_once 'vendor/autoload.php'; // Asumsi menggunakan Composer
use MyApp\Plugin\HelloPlugin;
use MyApp\Plugin\GoodbyePlugin;
use MyApp\Plugin\PluginInterface;
use MyApp\PluginManager;
// Direktori tempat plugin berada.
$pluginPaths = [__DIR__ . '/plugins'];
// Membuat instance PluginManager, yang secara otomatis akan memuat plugin.
$pluginManager = new PluginManager($pluginPaths);
// Mendapatkan daftar plugin yang dimuat.
$plugins = $pluginManager->getPlugins();
// Iterasi melalui plugin dan mengeksekusi masing-masing plugin.
foreach ($plugins as $plugin) {
if ($plugin instanceof PluginInterface) {
echo $plugin->execute() . "\n";
}
}
Pastikan struktur folder Anda memiliki folder `plugins` di root proyek Anda, dan di dalam folder `plugins` tersebut, Anda memiliki file PHP yang berisi definisi class plugin Anda (HelloPlugin.php dan GoodbyePlugin.php).
Coba tambahkan fitur konfigurasi ke sistem plugin kita. Buat file konfigurasi (misalnya, `config.php` atau `plugins.json`) yang menentukan plugin mana yang akan dimuat. Modifikasi PluginManager untuk membaca file konfigurasi ini dan hanya memuat plugin yang terdaftar di dalamnya.