Burhan T. 3 dakikalık okuma
June 12, 2017

PHP’de Anonymous Fonksiyonlar ve Closure Kullanımı

PHP 5.3 sürümü ile birçok yeni özelliği bünyesine katmış. Dilde hem nesne yönelimli programlama iyileştirmesi olsun hem de yeni dil özellikleri olsun bu gelişmeler gerçekten PHP’yi bir çıta üste taşımış.

Anonymous fonksiyon, isimsiz fonksiyon manasındadır. Closure ise Anonymous fonksiyonunun nesne yönelimli kullanım yöntemidir.

İleride çok daha detaylı bahsedeceğim dependecy injection tekniği bu Closure özelliği ile yapılıyor.

Anonymous Fonksiyon

Aşağıdaki örnek son derece net durumu özetliyor:

$yaz = function($girdi)
{
    echo ("Merhaba".$girdi);
}; // dikkat ; ile sonlandırdım.

$yaz('World');
$yaz('PHP');

Yukarıda görüldüğü üzere fonksiyonda isim yok. Ayrıca fonksiyon bittikten sonra } değil de }; şeklinde kullandım. Buna da dikkat edin.

Şimdi gelelim bu Anonymous’larla neler yapabiliriz. Daha çok callback işlemleri işin kullanılıyor. Callback kendi kendini geri çağırma demek. Nasıl ?

// Anonymous fonksiyonumuz
$double = function($a) {
    return $a * 2;
};

// Sayı aralıklarını belirleyelim.
$numbers = range(1, 5);

// Burada Anonymous fonksiyonumuzu callback olarak
// kullanıyoruz.
$new_numbers = array_map($double, $numbers);

print implode(' ', $new_numbers);

Yukarıda array_map içerisinde Anonymous fonksiyon kullandık. Örneğin array_map() isimli standart fonksiyon ilk parametresine aldığı closure ile ikinci parametresinde aldığı diziyi işleme soktorur ve sonucu gönderir. Bu açıklama çok önemli. bir isimsiz fonksiyon yazıyorum bu fonksiyon mesela dizi elemanlarının herbinini 2 ile çarpacak. İşte array_map ile closure kullanarak bunu yapabiliyorum. Eğer ben Anonymous fonksiyon değil de klasik fonksiyon yazsaydım php içinde. Şu şekilde:

function yaz($girdi)
{
    echo ("Merhaba".$girdi);
}

Bu kodu array_map gibi fonksiyonlar içerisinde kullanamayacaktım.

Closure ve Kullanımı

Php 5.3 ‘ten sonra gömülü olarak gelen Closure sınıfına göz atalım:

 Closure {
/* Methods */
private __construct ( void )
public static Closure bind ( Closure $closure , object $newthis [, mixed $newscope = "static" ] )
public Closure bindTo ( object $newthis [, mixed $newscope = "static" ] )
public mixed call ( object $newthis [, mixed $... ] )
public static Closure fromCallable ( callable $callable )
}

Closure sınıfının metodlarının açıklaması şöyle:

  • Closure::__construct — Constructor that disallows instantiation
  • Closure::bind — Duplicates a closure with a specific bound object and class scope
  • Closure::bindTo — Duplicates the closure with a new bound object and class scope
  • Closure::call — Binds and calls the closure
  • Closure::fromCallable — Converts a callable into a closure.

Şimdi bir Closure kullanalım. Aşağıdaki örnekte de görülmek üzere Anonymous fonksiyonların nesne yönelimli yöntemle kullanım şeklidir Closure.

class TheRoot
{
    public function poidh($param) {
        echo "TheRoot $param!";
    }   

}

class Internet
{

    public function run_my_closure($bar, Closure $my_closure) {
        $my_closure($bar);
    }   
}

$Internet = new Internet();
$Root = new TheRoot();

//Closure fonksiyonun parametresi muhakkak object olmalı...
//verdiğimiz root sınıfını nasıl closure içinde işlettirip sonucu
//aldığımızı görün :)
$Internet->run_my_closure($Root, function($Object) {
    $Object->poidh(42);
});

Closure’un kullanım alanlarından en güzel örneğin yukarıdaki olduğunu söyleyebilirim. Yukarıda kullanılan şu satıra dikkat:

$Internet->run_my_closure($Root, function($Object) {
    $Object->poidh(42);
});

Şimdi Closure’nin başka stil kullanımlarını gösterelim. Aşağıdaki örneği iyi inceleyin:

$mesaj='Merhaba Dünya!';

// Closurelarda parametre esnekliği. Use ile diyorum ki dışarıdaki $mesaj'ı bu fonksiyon içinde //kullan.$par1'de Closure metodumun parametresi. Dinamik olarak dışarıdan alınacak.
$ornek = function ($par1) use ($mesaj) {
var_dump($par1 . ' ' . $mesaj);
};
$ornek("Günaydın");
//cikti: Günaydın Merhaba Dünya!

Bir sınıfın private değişkenine Closure kullanarak erişebiliriz. Bunu de örnekle gösterelim:

class SimpleClass {
    private $privateData = 2;
}

$simpleClosure = function() {
    return $this->privateData;
};

$resultClosure = Closure::bind($simpleClosure, new SimpleClass(), 'SimpleClass');

echo $resultClosure();  // çıktı 2 olacak.

Görüyor musunuz ? Sadece private değişken ismini biliyoruz ve mevcut sınıfı değiştirmeden harika bir yöntemle private değişkenindeki değeri kullanabiliyoruz.


Etiketler: