Perde arkası: Nasıl bir ORM "düşünmek" nedir?

4 Cevap php

Ben Raylar ActiveRecord, PHP için Doktrini (ve benzer ORMs) arkasında bazı tasarım ilgileniyorum.

  • Bunlar genellikle işe beklenen nasıl bir ORM zincirleme erişimcilerden ve ne kadar derin gibi özellikleri gerçekleştirmek için yönetir?
  • Nasıl bir ORM içten sorguları oluşturmak mı?
  • Bunun beklenen tüm bu keyfi doğasını sürdürürken nasıl bir ORM sorguları yönetir?

Açıkçası bu akademik bir soru, ama tüm cevapları doğaya bekliyoruz!

(Seçim Benim dil OO PHP5.3 değildir!)

4 Cevap

Zincirli yöntem çağrıları hepsi OOP'deki yerde kullanılan konum, ORM soruya diktir. Bir zincir-mümkün yöntem sadece dönüş değeri denir izin vererek, mevcut nesnenin bir başvuru verir. PHP

class A {
	public function b() {
		...
		return $this;
	}

	public function c($param) {
		...
		return $this;
	}		
}


$foo = new A();
$foo->b()->c('one');
// chaining is equivilant to
// $foo = $foo->b();
// $foo = $foo->c();

