Memahami Reflection Class pada PHP

Khairu Aqsara Sudirman

Khairu Aqsara Sudirman

Mar 18, 2020 — 6 mins read

dari arti-nya saja teman-teman mungkin sudah bisa menebak maksudnya, ya sederhananya dalam bahasa indonesia refleksi, tetapi dalam dunia pemrograman refleksi ini bisa kita sebut sebagai kemampuan sebuah program untuk mengidentifikasi dirinya sendiri, maksudnya dengan adanya fitur ini sebuah class dapat melihat method dan property apa saja yang dimilikinya.

Sebelum kita beranjak lebih jauh tentang ReflectionClass pada php, ada baiknya kita memahami dulu konsep Class dan Object function, karana sekilas mungkin Reflection tidak ada perbedaanya.

ada beberapa contoh dari Object function yang sering digunakan, misalnya get_class untuk mengambil nama class, get_class_method untuk mengambil semua method yang ada dan get_parent_class untuk mengambil parent class dari sebuah object, sebenarnya masih banyak sekali contoh dari Object function yang bisa kita gunakan, kalo dibahas semua bisa keriting tangan dan rambut :)

untuk lebih memperjelas tentang Object function ini mari kita mengimplementasikan-nya dalam bentuk yang sederhana.Kita akan membuat dua buah class dengan nama Siswa dan Sekolah.

#kode program untuk Sekolah.php
class Sekolah {
	private $nama_sekolah;
	public function __construct($nama_sekolah){
		$this->nama_sekolah = $nama_sekolah;
	}
	public function nama_sekolah(){
		return $this->nama_sekolah;
	}
}

kode program untuk Siswa.php

include "Sekolah.php";
class Siswa extends Sekolah{
	private $nama_siswa;
	public function __construct($nama_sekolah, $nama_siswa){
		$this->nama_siswa = $nama_siswa;
		parent::__construct($nama_sekolah);
	}
	public function nama_siswa(){
		return $this->nama_siswa;
	}
}

untuk melihat hasilnya kita gunakan script berikut

include("Siswa.php");
$siswa = new Siswa("SMP N 1","Kurosaki Ichigo");
echo $siswa->nama_siswa() ." Bersekolah Di ". $siswa->nama_sekolah() ."\n";

Terus yang kita bahas apa? bukanya itu OOP seperti biasanya ? ya memang bener, sabar dulu sob.... perjalanan masih jauh :)

sebelumnya kan kita sudah membahas tentang Object Function, nah sekarang kita coba menggunakan nya, jika script diatas kita modifikasi dan menambahkan Object Function get_class() pada inisialiasi sebuah class, maka kita akan mendapatkan hasil nama dari Class tersebut

echo 'Class dari $siswa Adalah : '.get_class($siswa).''

sekarang kita coba menggunakan Object function get_class_methods(), return dari get_class_methods() adalah array, jadi kita menggunakan print_r() untuk mencetak hasilnya.

echo "Method dari Class ".get_class($siswa)." Adalah :\n";
print_r(get_class_methods($siswa)); 

satu lagi biar lengkap, kita coba menggunakan get_parent_class()

echo "Parent Class ".get_class($siswa)." Adalah : ".get_parent_class($siswa)."\n";

hm... terus manfaatnya apa bang...? hm... tenang coy perjalanan masih panjang, nikmatin aja dulu :)

Fitur Reflection akan sangat bermanfaat ketika kita membutuhkan informasi tentang struktur dan cara kerja dari sebuah class yang akan kita gunakan, terkadang banyak class-class yang tidak ada dokumentasinya, istilah kerenya reverse enginering lah, satu teknik yang digunakan untuk mempelajari cara kerja sebuah proses.

secara garis besarnya, Reflection dikelompokan dalam beberapa class, yang paling umum digunakan yaitu ReflectionClass() yang digunakan untuk mengidentifikasi class, ReflectionMethod() yang digunakan untuk mengidentifikasi method, ReflectionObject() untuk mengidentifikasi object, ReflectionParameter() untuk mengidentifikasi parameter pada method dan ReflectionProperty() untuk mengidentifikasi property.

untuk lebih jelasnya, mari kita coba saja pengimplementasianya, kita akan membuat sebuah class dengan nama Merek.php dimana nanti class Merek akan Digunakan dibeberapa class lainya.

#Merek.php
class Merek {
	private $nama;
	private $tahun;
	public function __construct($nama="Blank",$tahun="Tidak Diketahui"){
		$this->nama = $nama;
		$this->tahun = $tahun;
	}
	public function nama(){
		return $this->nama;
	}
	public function tahun(){
		return $this->tahun;		
	}
}

Script diatas membuat sebuah class Merek dengan dua property $nama dan $tahun, kita juga membuat dua method getter nama() dan tahun(), dan pada __constructor() terdapat 2 parameter $nama dan $tahun dengan nilai default masing-masing. Sekarang kita akan membuat class baru dengan nama Mobil.php

abstract class Kendaraan {}
interface bisadijual {}
interface bisaditukar {}
class Mobil extends Kendaraan implements bisadijual,bisaditukar {
	private $kondisi;
	private $merek;
	public function __construct($kondisi="Baik", Merek $merek){
		$this->kondisi = $kondisi;
		$this->merek = $merek;
	}	
	public function __toString(){
		return "Kondisi  : ".$this->kondisi."\n"
			  ."Merek : ".$this->merek->nama()."\n"
			  ."Tahun : ".$this->merek->tahun()."\n";
	}
}

