NoSQL vertiabanı motorları son yıllarda çok popülerleşti, çünkü yapısız olmalarından dolayı daha kolay mimari değişiklik yapabileceğiniz veri yapıları olduğu için tercih edilmeye başladı. Ölçeklenebilirlik de klasik sql veritabanlarının sınırlı ve geleneksel kaldığı konulardı. NoSQL çıkışı kesinlikle modern bir çözüm olarak görülebilir.

İnternette bir çok karşılaştırma, performans analiz yazıları bulabilirsiniz sql ve nosql veritabanları hakkında. Ancak her yere uyan mükemmel bir çözüm yok. Benim gördüğüm kadarıyla, hibrid ve akıllıca kurgulanarak dengelenmiş ve dağıtılmış sistemler en yaygın kullanımlar. Yani bazı şeyleri nosql ile daha zor ve daha çok kodlama zamanı harcayarak yapabilir, bazı şeyleri de sql ile yönetemez ve yapamazsınız.

Daha teknik konulara giriyorsanız zaten bu yazıdan daha çoğuna ihtiyacınız var :-) Bu yazı daha çok mongo'ya giriş ve flörtleşme dönemi hakkında.

Eğer MongoDB'yi denemek istiyorsanız, mongodb sunucusunu bilgisayarınıza yüklemek zorunda değilsiniz. Kurulumu da çok zor değil fakat sadece denemek için sunucu kurulumu konfigurasyonu gibi şeylerle uğraşmak zorunda değilsiniz. Sadece istemci sürücülerini kurmanız yeterli. Bu konu hakkında mongodb dökümantasyonundakihttp://docs.mongodb.org/ecosystem/drivers/php/ sayfasını inceleyebilirsiniz.

MongoLab adında bağımsız bir servis sayesinde ücretsiz bir mongo veritabanı oluşturabilir ve denemelerinizi onun üstünde yapabilirsiniz. MongoLab veritabanı ve kullanıcınızı oluşturduktan sonra açık erişim izni veriyor. Dolayısıyla php'den veya herhangi diğer bir ortamdan doğrudan erişebiliyorsunuz.

Tabi ki servisin amacı mongo denemek isteyen insanlara servis sunmak değil. MongoLab bulut veritabanı servisi. Veri dosyalarının saklanmasını istediğiniz alt servisi (Amazon, Rackspace, Windows Azure vs...), hatta yüzeysel de olsa bölge seçebiliyorsunuz (Amerika veya Avrupa veya uzak doğudaki bir veri merkezi şeklinde).

MongoLab 500mblık bir alanı ücretsiz sağlıyor. Diğer sınırlamalarını bilmiyorum fakat ufak projeleriniz için veya deneme yapmak için ideal. Eğer uygulamanız çok veri kullanmaya başlarsa küçük, büyük paketleri veya kurumsal hizmetlerinden faydalanabilirsiniz.

MongoLab ile tamamen php mongo eklentisi bağımlılığından da kurtularak doğrudan servisin basit REST apisini kullanabilir ve tek başına çalışan bir uygulama yazmanız da mümkün.

Konumuz mongo iken, birkaç php-mongo interaksiyonunu denediğim bir php dosyasının kodunu doğrudan vermek istiyorum.
<?php

$mongo = new Mongo("mongodb://dbuser:dbpassword@*.mongolab.com:45297/test_database");
$db = $mongo->selectDB("test_database");

$action = isset($_GET['action']) ? $_GET['action'] : NULL;

?>
	<ul>
		<li><a href="?action=create_collection&name=test_collection_<?=rand(1,10000);?>">Create a test collection</a></li>
		<li><a href="?action=list_collections">List collections</a></li>
		<li><a href="?action=add_record_to_nonexistent_collection">Add record to non existent collection (it creates the collection)</a></li>
		<li><a href="?action=add_user">Add a user</a></li>
		<li><a href="?action=find_fatih">Find Fatih</a></li>
		<li><a href="?action=search_user">Search user</a></li>
	</ul>
<?php

