PHP – singleton pattern vs clone

Class Test{
       /**
	 * Örnek Değişken
	 */
	public $sampleVariable = NULL;

	/**
	 * Singelton bir yapı kullanılmaktadır
	 * @var Test
	 */
	private static $_instance;
       /**
	 * Singelton yapıyı desteklemek için private constructor yarattım içi boş.
	 */
	private function __construct(){

	}

	/**
	 * Singelton yapıyı destekleyen getInstance metodu
	 * @return Test
	 */
	public static function getInstance(){
		if (self::$_instance == null) {
			self::$_instance = new Test();
		}
		return self::$_instance;
	}
}

Yukarıdaki kod basitçe bir singleton mimariyi gösteriyor.

Burada ben

 $test = new Test()

yaratamıyorum. Çünkü constructor method’un erişilebilirliği “private” olarak belirlenmiş.
Yani ancak bu sınıfı

$test = Test::getInstance()

diyerek kullanabilirim.

Peki gelin görün ki, unuttuğumuz bir şey var.

Php’de “clone” diye bir obje kopyalama özelliği var. Nedir bu?

$a = new stdClass();
$k = $a;

dediğimizde, $a->var = 5 dediğimizde, $k da aynı şekilde değişiyor. yani bu ikisi aynı objeyi işaret ediyor.

Ancak

$a = new stdClass();
$k = clone $a;

Yazdığımızda ise, artık $k, $a nın en son halinden kopyalanıp yeni bir obje olarak oluşturuluyor.

Yani ben ilk örnekte,

$test = Test::getInstance();

yazdıktan sonra bir yerlerde
$anotherTest = clone $test;
dersem, artık yeni bir obje türetebilmiş oluyorum.

Buyrun deneyin :

$test = Test::getInstance();
$anotherTest = clone $test;

$test->sampleVariable = 5;
$anotherTest->sampleVariable = 10;

var_dump($test);
var_dump($anotherTest);

Birbirinin aynısı olmayan, aynı objenin farklı 2 instance’ını singleton mimaride de yapabilmiş oldum.

Sonuç : Demek ki, PHP de singleton mimarisi güvenilir değildir. Class’ın içerisine ancak private bir __clone metoru tanımlayınca güvenli oluyor. (@edit adil ilhan’ın yorumuna istinaden)
Yine de güzel bir design patterni olarak beğeniyorum. Ancak bilinçli kullanmanızı tavsiye ederim.

phpunit – assert internal type error – CLI HAS STOPPED WORKING

phpunitteki bir test metodumda yanlışlıkla assertInternalType kısmında 2 parametre yerine tek parametre ile işlem yapmıştım.

$this->assertInternalType('string',$oid);

yazacağıma

$this->assertInternalType($oid);

yaazmışım.
$oid ise string tipinde rastgele bir veri.

Ancak phpunit bu kısımda bazen hata veriyor, bazen vermiyordu. Hata vermediğinde ilerleyen aşamalarda ise, CLI has stopped working diye windowsumda işlem duruyordu.
Bu herhalde bir bug.
Ancak hem windowsta ara sıra başıma geliyordu, hem de derdimi nasıl anlatacağımı bilmediğimden bug kaydı oluşturmadım.
Yazmam gerektiği gibi yazınca ise, artık problemin düzeldiğini gördüm.

Buradan sizinle paylaşmak istedim.

mysql’deki tablonun olup olmadığını kontrol etmek (php kullanarak)

Php ile çalışırken, mysql’de kullandığımız veritabanı içerisinde, herhangi bir isimdeki tablonun var olup olmadığını kontrol etmenin bir kaç yolu vardır. Bu yazıda onlardan bahsedeceğim.

Bunlardan ilki, SHOW TABLES querysini kullanmaktır.

Örneğin, test isminde bir veritabanımız olsun. İçerisindeki tabloların ismi de, admin, member, log, test1, test2 olsun. Yani mysql’e konsoldan bağlanıp use test dedikten sonra, show tables dediğimizde karşımıza şu çıksın.

+------------------------+         |
| admin                  |
| member                 |
| log                    |
| test1                  |
| test2                  | 
+------------------------+

Şimdi işin Php kısmına geçelim.

// burada mysql'e bağlanmış olalım.

$result = mysql_query( "SHOW TABLES FROM test" );