Jangan bingung dulu lihat scriptnya, memang agak panjang tetapi pastinya teman-teman sudah mulai terbayangkan kapan dan dimana pernah pake model kode yang seperti itu ?, mari kita lihat satu persatu penjelasanya.

Class Mobil merupakan turuan dari class Kendaraan, class ini juga mengimplementasikan interface bisadijual dan bisaditukar, class Mobil juga punya dua parameter $kondisi dan satunya lagi $merek merupakan DI (Dependcy Injcetion) dari class Merek, kemudian ada magic method __toString() yang akan kita gunakan sebagai pengganti echo atau print pada class Merek, sekarang mari kita coba jalankan.

include_once("Merek.php");
include_once("Mobil.php");
$honda = new Merek("Honda",2015);
$mobil = new Mobil("Sangat Mulus", $honda);
echo $mobil;

Class diatas merupakan class sederhana, bayangkan saja jika classnya ratusan interfacenya juga puluhan belum lagi property dan method yang bahkan sampe ribun, apa teman-teman mau menelusurinya ? 

oleh karena masalah itulah kita terkadang membutuhkan ReflectionClass, dengan adanya ReflectionClass kita jadi lebih mudah menelusurinya, misalnya kita coba modifikasi script sebelumnya dengan merubah echo $mobil menjadi seperti berikut

echo $reflector->getName(). "\n";
echo $reflector->getParentClass()->getName(). "\n";
var_dump($reflector->getMethods());

mari kita coba bebera fungsi lagi

var_dump($reflector->getInterfaceNames());
$constructor = $reflector->getConstructor();
var_dump($constructor->getParameters());

terlihat disini kita bisa mengidentifikasi elemen-elemen yang ada pada class dengan menggunakan ReflectorClass, bukan hanya itu saja, ReflectorClass juga bisa kita gunakan untuk hal yang lainya, misalnya seperti Automatic resolution atau kalo yang sering kerja dengan laravel pasti sudah tidak asing dengan istilah Automatic Resolution, Service Container dan Depedency Injection, Jika ada waktu nanti kita akan mencoba membahas Service Container pada Laravel, untuk sekarang mari kita memanfaatkan ReflectionClass ini menjadi Automatic Resolution Sederhana.

Cara kerja Automatic Resolution adalah dengan Menginjectkan parameter yang dibutuhkan pada method __construct(), seperti script sebelumnya, secara otomatis jika dibutuhkan maka ia akan membuat atau menginisialisasikan object tersebut.

sebelumnya kita sudah membuat class sederhana bukan ? class Merek dan Class Mobil, Sekarang mari kita jalankan kembali script tersebut tanpa memberikan parameter pada class Merek.

include_once("Merek.php");
include_once("Mobil.php");
$honda = new Merek();
$mobil = new Mobil("Tidak Tau", $honda);
echo $mobil;

Dari gambar diatas kita bisa melihat hasilnya, pada class Merek, walaupun kita tidak memberikan parameter, class Merek akan menggunakan nilai defaultnya, tetapi yang perlu diperhatikan adalah disini kita melakukan inject manual class Merek kedalam class Mobil.Sekarang mari kita terapkan Automatic Resolution nya dengan membuat sebuah class baru dengan nama Agen.

class Agen {
	public static function make($class){
		$reflector = new ReflectionClass($class);
		$constructor = $reflector->getConstructor();
		if (is_null($constructor)){
			return new $class;
		}
		$dep = $constructor->getParameters();
		$param = [];
		foreach($dep as $d){
			if(is_null($d->getClass())){
				array_push($param, $d->getDefaultValue());
			}else{
				array_push($param, self::make($d->getClass()->name));
			}
		}
		return $reflector->newInstanceArgs($param);
	}	
}

Kode diatas bisa dikatakan sebagai Service Container Sederhana, jika kita perhatikan hanya terdapat satu method yaitu make() dengan parameter $class, parameter ini nantinya akan dianggap sebagai sebuah class dan dibuatkan ReflectionClass() nya, kemudian dari ReflectionClass() jika $reflector tidak didapatkan secara otomatis maka $class menjadi instance dari sebuah $class itu sendiri.Secara sederhana class Agen diatas membuat object class baru berdasarkan ReflectorClass, mari kita coba jalankan.

include_once("Merek.php");
include_once("Mobil.php");
include_once("Agen.php");
$mobil = Agen::make("Mobil");
echo $mobil;

terlihat hasilnya kan, dengan Automatic Resolution kita tidak perlu lagi membuat object dari class Mobil, kita juga tau class Mobil menggunakan Class Merek, tetapi kita sama sekali tidan membuat kedua Object dari kedua class tersebut, karena dengan adanya Class Agen yang bertindak sebagai Service Container sederhana yang menerapkan konsep Autmatic Resolution.

Saya yakin teman-teman sudah mulai mengingat kapan dan dimana pernah menggunakan model kode yang mirip-mirip seperti diatas, tentunya akan sangat banyak kita temukan pada framework laravel.

terkadang pengetahuan dasar dari bahasa pemrograman itu sangat penting ketika kita mulai beranjak menggunakan framework dari bahasa pemrograman itu sendiri, tanpa memahami arsitektur dari framework yang kita gunakan kita sering dihadapkan dengan masalah yang sebenarnya cukup simple penyelesaianya tetapi menjadi sungguh luar bisa ribet saat dikerjakan.


laravel php
You might enjoy

REST API Unit Testing Pada Laravel

Pasti teman-teman sudah tidak asing dengan dengan istilah REST API, bahkan mungkin sudah sangat sering menggunakannya maupun membuatnya, Tap...