switch ($action) {
	case 'create_collection':
		$name = isset($_GET['name']) ? $_GET['name'] : 'users';
		var_dump($db->createCollection($name, FALSE));
		exit;
		break;

	case 'list_collections':
		$_collections = $db->listCollections();

		print '<h3>Collecitons</h3>';
		foreach ($_collections as $collection) {
			print $collection . '<br />';
		}

		break;

	case 'add_user':
		$name = isset($_GET['name']) ? $_GET['name'] : 'test_user_' . rand(1, 100000);

		$users = $db->users;
		$result = $users->insert(array(
			'username'   => $name,
			'created_at' => date('Y-m-d H:i:s')
		));

		print '<h3>Result:</h3>';
		var_dump($result);
		exit;
		break;

	case 'add_record_to_nonexistent_collection':
		$collection = isset($_GET['name']) ? $_GET['name'] : 'collection_' . rand(1, 100000);

		// it creates the collection even if not exists.

		$collection_obj = $db->$collection;
		$result = $collection_obj->insert(array(
			'test' => 1,
			'time' => time()
		));

		print '<h3>Result:</h3>';
		var_dump($result);
		exit;
		break;

	case 'find_fatih':
		$users = $db->users;
		$result = $users->findOne(array("username" => 'fatih'));

		print '<h3>Fatih?</h3>';
		var_dump($result);
		exit;
		break;

	case 'search_user':
		$users = $db->users;
		$result = $users->find(array("username" => array('$regex' => 'test_')));

		print '<h3>Users:</h3>';
		foreach ($result as $_result) {
			var_dump($_result);
		}
		exit;
		break;

	default:
		break;
}
İlk satırlarda göreceğiniz dsn'i mongolab'den edineceğiniz sunucu adresi ve portunu (tahminimce her kullanıcı için farklı olma durumu var), veritabanı kullanıcı adınız ve şifrenizi belirterek tek parça string şeklinde belirttiginiz takdirde bağlantı sağlayabileceksiniz.

Mongo, küçük uygulamalarda veri düzeni zorunluluğu olmadığı için kullanması çok keyifli, fakat verinizi dökümante etmeyi unutmayın. Yoksa neyin ne olduğunu unutur veya ipin ucunu kaçırarak karmaşık bir veri yığını elde edebilirsiniz günün sonunda.

MongoDB dökümantasyonunu inceleyerek indeksleme, sorgulama ve veri yönetimi nasıl yapılıyor fikir edinebilirsiniz. Ayrıca php manual'daki bazı SQL örneklerinin php ile mongo sınıfında nasıl yapıldığını gösteren bu sayfayı:http://php.net/manual/en/mongo.sqltomongo.php incelemekte fayda var.

MongoLab servisinin adresihttps://mongolab.com
Yaklaşık 2 yıldır ufak bir sosyal ağ geliştiren bir ekibin parçasıyım. Her gün farklı bir sosyal problemle karşılaşıyor ve çözmeye çalışıyoruz. Yüksek oranda pozitif geri bildirime sahibiz ve tabi ki insanların pozitif geri bildirimleri ekibe büyük bir motivasyon olarak etki ediyor.

Birkaç hafta önce ilginç bir kullanıcı geri bildirimi aldık. İspanyol bir kullanıcımız hem mobil uygulamamızda hem de sitede çok detaylı bir erişilebilirlik analizi sunarak ürünlerimizin büyük oranda erişilebilir olduğunu söyledi ve bunun için teşekkür etti. Hemen anlayamadık tabi ki niye böyle bi analizi sunduğunu. Sonrasında kullanıcı hesabını incelediğimizde kullanıcının kısa sürede iyi bir ürün adaptasyonu sağladığını farkettik, yani mobil uygulamamızdaki her ekranı delik deşik etmis, web sitesinin de altıdan girip üstünden çıkmış, kısa sürede "deneyimli" bir kullanıcı seviyesine erişmiş de diyebiliriz.

Buraya kadar herşey normal, çünkü sistemimizde çok sayıda, aktif ve yüksek etkileşimde bulunan kullanıcımız var. Fakat bu kullanıcı, birkaç mesajlaşmamızdan sonra görme engelli bir geliştirici olduğunu, uygulamalarımızı ekran okuyucu gibi araçlar kullanarak kullandığını söyledi, sonraki yazışmalarımızda sitede erişilebilirlik konusunda eksik olan kısımları nasıl kullandığını anlattığında açıkçası ağzımız açık kaldı ve saygı duyup takdir ettik.

Devamını Oku →
16 Temmuz Pazartesi ´12   —   7 Yorum
Türkçesini çok bulamadığım hash kelimesini anahtar olarak kullanacağım. Burada aslında bahsettiğim anahtar herhangi bir veri grubunuza atadığınız, sayısal olmayan kimliklerden bahsediyorum. Yani rasgele üretilmiş belirli bir uzunlukta olan kimlikleri her yerde kullanıyoruz.

