Tag Archives: YII Framework

Programa Dilleri ve Çatıları

YII Üzerinde ActiveRecord Kullanımı

Ben yazdığım uygulamalarda uzun uzun SQL yazmayı sevmeyenlerdenim. Neden mi ? Pis duruyor arkadaş! Güvenli olsun diye göndereceğim her bir parametreyi teker teker escape etmek zor geliyor. Projelerimde basitliği nedeniyle zaman zaman ActiveRecord u tercih ediyorum. Bugün sizlere YII üzerinde ActiveRecord kütüphanesinin nasıl kullanılacağı konusundan kısaca bahsedeceğim.

Active Record Yenilir mi İçilir mi ?

ActiveRecord, bildiğiniz DbTable türünden bir PHP kütüphanesidir. Veritabanındaki herbir tablo, CActiveRecord sınıfından türeyen bir sınıf ile temsil edilir.

Şöyle bir tablomuz olsa:

CREATE TABLE tbl_post (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    title VARCHAR(128) NOT NULL,
    content TEXT NOT NULL,
    create_time INTEGER NOT NULL
);

Oturup PDO ile bu tabloya kayıt insert ediyor olsaydık şunları yapmamız gerekirdi.

$sqlQuery = "INSERT INTO `tbl_post` 
	     SET `title` = :title,
		  `content` = :content";
$pdo = new Pdo('mysql; host=127.0.0.1;dbname=mydb', 'dbuser', 'dbpass');
$statement = $pdo->prepare($sqlQuery);
$statement->bindValue(':title', 'sample post');
$statement->bindValue('content', 'post content');
$statement->execute();

Hakikaten kirli bir kod. Şimdi de gelin bu işi ActiveRecord ile yapalım.

$post = new Post();
$post->title = 'sample title';
$post->content = 'post content';
$post->save();

Bitti..! Temiz, güvenli ve stabil.

Güzelmiş… Peki ActiveRecord’u Nasıl Kullanırım ?

AR Tablolarımızla çatır çatır işlem yapabilmek için veritabanı bağlantımızın sular seller gibi açık olması gerekiyor. YII tarafında veritabanı bağlantısını başlangıçta ayağa kaldırmak için konfigürasyonda aşağıdaki değişikliği gerçekleştirmemiz gerekir.
protected/config/main.php:

return array(
    ......
    'components'=>array(
        ......
        'db'=>array(
            'class'=>'CDbConnection',
            'connectionString'=>'mysql:host=localhost;dbname=testdb',
            'username'=>'myusername',
            'password'=>'mypassword',
            'emulatePrepare'=>true,  // YII nin sitesinde bazi SQL sorgulari icin gerekli oldugundan bahsediyor. Muhtemelen parametre iceren SQL sorgularinin dogrudan calistirilmamasi icin kullanilmasi gereken bir parametre.
        ),
    ),
)

Bir de AR sınıflarımızın autoloader a tanıtılması gerekiyor ki PHP new Post() çağrısını aldığında “Post da kim?” demeisn. AR sınıflarımızın protected/models klasörü altında olduğunu varsayarak, konfigürasyonda aşağıdaki değişiklikleri yapmamız gerekir:
protected/config/main.php:

return array(
  ...... 
  'import'=>array(
      'application.models.*',
  ),
  ......
);

Şimdi de tablomuzu temsil edecek AR sınıfını kodlayalım.

class Post extends CActiveRecord
{
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }
 
    public function tableName()
    {
        return 'tbl_post';
    }
}

Not: Eğer konfigürasyonda table prefix tanımlamışsanız tableName() metodu içinde tanımladığınız tablo adını ‘{{post}}’ şeklinde tanımlayabilirsiniz. Bu şekilde yapılan tablo tanımlaması konfigrasyondaki table prefix bilgisinden dolayı otomatik olarak tbl_post şeklinde kullanılacaktır. TablePrefix ile ilgili daha fazla bilgi için bu sayfa yı nceleyebilirsiniz.

AR Sınıflarını Kullanarak INSERT İşlemi Gerçekleştirmek:

Girişde gördüğünüz örnekden anlaşılacağı üzere her bir tablo bir sınıfla, tablodaki her bir alan sınıfın attribute u olarak temsil edilir. Veritabanına yeni bir kayıt oluşturmak için bir adet AR sınıfı instance oluşturup, alanlarınıza verilerinizi eşitledikten sonra save() metodunu çağırmanız yeterlidir. Oluşan yeni kaydın kimliği, primarykey olan field attribute una geri döner. Muhteşem, değil mi ? :)

$post = new Post();
$post->title = 'Sample post';
$post->content = 'Post content';
$post->save();

echo $post->id;

