06.Symfony Doctrine — Giriş

06.Symfony Doctrine — Giriş

Merhaba. Bu yazımda sizlere Doctrine ile İlişkisel veritabanları ve NoSQL veritabanları arasında ki bağlantıyı anlatacağım. Doctrine nedir, ilişkisel veritabanlarından neleri destekler, ilişkisel olmayan, NoSQL veritabanlarından hangilerine destek verir, Doctrine nin çalışma mantığı nedir, mimarisi nasıldır veya benzeri sorulara yanıt vermeye çalışacağım. En sonunda ise Symfony Doctrine giriş yapacağız.

Piyasada birçok veritabanı yönetim sistemi (DBMS) bulunmaktadır. Bu sistemler iki gruba ayrılabilir: verileri sorgulamak ve değiştirmek için SQL dilini kullanan geleneksel ilişkisel veri tabanları ve verilere erişmek ve yönetmek için sadece “SQL değil” yöntemleri kullanan NoSQL veritabanları. Her belirli projede, yetenekleri ve rekabet avantajları nedeniyle bazı DBMS’yi tercih edebilirsiniz. Seçiminize göre, Hangi veritabanı ile çalışacağınız bir çok şey değiştirebilir. Burayı biraz daha açalım.

İlişkisel Veritabanları – Relational Databases

İlişkisel bir veritabanında, satırlardan oluşan bir tablo (ilişkiler) koleksiyonunuz var. Bir satırda bir veya birkaç sütun olabilir. Bir tablonun bir satırı (veya birkaç satırı) başka bir tablonun bir satırına (veya birkaç satırına) bağlanabilir, böylece veriler arasında bir ilişki oluşturulabilir.
 
Örneğin, veritabanında iki tablo içeren bir blog web siteniz olduğunu varsayalım: yazılarınızın, makalelerinizin tutulduğu post ve kullanıcıların yorumlarının tutulduğu comment tablosu olsun. Post tablonuzda id, title, content, author, date_created; ve comment tablonuzda ise id, post_id, author, content, ve date_created olsun. post tablosu, yorum tablosuyla One-To-Many olarak ilişkilidir, çünkü belirli bir yorum yalnızca tek bir yazıya ait olabilirken, bir yazı/post sıfır veya daha fazla (çok) yoruma sahip olabilir. Daha da açık yazarsak, bir yazıya birden fazla kişi yorum bırakabilir.

Grafik olarak, yukarıda belirtilen tablolar, sütunları ve ilişkileri aşağıdaki resimde görebilirsiniz.

Piyasada, bir dizi önemli ilişkisel veritabanları vardır. Bunların arasında en çok bilinenler: SQLite, MySQL, MariaDB, PostgreSQL, Oracle, Microsoft SQL Server vb. Her veritabanı sistemi, DBMS’ye özgü ve diğer sistemlerin parçası olmayan kendi özelliklerine sahiptir. Örneğin:
SQLite:
PHP motorunun embed uzantısı olarak tasarlanmıştır ve kurulum gerektirmez, ancak yalnızca basit siteler için de çalışır.
MySQL/MariaDB:
Kurulumda ve yönetimde çok basit ve küçükten orta seviyeye değişen sistemlerde kullanmak için iyi bir ücretsiz sistemdir
Ticari Oracle DBMS:
Büyük ölçüde büyük ölçekli sistemleri hedef almaktadır ve gelişmiş yönetim araçlarına sahiptir;
PostgreSQL:
Sınırsız büyük veritabanlarını destekler ve Oracle’ın açık kaynaklı bir yedek olarak kabul edilebilir.


Doctrine kitaplığı, birleşik bir programlama arabirimi kullanarak tüm önemli veritabanları ile çalışacak şekilde tasarlanmıştır. Bu programlama arabirimi iki seviyede uygulanmaktadır.