Neden sayısal bir kimlik kullanmak yerine bu anahtarlara ihtiyaç duyacağınızı en açık şekilde şöyle anlatabilirim. Mesela tahmin ederek erişilmesini istemeyeceğiniz ama şifre veya kullanıcı girişi gibi herhangi bir sınırlama koyamayacağınız bir sayfanız var, örnek veriyorum yapılacak işler listesi veritabanı oluşturuyorsunuz ve her kayıt bir yapılacak iş listesi. Veritabanında sayısal bir kimliğe yani numaraya sahip bu kayıtlar. Hazırladığınız bir php sayfası da liste numarasına göre yapılacak iş listesinin detayını ekrana döküyor.

Eğer liste_detay.php?no=145 gibi basit bir şekilde tutarsanız url'i oynayarak başkalarının listelerine erişebilir, sadece erişmek değil sistemdeki tüm listeleri basit bir script ile tahmin edebilir veya tarayıp kaydedebiliriz. Böyle bir durumda listelerinizi sadece sayısal değil, tahmin edilemeyecek bir anahtar ile (örneğin: t34de6gx) tanımlamak istiyorsunuz.

Bu noktada rastgele bir anahtar üretebilirsiniz, bunu yapmak çok zor değil. PHP'deki rasgele sayı üretme fonksiyonunu kullanarak ve bir karakter dizisinden rastgele elemanlar çekerek bir kelime üretebilirsiniz.

Bunu daha pratik bir şekilde tek satırda bile yapabilirsiniz:
$anahtar = substr(str_shuffle('abcdefghklmnoprstuvyzqxw1234567890'), 0, 6);
Bu satır size 6 karakterlik bir kelime üretecektir. Basitçe str_shuffle fonksiyonu ile özel karakter içermeyen ve rakamlarında dahil olduğu bir alfabeyi karıştırıyor ve başındaki ilk 6 karakteri alıyoruz.

Şimdi bu, işin basit kısmı. Eğer veritabanındaki bir veri set için bu anahtarı oluşturuyorsanız üretilen anahtarın veri setinde daha önce kullanılıp kullanılmadığını test etmek zorundasınız. Sonuçta tekil bir anahtar oluşturuyorsunuz. Bu arada veri setiniz mysql veya bir sql veritabanında olmak zorunda değil, bir xml, csv veya txt dosyasında saklı olan bir set için de benzer şeyi uygulayabilirsiniz.