Olur da herhangibir alana veritabanı fonksiyonlarından birinin döndüğü bir değeri set etmek isterseniz :

$post->create_time = CDbExpression('Now()');

AR Sınıflarını Kullanarak SELECT İşlemi Gerçekleştirmek:

Arama işlemleri AR base sınıfı (CActiveRecord) üzerinden gerçekleştirilir. AR sınıflarının base sınıfına ulaşmak için model() metodunu kullanacağız. Aşağıda çeşitli arama şekillerini görüyoruz.

// Belirtilen şarta uygun ilk satırı döner.
$post=Post::model()->find($condition,$params);

// Belirtilen birincil anahtar a sahip (PrimaryKey) kaydı döner.
$post=Post::model()->findByPk($postID,$condition,$params);

// Belirtilen niteliklere uygun ilk satırı döner.
$post=Post::model()->findByAttributes($attributes,$condition,$params);

// SQL cümlesinde verilen şarta uygun kayıtlardan ilk satırı döner.
$post=Post::model()->findBySql($sql,$params);

// Belirtilen şarta uyan tüm satırları döner.
$posts=Post::model()->findAll($condition,$params);

// Belirtilen birincil anahtara uygun tüm kayıtları döner. Pratikte birincil anahtarın tek kayıt ile eşleşmesi beklenir.
$posts=Post::model()->findAllByPk($postIDs,$condition,$params);

//Belirtilen niteliklerle eşleşen tüm kayıtları döner.
$posts=Post::model()->findAllByAttributes($attributes,$condition,$params);

//Belirtilen SQL cümlesine uyan tüm kayıtları döner.
$posts=Post::model()->findAllBySql($sql,$params);

Aslanım ActiveRecord seviyoruz seni. Yukarıda gördüğünüz herbir findXXX metodu arma işleminin gerçekleştiği AR sınıfının bir örneğini yada AR sınıflarından oluşan bir kayıt dizisini döner. Gelin hemen birkaç örnek inceleyelim:

$post = Post::model()->find('id=:id', array(':id' => 10);
echo $pos->id;

condition parametresini isterseniz array(‘id’=>’:id’), isterseniz ‘id=:id’ yok ben öyle de istemiyorum derseniz aşağıdaki şekilde gönderebilirsiniz:

$condition = new CDbCriteria();
$condition->select='title, content';
$condition->condition='id=:id';
$condition->params = array(':id' => 10);

$post = Post::model()->find($condiiton); //Bulursak Post tipinde, bulamazsak null veri döner.

Oldu da birden fazla kayıt dönerse:

$posts = Post::model()->findAll('category_id=:category_id', array(':category_id' => 1));
foreach($posts as $post) {
  echo $post->title;
}

Bir de primary key e göre arayalım.

$post = Post::model()->findByPdk(10);
echo $post->title;

Bir de böyle count’lu exists li işler için aşağıdaki metodlarımız var.

// Belirtilen kriterlere uygun kayit sayisini doner.
$n=Post::model()->count($condition,$params);

// Belirtilen SQL cümlesine uyan kayıtların sayısını döner.
$n=Post::model()->countBySql($sql,$params);

// Belirtilen şartlara uygun kayıt olma durumu ile ilgili mantıksal (boolean:true/false) değer döner.
$exists=Post::model()->exists($condition,$params);

AR Sınıflarını Kullanarak UPDATE İşlemi Gerçekleştirmek:

Update işlemi insert işlemi ile aynıdır. Kaydı bulur, alanlara ilgili verileri yazar, save metodunu çağırırız.

$post = Post::model()->findByPk(1);
$post->title = 'Bu bir denemedir';
$post->save();

Şayet birden fazla kaydı güncellemek istiyorsanız aşağıdaki metodları kullanabilirsiniz:

// belirtilen şartla eşleşen tüm kayıtları günceller.
Post::model()->updateAll($attributes,$condition,$params);

// Belirtilen şartlar ve primary key ile eşleşen tüm kayıtları günceller.
Post::model()->updateByPk($pk,$attributes,$condition,$params);

// Bunu ben de yazarken öğrendim. YII de sayaç olarak atadiginiz alanlari 
// arttirmak için (Örneğin makaleyi okuyan kişi sayısı gibi) saveCounter() 
// ve updateCounter() gibi komutlar varmış. saveCounters(), sadece geçerli AR
// sınıfının sayaç alanlarını güncellerken, updateCounters() metodu birden çok 
// kaydın sayıcılarını güncelleyebiliyormuş.
// Daha detaylı bilgi için bu yazıyı inceleyebilirsiniz: 
// http://www.yiiframework.com/wiki/282/using-counters-with-activerecord/
Post::model()->updateCounters($counters,$condition,$params);

AR Sınıflarını Kullanarak DELETE İşlemi Gerçekleştirmek:

Insert ve Update işlemini gördükten sonra sanırım delete işleminin nasıl yapıldığını tahmin etmeniz çok zor olmamıştır. Kayıt silme işlemi için kaydı bulmamız ve ilgili kaydın AR sınıfından delete() metodunu çağırmamız yeterlidir.

//kaydımızı buluyoruz.
$post = Post::model()->findByPk(1);
//kaydımızı siliyoruz.
$post->delete()

Şayet birden fazla kaydı silmek istiyorsak ActiveRecord bize aşağıdaki metodları sunuyor.

// Belirtilen kriterlere uygun kayıtları siler.
Post::model()->deleteAll($condition,$params);

// Belirtilen birincil anahtar(lar) a uygun kayıt(lar) ı siler.
Post::model()->deleteByPk($pk,$condition,$params);

Bu yazıda temel işlemler dışında çok fazla detaya girmek istemedim. Detaylı ve güncel bilgi için http://www.yiiframework.com/doc/guide/1.1/en/database.ar adresinden yararlanabilirsiniz. ActiveRecord kullanarak ilişkili tablo yapılarında da çalışabilmeniz mümkündür. İlerleyen günlerde bu konuda da bir blog yazısı yayınlayacağım. Her türlü sorunuz veya öneriniz için ibrahimgunduz34(at)gmail.com adresinden bana ulaşabilirsiniz.

Programa Dilleri ve Çatıları

YII ile Basit Veritabanı İşlemleri

Aslında pek üstüne blog yazısı yazmaya deyecek bir konu olduğu söylenemez. :) Hem dağılan kafamızı biraz toparlayalım, hem de konuyu arayan birilerine Türkçe kaynak olsun. Hadi bakalım…