if (! $result) {
	echo "Sorguda hata meydana geldi 
"; echo 'mysql error: ' . mysql_error(); } else { $row = array(); while ( $row = mysql_fetch_row( $result ) ) { echo "Tablo ismi : ".$row[0]."
"; } } mysql_free_result( $result );

SHOW TABLES FROM test querysinin ardından, LIKE parametresi ekleyerek, sonucu daraltabiliriz. Ardından da sonuçları php ile parse ederek, aradığımız isimdeki tablonun olup olmadığını kontrol edebiliriz. (SHOW TABLES FROM test LIKE ‘%min%’ gibi)

İkinci yöntemimiz ise, mysql’deki information_schema databasei içerisindeki TABLES tablosundaki bilgiler. Bu tabloda TABLE_SCHEMA sütununda veritabanı isimleri TABLE_NAME sütununda ise tablo isimleri yer almaktadır.

SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = ‘{database ismi}’ AND table_name = ‘{tablo ismi}’ şeklinde çalıştıracağımız sorgudan gelen sonuç ile istediğimizi elde etmiş olacağız. Yapalım;

// burada mysql'e bağlanmış olalım.

$result = mysql_query( "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='test' AND table_name='test1'" );

if (! $result) {
	echo "Sorguda hata meydana geldi 
"; echo 'mysql error: ' . mysql_error(); } else { $count = mysql_num_rows($result); if($count == 1){ // tablo var, gerekli işlemler } else { // tablo yok, gerekli işlemler } } mysql_free_result( $result );

php strict standards – only variables should be passed by reference error

strict standards – only variables should be passed by reference error hatasını alıyorsanız, referans olarak değişken göndermeniz gereken yere, siz farklı bir şey göndermişsiniz demektir.

Ben hatayı şöyle almıştım.

$var = end(explode( "/", $filename ));

end işlemini yaptığım şey explode işleminin sonucu. Ancak explode bir array döndürürken, bu male dating rules arrayi bir değişkene atamadığım için, arrayin sadece adresini döndürmüş oluyor. Bu free sex slave videos online da end fonksiyonunun çalışmamasına sebep http://crosspointnyc.com/uemz-free-contact-personals-websites oluyor.

Çalışması için aşağıdaki gibi basit bir düzenleme yapıyoruz :

$tmpArr= explode( webcams in argentina  "/", $filename);
$var = end($tmpArr);

Bu problem php 5.4.x sürümlerinde karşınıza çıkmıyor ancak php 5.3.x sürümlerinde mevcuttur.

TypeHinting nedir? Php Typehinting

Typehinting demek, bir class’a ait metodun aldığı parametrelerin türünün önceden belirlenmesi, force edilmesi demektir. Ancak bu işlemi sadece objelerde ve arraylerde yapabilmekteyiz.

Örnek verecek olursak;

class Dubluve{
 public function deneme(array $a){
  var_dump($a);
 }
}
$obj = new Dubluve();

deneme metodu için şunları söyleyebiliriz;

// bu kodlar hata verecektir
$obj->deneme("php");
$obj->deneme(123);
$obj->deneme("1");

// bu kod çalışacaktır
$obj->deneme(array("a", "b", "c"));

Type hinting işlemini düzgün olarak array ve objelerde kullanabiliyoruz onun da şöyle bir püf noktası var. Metoda gönderdiğimiz parametre için default değer olarak NULL atarsak, gönderdiğimiz parametre de NULL olabilir. Bunu da örnekle açıklamak gerekirse,

class DubluveRSS{
 public function deneme(Dubluve $dubluve) // $dubluve değişkeni sadece Dubluve'nin objesi olabilir
 public function deneme(Dubluve $dubluve = NULL) // $dubluve değişkeni Dubluve'nin objesi olabilir veya NULL olabilir
}

Öte yandan ;

public function deneme(array $dubluve = array("a", "b", "c"))

bu fonksiyonu deneme(null); şeklinde çalıştıramayız. Ancak diyorsak ki, null parametre gönderilebilsin ancak null geldiyse default olarak bir şeyler atayabileyim, o zaman da şöyle birşey yapabiliriz

public function deneme(array $dubluve = null){
 if($dubluve === null){
   $dubluve = array("a", "b", "c");
 }
 .
 .
 .
}

Typehinting fonksiyonlarda da çalışmaktadır. Yine class metodlarında olduğu gibi sadece obje ve arrayler ile işlem yapılabilmektedir.