Veritabanındaki veriyi test ederek bir anahtar oluşturmanın en kısa ve basit kodu şöyle:
do {
    $anahtar = substr(str_shuffle('abcdefghklmnoprstuvyzqxw1234567890'), 0, 6);

    $query = mysql_query("SELECT no FROM listeler 
        WHERE anahtar LIKE '" . $anahtar . "'");
} while (mysql_num_rows($query) > 0);

print $anahtar;
Bu kod, veritabanında olmayan bir anahtar üretmenizi sağlayacaktır. Sonra verinizi hazırlayıp tablonuza yeni kayıdınızı ekleyebilirsiniz.


Hazırlayan: Mehmet Fatih YILDIZ
6 Ekim Pazartesi ´08   —   13 Yorum

MDB2 Nedir?

MDB2 ilk başta DB olarak başlayan sonra MDB olan ve en son MDB2 ismine dönüşen PEAR'ın veritabanı yönetim paketlerinden birisidir. Oldukça fazla türde veritabanı sürücüsü (driver) bulunduğu için, projenizde bu kütüphaneyi kullanıp fakrlı veritabanı yapılarını aynı kodda rahatça kullanabilmenizi sağlar. Ayrıca "prepare & execute" gibi yapılarla hem sql sorgularınızı daha anlaşılır yapar, hem de injection gibi saldırılar için veri türü kontrollerini otomatik yapar.

Sonuç olarak güvenlik, daha taşınabilir kod, kolaylık gibi özelliklerinden dolayı tercih edilmesi gereklidir diye düşünüyorum. Genel olarak PHP'nin PDO'suna benzeyen bir yapısı var (özellikler bakımından).

Örneklerle Genel Kullanımı

PEAR'ı sisteminize kurmanız gerekiyor. Ya da PEAR'ı kendi projenize gömerek de kullanabilirsiniz.http://pear.php.net/package/MDB2 adresinden MDB2'yi indirebilirsiniz. PEAR dizininizi include_path'a tanıtırsanız şu şekilde sayfa başında MDB2'yi çalıştırabilirsiniz :
require_once('MDB2.php');

Bağlantı

MDB2'yi bağlamak çok kolay. Bağlantı fonksiyonunda DSN (Data Source Name) denilen bir cümle ile veritabanı türü, kullanıcı, şifresi, sunucu, port, veritabanı adını bir url olarak veriyorsunuz. Yani fonksiyona 100 tane parametre girmek zorunda kalmıyorsunuz.

Aşağıdaki örnekten rahatça anlayacaksınız zaten DSN'nin nasıl birşey olduğunu :
$db = MDB2::connect("mysql://kullanici:[email protected]/veritabani");
if(PEAR::isError($db)){
  die( 'Veritabani baglantisi yapilamadi!<br>' . $db->getMessage() );
}
gördüğünüz gibi bir web sitesi url'si tanımlamak gibi. Daha doğrusu ftp erişimi yapmak gibi.
protokol türü + "://" + kullanıcı + ":" + şifre + "@" + sunucu (+":port") + "/" veritabanı

Yani siz aynı veritabanı yapısını oluşturduğunuz sürece projenizi ileride mysql:// yerine pgsql:// yazarak kolayca çevirebileceksiniz.

Neyse, bağlantı kısmı işin başlangıcı. Asıl sık sık kullanacağımız olan şey sorgu işletmek, sonuçları işlemek vs.

Sorgu işletmek

// sorguyu isletirken query fonksiyonunu kullanıyoruz
$sorgu = $db->query("select * from haberler");
// numRows ile donen sonuc kumesinin boyutunu alabiliriz
if( $sorgu->numRows() > 0 ){

  // fetchAll ile tum sonucları çok boyutlu dizi olarak alabiliriz
  // veya while ile donerek fetchRow() fonksiyonu yardimi ile
  // kayitlari sirayla tek tek aldirabiliriz.
  $sonuclar = $sorgu->fetchAll();

  // sorgu kaynagini kaldiriyoruz. Eger bu islemi yapmazsak
  // sunucu yukunu agirlastirabiliriz
  $sorgu->free();

  // sonuclari normal dizi islemleri ile isleyebiliriz
  foreach($sonuclar as $sonuc){
    print $sonuc[baslik] . '<br />';
  }

}
Örnekte tüm detayları açıkladım :-) Eğer çok boyutlu sonuçlarla çalışıyorsanız fetchAll ile halletmenizi öneririm işlerinizi. Eğer tek boyutlu sonuç bekliyorsanız fetchRow işinizi görecektir.

Injection için güzellikler

En sevdiğim kısmı ise sizi verilerinizin türünü kontrol etme işini üstünüzden alması. Bunun için iki yol var. Birincisi query kullanarak quote yapmak. Yani Türkçesi, yukarıdaki methodu kullanarak sorgu işletmek, ama işletirken de değişkenleri tek tek bir fonksiyondan geçirmek. Örnekle anlatırsam :
// elimizde $ad, $ziyaret_sayisi degiskenleri olsun

$sorgu = $db->query('insert into uyeler (ad, ziyaret) values ('. $db->quote($ad, 'text') .', '. $db->quote($ziyaret_sayisi, 'integer') .')');
görüldüğü gibi sql içinde herhangi bir tırnak kullanmadan doğrudan quote() fonksiyonunu kullandım. ilk parametrede veri ikinci parametrede de veri türünü belirtiyorsunuz. Eğer text ise sql injection önlemlerini alıyor. integer ise zaten sayısallaştırıp kaydediyor.

Ancak yine de sqliniz oldukça karışık görünüyor. Yani baksanıza bir sürü tırnak ile SQL cümlesini oluşturan string'den kaçmak için uğraştık. Ayrıca sürekli $db->quote(...) gibi bir fonksiyon çağırmak, elinizde 20 tane alan varsa sıkıcı bir işe dönüşecektir. Bunun için prepare & execute yapısını kullanacağız.

Prepare & Execute

quote kullanımından biraz daha uzun. Ancak eğer sorgunuzda kullanıcıdan gelebilecek bir veri kullanıyorsanız KESİNLİKLE bu yapıyı kullanmanızı öneririm. Yani sonuçta gözünüzden kaçabiliyor bazen değişkenlerinizi izlemek ve kontrol etmek. Bu kullanıma alışırsanız farkında olmadan vereceğiniz açık sayısı en az inecektir.

Gelelim kullanıma, bunu da örnekleyerek anlatacağım :
// prepare ile ilk parametrede sorgunuzu yazıyorsunuz. Değişken olan her yere tırnak fln koymadan sadece soru işareti koyuyorsunuz. prepare fonksiyonunun ikinci parametresinde de dizi olarak sırasıyla o soru işaretlerinin veri türlerini belirtiyorsunuz.
$sorgu = $db->prepare("select * from uyeler where adi like ?", array('text'));