1. Alt düzeydeki Doctrine, desteklenen herhangi bir ilişkisel veritabanına SQL sorguları oluşturmak ve veritabanı şemasını değiştirmek için birleşik mekanizma sağlar. Bu mekanizmaya, Veritabanı Soyutlama Katmanı (DBAL – Database Abstraction Layer) bileşeninde uygulanmaktadır. Bizim için önemli çünkü, böylece biz veritabanlarına insert, delete update ve benzeri komutları yazmıyoruz. Bunu Doctrine yapıyor. Biz bu işlemler için PHP Class larını çağırıyoruz. Böylece her veritabanının nin kendi dialectine uygun(kendine özgü ) SQL kodu yazmaktan kurtulmuş oluyoruz. Örneğin şunu düşünün, MySQL ile işe başladınız ama projenizin ortasında PostgreSQL ‘e yada Oracle ‘a geçmeniz gerekti. Eğer sorgularımızı, RAW SQL olarak yazsaydık, tüm sorgularımızı elden geçirmemiz gerekecekti. Daha da kötü senaryo şu, ya aynı anda 2 farklı müşteriniz iki farklı veritabanı kullansaydı? Birisi küçük ölçekli MySQL yetiyor diyelim, ama diğeri çok büyük ölçekli ve Oracle kullanmanız gerekiyor diyelim. Veritabanı Soyutlama Katmanı bu nedenle önemli. Böyle durumlarda minimum değişiklik yada efor ile kurtulmamızı sağlıyor. Veritabanı değişti diye, tüm projeyi baştan yazmıyoruz. Doctrine sorgularımızı seçilen veritabanına göre, kendisi otomatik olarak oluşturuyor. Umarım ne demek istediğimi size anlatabildim.

2. Üst düzeydeki Doctrine, Doctrine’in Nesne İlişkisel Eşleştiricisi (ORM) bileşeni, tabloları PHP Sınıflarına eşleyerek veritabanı verilerini nesne yönelimli olarak sorgulama ve yönetme olanağı sağlar. Bu bileşen ayrıca, nesne yönelimli stilde sorgular oluşturmak için DQL(Doctrine Query Language) adlı özel veritabanı sorgu dili de sağlar.


Genellikle bizler, üst düzey ORM bileşeni tarafından sağlanan API leri kullanılırız. Fakat bazen ihtiyaçlarımız değişebilir ve daha özel sorgular yazmak durumunda kalabiliriz, böyle durumlarda DBAL bileşeniyle kolayca çalışabiliriz.


 
Bir ilişkisel veritabanı sistemi kullanırken, genellikle SQL dilini, veritabanı verisine erişmek ve veritabanı şemasını yönetmek için standart bir yol olarak kullanırız. Bununla birlikte, her DBMS’in genellikle kendi özel SQL dil uzantıları vardır.

Yukarıda Doctrine i ikiye ayırdık bunlar Alt Düzey Doctrine ve Üst Düzey Doctrine. Yazımda bir kaç yerde geçti, eğer Doctrine ‘i araştırdıysanız başka sitelerde de görmüşsünüzdür. Genel de Doctrin ‘e Doctrine Kitaplığı (Doctrine components) da deriz. Eğer ilişkisel Veritabanı kullanıyorsak, bu kitaplıkta nelerin bulunduğuna aşağıda ki resimde bakabilirsiniz.


Yukarıda ki resimde de görülebileceği gibi Doctrine ‘nin TEMELİ, PHP Engine özelliklerine ve aslında belirli veritabanı yönetim sistemlerine sürücü olarak kullanılan PHP – PDO uzantılarına dayanmaktadır.

PHP Engine ve PHP – PDO katmanın üzerinde, diğer üst düzey bileşenler için temel işlevsellik sağlayan ana Doctrine bileşenleri (Annotations, Common, Cache, Migrations vs) vardır. DBAL bileşeni veritabanı türü soyutlama katmanı sağlar. Ve bunların hepsinin en üstünde de , nesne odaklı bir şekilde veri ile çalışmak için ORM bileşeni var.