Sorguları nasıl inşa edildiği gibi, iki yöntem vardır. ActiveRecord yılında ORMs gibi Veri tabanlarının meta verileri inceler kod var. Çoğu veritabanı bu meta-verileri görüntülemek için komutları gibi SQL veya SQL çeşit vardır. (MySQL en DESCRIBE TABLE, Oracle'ın USER_TAB_COLUMNS masa, vs)

Bazı ORMS'nin böyle YAML gibi nötr bir dil veritabanı tabloları tarif var. Diğerleri (Django bunu yapar söylemek istiyorum, ama ben ona baktım çünkü bir süre oldu) ve nesne modelleri oluşturduk şekilde bir veritabanı yapısını anlaması olabilir. Son olarak orada önceki iki tekniklerden birini kullanılan melez bir yaklaşım, ama ayrı bir araç tarafından otomatik olarak YAML / etc oluşturmak için sağlanmıştır. ya da sınıf dosyaları.

Bir masanın bir isimleri ve veri tipleri o pragmatik tüm satırları, ya da belirli bir ölçüte uyan satır belirli bir kümesi döndüren bir SQL sorgusu yazmak oldukça kolay, bilinmektedir.

Son sorunuza gelince,

How does an ORM manage the queries while sustaining the arbitrary nature of all that is expected of it?

Ben cevap "çok iyi olmadığını" iddia ediyorum. Eğer bir tablo, bir nesne metafor ötesine geçerse, her ORM SQL sorguları nesneleri modellemek için nasıl kullanılması gerektiği gibi farklı bir yaklaşım, bir felsefe vardır. Soyut olsa, sadece ORM varsayımları (yani Zend_Db_Table en "findManyToManyRowset" yöntemi) dayalı sorgular inşa yeni yöntemler ekleyerek kadar basit

Bunlar genellikle işe beklenen nasıl bir ORM zincirleme erişimcilerden ve ne kadar derin gibi özellikleri gerçekleştirmek için yönetir?

Kimse bu cevap gibi görünüyor. Ben hızlı Doktrin PHP yapar nasıl açıklayabilirsiniz.

Doktrin olarak, bir nesne modeline bakın alanların hiçbiri aslında o sınıf için tanımlanmıştır. Yani örnekte, $ araç-> sahipleri, 'sahiplerinin $ otomobilin sınıfında tanımlanan denilen hiçbir gerçek bir alan vardır.

Bunun yerine, ORM __get and __set gibi sihirli yöntemler kullanır. Eğer $ araba-> rengi gibi bir ifade kullanmak çok zaman, içten PHP Doctrine_Record # __get ('renk') çağırır.

Bu noktada, her durumda gerekli ORM bu karşılamak için serbesttir. Olası tasarımları bir yeri vardır burada. Bu, örneğin $ _values ​​denilen bir dizide bu değerleri depolamak ve daha sonra dönebilirsiniz $ this-> _values ​​['color']. Özellikle parça değil sadece her kayıt için değerler değil, aynı zamanda veritabanı sebat onun durumu göreceli olarak doktrin.

Sezgisel değil bu bir örneği Doktrini ilişkileri ile. Eğer $ arabaya bir başvuru olsun, 'sahipleri' olarak adlandırılan insanlar tabloya bir ilişki vardır. Yani $ araba> sahipleri için veri aslında $ arabanın kendisi için veriden ayrı bir tabloda saklanır. Yani ORM, iki seçeneğiniz vardır:

  1. Bir $ kullanıcıyı yüklerken her seferinde, ORM otomatik olarak ilgili tüm tabloları katılır ve nesnenin içine bu bilgileri doldurur. Eğer $ araba-> sahipleri yaptığınızda, bu veriler var zaten. Nesneleri birçok ilişkileri olabilir, ve bu İlişkiler İlişkiler kendilerini olabilir, çünkü bu yöntem, ancak yavaş. Yani a lot of joins ekleyerek olurdu ve mutlaka bile bu bilgiyi kullanarak değil.
  2. Bir $ kullanıcı yüklemek her zaman, alanlar Kullanıcı tablosundan yüklenen ve onları doldurur olan ORM bildirimler, ancak ilgili tablolardan yüklenen tüm alanları yüklenmez. Bunun yerine, bazı meta olma olarak işaretlemek için bu alanlara bağlı 'yüklü değil, ama mevcut' dir. Eğer ifade $ araç-> sahipleri yazarken şimdi, ORM 'sahiplerinin ilişki yüklenmiş olmadığını görür, ve o, bu bilgi almak nesnesinin içine ekleyin ve sonra bu verileri döndürmek için ayrı bir sorgu verir. Bu, tüm Bunu gerçekleştirmek için gerek kalmadan şeffaf olur.

# 1 orta karmaşıklığı ile herhangi bir gerçek üretim yeri için ağır olur beri Tabii ki, Doktrin, 2. kullanır. Ama aynı zamanda yan etkileri vardır. Eğer $ arabada birkaç ilişkilerini kullanarak iseniz erişmek, sonra Doktrin, her birinin ayrı ayrı yükleyecektir. Böylece belki de sadece 1 gerekli olduğunda 5-6 sorguları çalıştıran sonunda.

Doktrin Eğer Doktrin Query Language kullanarak bu durumu optimize sağlar. Eğer bir araba nesnesi yüklemek istediğiniz DQL anlatmak değil, aynı zamanda vb sahipleri, üreticiler, başlıklar, rehin, onu katılmak ve bu nesnelerin içine tüm veriler yükler.

Yaşasın! Uzun yanıt. Temel olarak, olsa da, kalbinde kazanılmış "bir ORM amacı nedir?" ve "Neden birini kullanmak gerekir?" ORM bize çoğu zaman nesne modunda düşünmeye devam etmesini sağlar, ancak soyutlama mükemmel değildir ve soyutlama sızıntı performans cezalar gibi çıkıp eğilimindedir.

Ben size ilginç olabilecek bir PHP DataMapper binanın konuyla ilgili bir sunum yarattı. Ben PHP kullanıcı grubu için orada sunulan zaman Oklahoma City Coworking İşbirlikçi videoda kaydedildi:

Video: http://blip.tv/file/2249586/

Presentation Slides: http://www.slideshare.net/vlucas/building-data-mapper-php5-presentation

Bir sürü beri değişmiş olsa sunum, temelde phpDataMapper erken kavramı oldu.

Onlar biraz daha iyi ORMs iç işleyişini anlamak yardımcı umuyoruz.

Zincirli erişimciler gerçekten büyük bir anlaşma değildir: return $this setter yöntemi. Boom, bitti, istediğiniz gibi pek çok seviyede çalışır.