// execute ile dizi şeklinde soru işaretlerine sırasıyla gelecek verinizi veriyorsunuz.
$sonuc = $sorgu->execute("fatih");

// evreka, $sonuc degiskeni bir sonuc kumesine dönüyor. Sonra klasik işlemleri yapıyorsunuz
if($sonuc->numRows() < 1) die("sonuc bulunamadi");
$uyeler = $sonuc->fetchAll();
// ...
Bu örnekte tek değişken gösterdiğim için pek anlaşılmamış olabilir. Ancak alttaki örnekte prepare & execute yapısının önemini kavrayacaksınız.
// elimizde çok değişken olsun

$sorgu = $db->prepare("insert into uyeler (no, adi, eposta, yorum_sayisi, uyelik_tarihi, aktif, www) values (?, ?, ?, ?, now(), ?, ?)", array('integer', 'text', 'text', 'integer', 'integer', 'text'));
// verilerinizi bir diziye koyuyorsunuz, tabiki soru işaretleri hangi sırada ise o sırada koyuyorsunuz
$veri = array($no, $adi, $eposta, $yorum, $aktif, $www);
// basitçe sorgunuzu işletiyorsunuz
if( !$sorgu->execute($veri) ) die("sql çalışmadı");

// işte olayın güzelliği şurada :
// mesela aynı sqlinizi bir daha işletmek istiyorsunuz.
// bunun için $sorgu olan object değişkenini tekrar tekrar kullanabilirsiniz
$sorgu->execute(array(5, 'başka üye', [email protected]', 10, 1, "http://www.deneme.com"));

// hatta eğer sisteminizi daha efektif hale getirmek isterseniz
// bütün SQL'lerinizi fonksiyonlara çevirin. Mesela :
function uye_kaydet($veri){
  // sql hazirlaniyor
  $sorgu = $GLOBALS[db]->prepare("insert into uyeler (no, adi, eposta, yorum_sayisi, uyelik_tarihi, aktif, www) values (?, ?, ?, ?, now(), ?, ?)", array('integer', 'text', 'text', 'integer', 'integer', 'text'));

  // gelen veri isletiliyor
  if( $sorgu->execute($veri) ) return true;
  else return false;
}
Son kısımda bahsettiğim detayı umarım anlayabilmişsinizdir. Çünkü bu şekilde uygulama geliştirdiğiniz zaman, uygulamanız daha esnek, daha rahat müdahale edilebilir ve daha rahat geliştirilebilir hale gelecektir. Siz üye kayıt sayfasını daha sadeleştirmiş olacak, eğer gerekirse üye veritabanında yapacağınız bir değişiklik için gidip üye kayıt sayfasının içinde HTML, PHP karışık kodun içinde aramak yerine doğrudan fonksiyonunuzdaki sql'i güncelleyerek daha hızlı çalışacaksınız.

Bu noktada iş gruplarına ait fonksiyonları sınıflandırırsanız zaten Nesne Tabanlı Programlama (OOP)'ya adım atmış olacaksınız :-)


Hazırlayan : Mehmet Fatih YILDIZ

Popüler Etiketler

opengraph graph api facebook share social wanda proje kampanya logo html5 html regex css javascript cache htaccess apache oyun js mysql query select spam imza signature apple mail link url service tool google search mod_rewrite cookie php assets ubuntu workspace rss parse xml coding ipad ios firefox zaman mfyz design wordpress framework mootools ajax xmlhttprequest twitter calendar media download digital ingilizce phpstorm jetbrains pgsql sql mssql ide editor injection css3 browsers support nedir ui ux icons internet explorer less optimization fql bootstrap jquery portfolio ie session wireless language development style compile compiler macosx windows linux app on-the-fly pear mdb2 prepare execute www subdomain redirect crossdomain kurulum sosyal medya istatistik statistics iphone app store store in-app purchase purchase subscription verification storekit itunes connect itunes mobile table plugin box gimp screen internet tebrik server doritos tytz job chart grafik network iOS integration blog örnek kod cms banner lifestream kontrol yapıları if while textarea applications free konsol terminal dokuman optimizasyon db code license auth web app open source form input developer object insanlar icon ikon howto ruffles player lisans sitemap seo date diff tarih http osx notebook laptop newsletter widget ipucu kitap analyse procedure route router database connect svn subversion git version control deployment meta radio webkit music button ntfs fstab startups pharma hack nasıl login generator xhtml export browser switch