Yukarıda ki resme bakıp, Doctrine ve Component leri/Bileşenleri hakkında bir fikir sahibi olabiliriz. Örneğin Cache i gördüğüm için, Doctrine de Cache desteği vardır. Cache diyince aklımıza APC-APCU – Redis – MemCache – XCache gelir. Eğer bilgimi bir kenara bırakıp yorum yapsaydim, bunlardan birine yada bir kaçına destek verdiğini söylerdim.

Aşağıda ki kodu incelerseniz eğer, cache olarak array kullandığını görürsünüz. ( Örnek Doctrine YAML/Ayar Dosyası )

doctrine:
    orm:
        auto_mapping: true
        # the standard distribution overrides this to be true in debug, false otherwise
        auto_generate_proxy_classes: false
        proxy_namespace: Proxies
        proxy_dir: '%kernel.cache_dir%/doctrine/orm/Proxies'
        default_entity_manager: default
        metadata_cache_driver: array
        query_cache_driver: array
        result_cache_driver: array

Aşağıda ki kodu incelerseniz eğer, cache olarak apc-apcu kullandığını görürsünüz. ( Örnek Doctrine YAML/Ayar Dosyası )

doctrine:
    dbal:
        driver:   pdo_mysql
        host:     "%database_host%"
        port:     "%database_port%"
        dbname:   "%database_name%"
        user:     "%database_user%"
        password: "%database_password%"
        charset: utf8mb4
        default_table_options:
            charset: utf8mb4
            collate: utf8mb4_unicode_ci
    orm:
        metadata_cache_driver: apcu
        query_cache_driver: apcu
        auto_generate_proxy_classes: "%kernel.debug%"
        naming_strategy: doctrine.orm.naming_strategy.underscore
        auto_mapping: true

Aşağıda ki kodu incelerseniz eğer, cache olarak apc-apcu ve MemCache kullandığını görürsünüz. ( Örnek Doctrine YAML/Ayar Dosyası )

doctrine:
    orm:
        auto_mapping: true
        metadata_cache_driver: apc
        query_cache_driver:
            type: service
            id: my_doctrine_common_cache_service
        result_cache_driver:
            type: memcache
            host: localhost
            port: 11211
            instance_class: Memcache

Örnekler çoğaltılabilir. Aynı şekilde Doctrine ‘ de Migration da var. İleri de değineceğiz. Özetle yukarıda ki resim size Doctrine hakkında bir fikir verebilir.

İlişkisel Olmayan Veritabanları – NoSQL Databases

İlişkisel bir veritabanı sisteminin aksine, bir NoSQL veritabanı sistemi – adından da anlaşılacağı gibi – veriye erişmek için sadece bir SQL yöntemi kullanmaz. Bu, her NoSQL sisteminin, verilere erişmek ve bu verilerin manipüle edilmesi için kendi özel yöntemlerini ve API’lerini sağlayabileceği anlamına gelir. Bu kısmı çok uzatmayacağım. NoSQL sistemleri arasında en bilinenleri MongoDB, Doctrine, bir dizi NoSQL veritabanını destekler: MongoDB, CouchDB, OrientDB ve PHPCR bunlardan bazılarıdır.

Symfony Doctrine

Herhangi bir PHP uygulamasının en yaygın ve en zorlu görevlerinden biri, veritabanı işlemleridir. Symfony Framework, veritabanlarıyla çalışacak herhangi bir bileşeni entegre etmese de, Doctrine adlı bir üçüncü parti kütüphaneye sıkı entegrasyon sağlar. Doctrine in tek amacı, veritabanı etkileşimlerini kolay ve esnek yapmak için size güçlü araçlar vermektir. Yukarıda da belirttiğim üzere, Symfony de veritabanı işlemleri için, bir bileşen yoktur. Bunun yerine Symfony Doctrine denilen üçüncü parti uygulamaya full destek verir.

Symfony ile Doctrine i birleştirirsek. composer.json dosyanıza bakarsanız şunun gibi bir satır görürsünüz.

"require": {
        "symfony/orm-pack": "*",
        .......................
    },

