Sihirli Yöntemler
__construct(),
__destruct(),
__call(),
__callStatic(),
__get(),
__set(),
__isset(),
__unset(),
__sleep(),
__wakeup(),
__serialize(),
__unserialize(),
__toString(),
__invoke(),
__set_state(),
__clone() ve
__debugInfo()
işlev isimleri PHP
sınıflarında sihirli işlemler yaparlar. İşlevlerinize sihirli bir
işlevsellik kazandırmak istemedikçe bu isimleri sınıfınızın içinde işlev
ismi olarak kullanamazsınız.
Bilginize:
Tüm sihirli yöntemler KESİNLİKLE
public
olarak bildirilmelidir.
Dikkat
PHP, __
ile baslayan tüm işlev isimlerini sihirli
işlevlere ayırmıştır. Belgelenmiş bir kaç sihirli işlevsellik dışında
__
ile başlayan işlev isimleri kullanmamanızı öneririz.
public
__sleep
(
): array
public
__wakeup
(
): void
serialize() işlevi, sınıfın
__sleep()
adında sihirli bir işleve sahip olup olmadığına bakar. Böyle bir işlev
varsa herhangi bir dizileştirme işleminden önce bu işlev çalıştırılır.
Bu işlev ile nesne üzerinde temizlik yapabilir ve dizileştirilmesi
gereken nesnenin tüm değişken isimlerinin bir dizi halinde döndürülmesini
sağlayabilirsiniz. Eğer işlev hiçbir şey döndürmemişse null
dizileştirilir ve bir E_NOTICE
çıktılanır.
Bilginize:
Ebeveyn sınıflardaki private özelliklerin isimlerini döndürmek
__sleep() için imkansızdır. Bunu
yapmaya kalkışırsanız E_NOTICE
seviyesinde bir hata
iletisi alırsınız. Bunun yerine Serializable
arayüzünü kullanabilirsiniz.
__sleep() işlevinin asıl kullanım
amacı askıdaki veriyi göndermek gibi temizliğe benzer işlemler yapmaktır.
Ayrıca, tümüyle kaydedilmesi gerekmeyen büyük veri parçaları sözkonusu
olduğunda da bu işlevden yararlanabilirsiniz.
unserialize() işlevi tersine bir işlem yaparak
__wakeup() adında bir sihirli
işlevin varlığını araştırır.
Böyle bir işlev varsa, bu işlev nesnenin sahip olduğu tüm özkaynakları
yeniden oluşturabilir.
__wakeup() işlevinin asıl kullanım
amacı, dizileştirme sırasında kaybedilebilen veritabanı bağlantılarını
yeniden oluşturmak ve diğer ilklendirme işlemlerini yeniden yapmaktır.
Örnek 1 - Uyutma ve uyandırma
<?php
class Bağlantı
{
protected $hat;
private $dsn, $kullanıcı, $parola, $db;
public function __construct($dsn, $kullanıcı, $parola, $db)
{
$this->dsn = $dsn;
$this->kullanıcı = $kullanıcı;
$this->parola = $parola;
$this->db = $db;
$this->connect();
}
private function bağlan()
{
$this->hat = new PDO($this->dsn, $this->kullanıcı, $this->parola);
}
public function __sleep()
{
return array('dsn', 'kullanıcı', 'parola');
}
public function __wakeup()
{
$this->bağlan();
}
}?>
public __serialize
(
): array
public __unserialize
(array $data
): void
serialize() işlevi, sınıfın
__serialize() sihirli adına
sahip bir işlevinin olup olmadığına bakar. Varsa, bu işlev herhangi
bir dizileştirmeden önce çalıştırılır. Nesnenin dizileştirilmiş biçimini
temsil eden ilişkisel bir anahtar/değer çiftleri dizisi oluşturmalı ve
döndürmelidir. Hiçbir dizi döndürülmezse, bir
TypeError yavrulanır.
Bilginize:
Aynı nesnede hem __serialize()
hem de __sleep() tanımlanmışsa,
sadece __serialize()
çağrılır. __sleep() ise yok
sayılır. Nesne Serializable
arayüzünü gerçekliyorsa, arayüzün serialize()
yöntemi
yok sayılır ve yerine __serialize()
kullanılır.
__serialize() yönteminin
amaçlanan kullanımı, nesnenin dizileştirmeye uygun keyfi bir gösterimini
tanımlamaktır. Dizinin öğeleri, nesnenin özelliklerine karşılık gelebilir,
ancak bu gerekli değildir.
unserialize() işlevi ise tersine sınıfın
__unserialize() sihirli adına
sahip bir işlevinin olup olmadığına bakar. Varsa, bu işlev
__serialize() işlevinden
döndürülen geri yüklenmiş diziye aktarılır. Daha sonra nesnenin
özelliklerini uygun şekilde bu diziden geri yükleyebilir.
Bilginize:
Aynı nesnede hem __unserialize()
hem de __wakeup() tanımlanmışsa,
yalnızca __unserialize()
çağrılır. __wakeup() ise yok sayılır.
Bilginize:
Özellik PHP 7.4.0'dan beri kullanılabilmektedir.
Örnek 2 - Dizileştirme ve Nesneleştirme
<?php
class Connection
{
protected $link;
private $dsn, $username, $password;
public function __construct($dsn, $username, $password)
{
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->connect();
}
private function connect()
{
$this->link = new PDO($this->dsn, $this->username, $this->password);
}
public function __serialize(): array
{
return [
'dsn' => $this->dsn,
'user' => $this->username,
'pass' => $this->password,
];
}
public function __unserialize(array $data): void
{
$this->dsn = $data['dsn'];
$this->username = $data['user'];
$this->password = $data['pass'];
$this->connect();
}
}?>
public
__toString
(
): string
__toString() yöntemi, sınıf bir
dizgeye dönüştürüldüğünde sınıfın nasıl tepki vereceğine karar vermeyi
sağlar. Bu yöntem bir dizge döndürmelidir, aksi takdirde
E_RECOVERABLE_ERROR
seviyesinde ölümcül bir hata
çıktılanır.
Uyarı
__toString() yöntemin içinden
bir istisna yavrulatılamaz. Bunun yapılması ölümcül hata ile
sonuçlanır.
Örnek 3 - Basit bir örnek
<?php
// Basit bir sınıf tanımlayalım
class TestClass
{
public $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
public function __toString()
{
return $this->foo;
}
}
$class = new TestClass('Merhaba');
echo $class;
?>
Yukarıdaki örneğin çıktısı:
__invoke
(
...$values
):
mixed
__invoke() yöntemi, bir betik bir
nesneyi bir işlev olarak çağırmaya çalışırsa çağrılır.
Örnek 4 - __invoke() kullanımı
<?php
class CallableClass
{
public function __invoke($x)
{
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>
Yukarıdaki örneğin çıktısı:
static
__set_state
(array $özellikler
): object
Bu statik yöntem,
var_export() tarafından ihraç edilen
sınıflar için çağrılır.
Bu yöntemin tek değiştirgesi array('
özellik' =>
değer,
...)
biçeminde ihraç edilen özellikleri içeren bir dizidir.
Örnek 5 - __set_state() kullanımı
<?php
class A
{
public $var1;
public $var2;
public static function __set_state($bir_dizi)
{
$obj = new A;
$obj->var1 = $bir_dizi['var1'];
$obj->var2 = $bir_dizi['var2'];
return $obj;
}
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);
?>
Yukarıdaki örneğin çıktısı:
object(A)#2 (2) {
["var1"]=>
int(5)
["var2"]=>
string(3) "foo"
}
Bilginize:
Bir nesne ihraç edilirken,
__set_state() nesnenin sınıfı
tarafından gerçeklenmiş mi diye var_export() bakmaz,
dolayısıyla böyle nesnelerin yeniden ithali __set_state() hiç
gerçeklenmemiş gibi başarısız olur. Bu kısmen bazı dahili sınıfları da
etkiler.
Sadece, __set_state() gerçekleyen sınıfın nesnelerinin yeniden ithal
edileceğini doğrulamak yazılımcının sorumluluğundadır.
__debugInfo
(
): array
Gösterilmesi gereken özelliklerini döndürmek için bir nesne
dökümleneceği zaman bu yöntem var_dump() tarafından
çağrılır.
Örnek 6 - __debugInfo()
kullanımı
<?php
class C {
private $prop;
public function __construct($val) {
$this->prop = $val;
}
public function __debugInfo() {
return [
'propSquared' => $this->prop ** 2,
];
}
}
var_dump(new C(42));
?>
Yukarıdaki örneğin çıktısı:
object(C)#1 (1) {
["propSquared"]=>
int(1764)
}