***

YII çatısı altında veritabanı uygulamaları geliştirirken dilerseniz DAO (Data Access Object), dilerseniz ORM (Object Relation Mapping) kullanarak veritabanına erişebilirsiniz.

1. DAO (Data Access Object) Kullanarak Veritabanı İşlemleri Gerçekleştirmek :

1. 1. Veritabanı Bağlantısı Oluşturmak

YII ile veritabanı bağlantısını isterseniz dilediğiniz herhangibir anda başlatıp sonlandırabilir veya doğrudan aplikasyon başladığı anda veritabanı bağlantısını başlatabilirsiniz. DAO nesnesi PDO dan türediği için sunucunuz tarafından desteklenen tüm PDO sürücülerini kullanabilir.

Aşağıdaki örnekte anlık veritabanı bağlantısının nasıl başlatılıp sonlandırıldığını görüyoruz.

$dsn = 'mysql:host=localhost;dbname=testdb';
$username = 'myuser';
$password = 'mypass';
$connection=new CDbConnection($dsn,$username,$password);
$connection->active=true; // veritabani baglantisini aciyoruz...
......
$connection->active=false;  // veritabani baglantisini kapatiyoruz...

Veritabanı bağlantısını uygulama ayağa kalktığında başlatmak için ise veritabanı erişim bilgilerini konfigürasyona yazmanız yeterli.
protected/config/main.php:

array(
    ......
    'components'=>array(
        ......
        'db'=>array(
            'class'=>'CDbConnection',
            'connectionString'=>'mysql:host=localhost;dbname=testdb',
            'username'=>'myusername',
            'password'=>'mypassword',
            'emulatePrepare'=>true,  // YII nin sitesinde bazi SQL sorgulari icin gerekli oldugundan bahsediyor. Muhtemelen parametre iceren SQL sorgularinin dogrudan calistirilmamasi icin kullanilmasi gereken bir parametre.
        ),
    ),
)

Veritabanı bağlantısını ugulama ayağa kalktığında başlattığınızda connection nesnesine aşağıdaki şekilde ulaşabilirsiniz:

$connection = Yii::app()->db;

1. 2. SQL sorgusu çalıştırmak

SQL sorguları, veritabanı bağlantısı üzerinden bir fabrika metodu ile command nesnesinin yaratılıp bu nesnenin execute() edilmesi suretiyle gerçekleştirilir. Aslında bu kullanım şekli, PDOşinas olan arkadaşlarımıza son derece tanıdık gelecektir.

Adi bir select sorgusunu aşağıdaki şekilde çaılştırabilirsiniz.

/* @var $connection CDbConnection */
$connection = Yii::app()->db;
$sqlQuery = 'SELECT `id`, `name`, `amount` FROM `mytable` WHERE `id`=23';
/* @var $command CDbCommand */
$command = $connection->createCommand($sqlQuery);
/* @var $reader CDbDataReader */
$reader = $command->query();
foreach($reader as $row) {
 ...
}