Yukarıda gördüğünüz symfony/orm-pack aslında 2 ader eklentiyi temsil ediyor. Bunlar Doctrine ORM ve üzerine Doctrine Bundle geliyor. Doctrine Bundle size Symfony ‘de Annotations, DBAL yada Doctrine Cache gibi Doctrine bileşenlerinize destek sağlıyor. Hazır yeri gelmişken Symfony Doctrine için resmi sitesine/dökümanına da bakabilirsiniz.

 

Yukarıda da belirttiğim üzere, Symfony Doctrine adlı üçüncü partı uygulamay sıkı destek verir. composer.json dosyasında bulunan Doctrine Bundle, Symfony ile Doctrine arasında köprü vazifesi görür. Aslında bu destek bir çok uygulama için yeterli gelse de, arttırılabilir. Örneğin Symfony Doctrine Fixtures Bundle ile Fixture desteği sağlanırken aynı şekilde Symfony Doctrine Migrations Bundle ile de Migration desteği sağlanır. Bunların dışında da bir çok Component vardır. Zamanla işin içine girdikçe, ihtiyaçlarınıza göre, componentleri/bileşenleri araştıracak, öğrenip kullanacaksınız.

ÖZET

Bu yazımda sizlere, Doctrine kitaplık mimarisi ve bileşenleri(Doctrine library architecture and components) ile ilgili genel bilgilerden bahsettim. Doctrine, çoğunlukla veri kalıcılığını hedefleyen birden fazla bileşenden oluşan büyük bir projedir.

Piyasada, geleneksel ilişkisel veritabanları ve NoSQL veritabanları olmak üzere iki büyük veritabanı yönetimi sistemi grubu vardır.

Birçok ilişkisel veritabanı, sorgu yapmak ve verileri değiştirmek için SQL dili kullansa da, her belirli veritabanı sistemi kendi özel sorgu/SQL yapısına sahiptir. Aynı şey, NoSQL veritabanları içinde geçerlidir.

Doctrine , sofistike soyutlama katmanları sağlayarak(Database Abstraction Layer) veritabanı ayırt etmeden, teorikte, tüm veritabanları ile çalışabilir. Teorikte diyorum çünkü, yukarıda ki resme bakarsanız, en nihayetinde Doctrine PHP Engin ve PDO lar üzerine kurulmuştur. Başka bir değişle, PDO-Driver ları var ise, Doctrine ile o veritabanı yönete bilirsiniz. İster İlişkisel bir veritabanı olsun, ister NoSQL bir veritabanı olsun.


Yukarıda ki kısım bu yazının anahtarı. Sadece bunu anlamamız bile yeterli. Bu kısmı az daha açıp, bu yazıyı sonlandıracağım. Bu kısım Doctrine ‘nin çalışma mantığını anlatır. Kısaca Mapping. Aşağıda ki resme bakar ve Post tablosu için konuşursak eğer.

— Veritabanın daki post tablosunun Doctrine ‘de ki karşığı bir adet Post Sınıfı ( Php Class ). Ki biz buna Model, Symfony ve Doctrine de Entity deriz.

— Veritabanınımız da post tablosun da bulunan id, title, content, author, date_created alanları ise Doctrine ‘de ki Post Sınıfının elemanlarıdır.


Bu yazımı burada sonlandırıyorum. Genelde insanlar/diğer blog siteleri minimum 500, maksimum 1500 kelimelik makaleler çıkarır. Böylece ortaya hem bolca içerik, hem de daha hızlı okunan, tüketilen yazılar çıkar. Ben ise her seferinde kısa yaz diye kendimi tembihlediğim halde, ortaya çok uzun yazılar çıkıyor. Bu da şunu gösteriyor ki, hala iyi bir blogger değilim 🙂
 
Uzun yazı nedeniyle umarım okurken sıkılmadınız. Bir sonra ki yazım meselenin bam teli olan Entity ler üzerine olacak. Görüşmek dileği ile.