kurucu ve yıkıcı metodlar

programlamada bazen belirlemiş olduğumuz komutların kendi kendine (otomatik) çalışmasını isteyebiliriz. mesela bir sınıftan nesne oluşturduğumuz anda başlangıç değerleri atansın, nesne kaldırılırken de açık bıraktığı dosya kapatılsın.

kurucu ve yıkıcı metodlar burada kullanılır. kurucu metodun adı __construct, yıkıcı metodun adı ise __destruct tır. başlarındaki iki alt çizgiye dikkat edin. tek alt çizgi yazarsanız PHP bunları bu özel metodlar olarak tanımaz.

kurucu metod, new ile nesne oluşturduğumuzda çalışır. yıkıcı metod ise nesneye ait son referans da kaldırıldığında yada program normal şekilde sonlanırken çalışır. yani yıkıcı metodun çalışması için mutlaka sayfanın sonuna gelinmesi gerekmez. birazdan bunu ayrıca deneyeceğiz.

önce basit bir örnek üzerinden hangi metodun ne zaman çalıştığını görelim.

<?php
class Hesapla
{
    public function __construct()
    {
        echo "ben Hesapla içindeki kurucu metodum..<br>";
    }

    public function yaz()
    {
        echo "ben Hesapla içindeki yaz() metoduyum..<br>";
    }

    public function boz()
    {
        echo "ben Hesapla içindeki boz() metoduyum..<br>";
    }

    public function __destruct()
    {
        echo "ben Hesapla içindeki yıkıcı metodum..<br>";
    }
}

$ornek = new Hesapla();
$ornek->yaz();
$ornek->boz();

echo "ben arada bir satırım ki benim sınıfla bir alakam yok<br>";

bu örneği ayrı bir PHP dosyasında çalıştırdığımızda ekran çıktısı aşağıdaki gibi olur.

ben Hesapla içindeki kurucu metodum..
ben Hesapla içindeki yaz() metoduyum..
ben Hesapla içindeki boz() metoduyum..
ben arada bir satırım ki benim sınıfla bir alakam yok
ben Hesapla içindeki yıkıcı metodum..

burada dikkat ederseniz yaz ve boz metodlarını kendimiz çağırdık. fakat __construct için ayrıca bir çağrı yazmadık, new Hesapla() dediğimiz anda çalıştı. __destruct da bu örnekte programın sonuna geldiğimizde çalıştı. boz metodunun adı sizi yanıltmasın, o bizim verdiğimiz sıradan bir isim. PHP için yıkıcı olan metod __destruct tır.

kurucu metoda parametre gönderme

şimdi nesneyi oluştururken bir isim de göndermek istediğimizi düşünelim. kurucu metod bu değeri alıp nesnenin isim özelliğine yazsın. böylece nesneyi oluşturduktan sonra ayrıca isim atamak için başka bir metod çağırmamız gerekmez.

<?php
class Kase
{
    public $isim;

    public function __construct($isim)
    {
        $this->isim = $isim;
    }
}

$ornek = new Kase("Mustafa YILMAZ");
echo $ornek->isim; // Mustafa YILMAZ

burada new Kase parantezleri içine yazdığımız değer __construct metoduna parametre olarak gitti. $this->isim de o an oluşturulan nesnenin özelliği olduğu için, daha sonra nesne üzerinden bu değeri okuyabildik.

yıkıcı metodu dosya kapatma üzerinden görelim

ekrana yazı yazdırarak çalışma sırasını gördük. şimdi bir de gerçekten iş yapan örnek yazalım. bir sınıfımız olsun, nesne oluşunca dosya açsın ve gönderdiğimiz yazıyı bu dosyaya eklesin. nesne kaldırıldığında da açtığı dosyayı kapatsın.

<?php
class DosyaYazici
{
    private $dosya;

    public function __construct($yol)
    {
        $this->dosya = fopen($yol, "a");

        if ($this->dosya === false) {
            throw new RuntimeException("dosya açılamadı.");
        }

        echo "dosya açıldı<br>";
    }

    public function yaz($metin)
    {
        fwrite($this->dosya, $metin . PHP_EOL);
    }

    public function __destruct()
    {
        if (is_resource($this->dosya)) {
            fclose($this->dosya);
            echo "dosya kapatıldı<br>";
        }
    }
}

$kayit = new DosyaYazici(__DIR__ . "/ornek-kayit.txt");
$kayit->yaz("ilk kayıt");
echo "kayıt yazıldı<br>";

unset($kayit);

echo "program devam ediyor<br>";

bu örnekte PHP dosyasının bulunduğu klasöre yazma izni olması gerekir. fopen içindeki a dosyayı sonuna ekleme yapmak için açar, dosya yoksa oluşturmaya çalışır. kodu her çalıştırdığınızda ornek-kayit.txt içine yeni bir ilk kayıt satırı eklenir. önceki satırlar silinmez.

ekranda ise şu sırayı görürsünüz.

dosya açıldı
kayıt yazıldı
dosya kapatıldı
program devam ediyor

burada dosya kapatıldı yazısının program devam ediyor yazısından önce geldiğine dikkat edin. çünkü unset($kayit) ile değişkeni kaldırdık ve bu örnekte nesneyi tutan başka bir referans kalmadı. PHP de o anda __destruct metodunu çalıştırdı. dosyayı kapatan fclose komutunu bu metodun içine yazmıştık.

unset satırını kaldırıp tekrar deneyin. bu defa program devam ediyor yazısı önce, dosya kapatıldı yazısı programın sonunda gelir. aynı örnekte tek satırı değiştirerek yıkıcı metodun sadece sayfanın sonunda çalışmadığını görebilirsiniz.

bu arada nesneyi daha önce başka bir değişkene de atadıysanız yalnızca $kayit değişkenini kaldırmanız nesnenin hemen yok edilmesi için yeterli olmayabilir. başka değişken de aynı nesneyi tutmaya devam eder. yani unset doğrudan yıkıcı metodu çağıran bir komut değildir, burada kaldırdığımız şey değişkendir.

dosyayı kapatmak da dosyayı silmek anlamına gelmez. yazdığımız kayıt dosyada durur, sadece açtığımız dosya kaynağı kapanır. yıkıcı metodun içine yazdığımız echo satırları da bu işlemlerin sırasını görebilmek için var. kendi sınıfınızda dosya kapatırken ekrana mesaj yazdırmak zorunda değilsiniz.