YII, bize bir veritabanı sorgusunu çalıştırabilmemiz için aşağıdaki metodları sunar.

$rowCount=$command->execute();
/*
Bu kullanim, genellikle sonuc beklentisi olmayan 
INSERT, UPDATE, DELETE sorgulari icindir. Calitirildiginda 
sorgu sonucunda etkilenen satir sayisini doner.
*/

$dataReader=$command->query();   
/*
Bu kullanım şeklinde sonuc traversable bir obje olan 
CDbDataReader tipinde döner. Sorgu sonuclari döngü 
ile fetch edilir.
*/

$rows=$command->queryAll();
/*
Bu kullanim seklinde sorgu once calistirilir sonra tum 
sonuclar fetch edilir.
*/

$row=$command->queryRow();
/*
Bu kullanim seklinde sorgu once calistirilir sonra 
sonuca ait ilk satir fetch edilir.
*/

$column=$command->queryColumn(); 
/*
Bu kullanım şeklinde sorgu calistirilir ve sonucun ilk kolonu doner.
*/

$value=$command->queryScalar();  
/*
Bu kullanim sekli sorguyu calistirir ve ilk satirin ilk kolonunu doner.
*/

1. 3. Sorgu sonuçlarının fetch edilmesi

CDbCommand::query() metodu çağırıldığında CDbDataReader tipinde bir örnek üretilir. Sorgu sonuçlarını almak istediğinizde ise döngü içerisinde CDbDataReader::read() metodu tekrarlı olarak çağırılır.

$reader = $command->query();
while($row = $reader->read() ) {...}
foreach($reader as $row) {...}
//Bu kullanim sekli sorgu sonucundaki tum satirlari alir.
$rows = $reader->readAll();

1. 4. Transaction Kullanımı

Üstüne söylenecek çok fazla birşey yok. Sorguları çalıştırmaya başlamadan önce transaction ı başlatır sorguları çalıştırdıktan sonra commit edersiniz. Buyrun kod örneği :

$queries = array();
$queries[] = 'INSERT INTO `mytable` (`id`, `name`, `amount`) VALUES(1, 'zeynep', 100);';
$queries[] = 'INSERT INTO `mytable` (`id`, `name`, `amount`) VALUES(2, 'ayşe', 250);';
$queries[] = 'INSERT INTO `mytable` (`id`, `name`, `amount`) VALUES(3, 'elif', 115);';

$success = true;
$transaction = $connection->beginTransaction();
foreach($queries as $sqlQuery) {
    try {
        $connection->createCommand($sqlQuery)->execute();
    } catch(Exception $e) {
        $transaction->rollback();
        $success = false;
    }
}

if( $success ) {
    $transaction->commit();
}

Bir sonraki yazıda YII ‘nin basit, şirin ORM kütüphanesi ActiveRecord u inceleyeceğiz.
Sevgi, selam ötesi hürmet..

Programa Dilleri ve Çatıları

YII Framework Modülleri Arasında Model Erişimi

Hobi için uğraştığım proje anlaşılan bu ara epey blog yazısı yazmama vesile olacak.

YII framework de modüler bir proje geliştiriyorsanız projenin herhangibir yerinden modül içerisindeki bir modüle ulaşmak için aşağıdaki yolu izleyebilirsiniz.

1- Framework ün yardımcısını kullanarak veya manuel olarak aşağıdaki klasör yapısını oluşturmak suretiyle yeni bir modül oluşturun.

protected/
  modules/
    blog/
      components/
      models/
      views/
      controllers/

2- Güzel… Şimdi konfigürasyon dosyasına (protected/config/main.php) oluşturduğumuz modülü tanımlayalım.

  array('modules' => array(
    ---
    'blog'
  ));

3- Post isimli yeni bir model oluşturun ve bu modeli yeni oluşturduğunuz modülün model klasörüne (protected/modules/blog/model/) Post.php olarak kayıt edin.

class Post
{
  public function newPost()
  {
    ...
  }
}

4- Şimdi de modül sınıfımızı oluşturalım. Bu modülün içine ekleyeceğimiz getPost metodu az önce oluşturduğumuz modele başka modüllerden erişebilme imkanını sağlayacak. Bu sınıfı yeni oluşturduğunuz modül klasörüne BlogModule.php olarak kayıt edin.

class BlogModule extends CModule
{
  public function init()
  {
    $this->setImport(array('blog.models.*',
                           'blog.components.*'));
  }
  
  public function getPost()
  {
    return new Post();
  }
}

Oluşturduğumuz blog modülü dışında, projenin herhangibir yerinde Post modeline ulaşmamız gerektiğinde aşağıdaki şekilde ulaşabiliriz.

$post = Yii::app()->getModule('blog')->getPost();

Hepsi bu. İyi eğlenceler :) .