YII Üzerinde ActiveRecord Kullanımı

Share Button

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.

Share Button

About İbrahim Gündüz

1983 yılında İstanbul’da doğdu. İlkokul yıllarında cobol ve basic le olan tanışması, yazılıma olan ilgisini arttırdı 2005 yılında. Uludağ Üniversitesi Teknik Bilimler Meslek Yüksek Okulu Elektronik bölümünden mezun olan Gündüz, çeşitli alanlarda faaliyet gösteren kurumlarda yazılım geliştirici olarak görev almıştır. Mesleki ilgi alanları, ölçeklenebilir sistemler, uygulama entegrasyonları ve ödeme sistemleridir. Halen Markafoni back end geliştirici olarak çalışmaktadır.

8 Comments

  • ahmet
    Mayıs 5, 2013 - 12:19 am | Permalink

    Activerecord sınıfını sadece YII ile mi kullanabiliyoruz?

  • Murat Yılmaz
    Temmuz 14, 2013 - 8:34 pm | Permalink

    Ben activerecord kütüphanesini zend 1x ile kullandım. Sorgularda herhangi bir sorun yaşamadım. Sizce uzun vadede , yada proje büyüklüğüne göre sorun çıkarırmı ? Bildiğim kadarı ile activerecord kendini kanıtlamış bir kütüphane…

    • Temmuz 16, 2013 - 8:29 pm | Permalink

      Eğer standart işler yapıyorsanız bence activerecord uzun vadede ihtiyaçlarınızı karşılayacaktır. Hem bu tarz kütüphaneler veri katmanını soyutlayarak proje genelinde cachleme yada büyük yapısal değişiklikler yapmanızı kolaylaştırır. Bence activerecord tarafından çalışan sorgularınızı bir şekilde profile edip darboğaz oluşturan sorgularınızı optimize edebilirsiniz.

      Ayrıca vakit bulduğunuzda symfony2 üzerinde Doctrine orm kütüphanesini incelemenizi de öneririm.

  • Pingback: Data Provider Nedir? | Fatih GÜRSOY

  • Nahita
    Haziran 25, 2014 - 11:03 am | Permalink

    $post = Post::model()->find(‘id=:id’, array(‘:id’ => 10); bu satırı açıklar mısınız.Benim asıl öğrenmek istediğim “=:” ve ya “:id’ => 10” gibi ifadede iki nokta ve eşittirler ne anlama geliyor.

    • Haziran 25, 2014 - 1:46 pm | Permalink

      Selamlar.
      O sorguda gördüğünüz :id ifadesini placeholder olarak düşünün. find metodunun ikinci argümanı olarak gönderilen dizideki :id anahtarına karşılk gelen değer ile değiştirilir. >= 10 sorgusu için >=:id kullanabilirsiniz.

  • Bir Cevap Yazın

    E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir