2011-11-22 33 views
6

CakePHP'de İçeren Davranışı kullanmaya çalışırken biraz zaman geçirdim, ancak beklediğim gibi çalışamıyorum.CakePHP: Çok düzeyli İçindekiler Kullanılabilir Davranışı Kullanma

Uygulamam farklı ama basitleştirmek için bu örneği koyacağım. Konu ve etkinliklerle bir forumum olduğunu ve etkinliklerin değerlendirilebileceğini varsayalım. genel ilişkiler olacaktır:

Forum: hasMany [Konu]
Konu: belongsTo [Forum], hasMany [Etkinlik]
Etkinlik: belongsTo [Konu], hasMany [Derecelendirme]
Değerlendirme: belongsTo [Etkinlik]

Elde etmek istediğim, bulma yöntemini kullanarak belirli bir forumda gerçekleştirilen tüm derecelendirmeleri elde etmektir.

$this->Rating->find('count', array(
    'contain' => array(
     'Activity' => array(
      'Thread' 
     ) 
    ), 
    'conditions' => array(
     'Thread.forum_id' => 1 
    ) 
)); 

Ama sonuç sorgusu: Ne yapılmalı varsayalım şudur

SELECT COUNT(*) AS `count` FROM `ratings` AS `Rating` LEFT JOIN `activities` AS `Activity` ON (`Rating`.`activity_id` = `Activity`.`id`) WHERE `Thread`.`forum_id` = 1; 

Ben 'katıldı' seçeneğini kullanarak bu başardığımı, ama daha karmaşık ve ben gerek Birçok durumda bu tür eylemleri kullanın. Örneğin ilgili

tüm dosyalar burada bulabilirsiniz: http://dl.dropbox.com/u/3285746/StackOverflow-ContainableBehavior.rar

Teşekkür

Güncelleme

23.11.2011 Moz Morris cevaplara çerçevesini ve teşekkür araştırdıktan sonra ve api55 Sorunun kaynağını buldum.

Temel sorun, CakePHP'yi anladığım kadarıyla, her seferinde katılımları kullanarak sorgulamayı düşündüğüydü.

SELECT * FROM Rating JOIN Activity... 
SELECT * FROM Activity JOIN Thread... 
SELECT * FROM Activity JOIN Thread... 
... 

tüm faaliyetlerini almak için bir sorgu yapacağını Anlamı: o bunu yapmaz o şey, gerçek operasyon böyle bir şey olurdu aradığım sonucu elde etmek gerçekleştireceklerini ve sonra, her aktivite için, Konuları elde etmek için bir sorgu gerçekleştirin ... İçeren Davranış Davranışı yanlış kullanıldığından değil, tüm koşullara 'koşullar' seçeneği uygulandığından ve ilkinde yaklaşımım başarısız oldu. Konu tablosunun yokluğu nedeniyle çöktü.

  • api55 o Konu tablosu kullanılarak sorulara sadece bunları uygulamak istiyorum 'karakterini' dizisi içindeki koşulları kullanarak, söylediği gibi: Bu out bulduktan sonra iki olası çözüm vardır. Ama bunu yapmak sorun devam ediyor, çünkü çok fazla sorumuz var.

  • Moz Morris'in dediği gibi, Thread modelinin Derecelendirmeye bağlanması da işe yarayacak ve istediğimiz şey tek bir sorgu gerçekleştirecektir. Sorun şu ki, ilişkilerin modellerini atlayan ve CakePHP felsefesini takip etmeyen bir yama olarak görüyorum.

Api55 çözümünü doğru olarak işaretledim çünkü bu benim yaptığım somut problemi çözdü, ancak her ikisi de problemi çözdü.

cevap

5

Her şeyden önce, actAs değişken değişkenini appModel'e yerleştirdiniz mi ??o olmadan bu beahaviour hiç işe yaramayacaktır (iş parçacığıyla ilişkili olmadığından doğru çalışmadığını görüyorum)

Bunu forumdan kastediyorum. (Eğer forum ya da iş parçacığı istediğiniz emin değilim) ve tüm derecelendirme olsun, eğer rating yok boş değerlendirme puanı ile biterse. Bu değerin dizisini almak için özü:

$this->Rating->Activity->Thread->Forum->find('count', array(
    'contain' => array(
     'Thread' => array(
      'Activity' => array(
       'Rating' => array (
         'fields' => array ('Rating.*') 
       ) 
      ) 
     ) 
    ), 
    'conditions' => array(
     'Forum.id' => 1 
    ) 
)); 

Sonra değerlendirme tablosunda yalnızca bir değer gerekirse bu

appModel

public $actsAs = array('Containable'); 

derece kontrolörü gibi

şey sadece ayarla kullanmak . Bunu yaptığı gibi

BT zaten işe GEREKEN ama forum_id orada kullanmamayı sugest ancak koşullarda içeride Ayrıca, bu

'contain' => array(
    'Activity' => array(
     'Thread' => array(
       'conditions' => array('Thread.forum_id' => 1) 
     ) 
    ) 
), 

gibi içerirler, (containable behaviuor kullanarak modelinde actsAs değişkeni asla unutma veya uygulama modelinde)

+0

İş parçacığı dizisindeki 'koşulların' işlenmesi işe yaramayacaktır çünkü sonuçlar 'Thread' dizisi boşken her şey için yine de döndürülecektir. –

+0

@MozMorris thats true, çünkü birleşimden ayrıldı ... ama eğer en üstünden (forumdan/thread'dan) koşuyorsa, tüm notları veya boşluğu alacaktır, ancak çok can sıkıcı bir ağacınız olacak (genellikle linkable kullanıyorum) davranış) – api55

+0

Yanıtladığınız için teşekkür ederiz. Bağlantıda sağladığım kod üzerinde denedim ve sorgu, SELECT COUNT (*) forumları AS Forum WHERE Forum.id = 1' olarak kabul edildi. AppModel'de ve her şeyde bulunan İçeren Davranışlar zaten var. Bazı yapılandırma sorunum veya bir şey var mı bilmiyorum, ancak düzgün çalışmıyor gibi görünüyor. –

2

api55'in çözümünü beğeniyorum, sanırım sonuçlar biraz dağınık - tahmin ettiğim verilerle ne yapmak istediğinize bağlı.

ben olduğunu varsayalım bu yöntemi kullanarak bahsediyorduk 'katıldı' yöntemiyle dediğinde:

$this->Rating->bindModel(array(
    'belongsTo' => array(
    'Thread' => array(
     'foreignKey' => false, 
     'conditions' => 'Thread.id = Activity.thread_id', 
    ), 
    'Forum' => array(
     'foreignKey' => false, 
     'conditions' => 'Forum.id = Thread.forum_id' 
    ) 
) 
)); 

$ratings = $this->Rating->find('all', array(
    'conditions' => array(
    'Forum.id' => 1 // insert forum id here 
) 
)); 

Bu sadece bana biraz daha temiz görünüyor ve kullanmakta konusunda endişelenmenize gerek yok AppModel'inizde tutarsız davranış. Dikkate değer.

+0

Sayıma ihtiyacınız varsa, o zaman 'all' i 'count' ile değiştirin. :) –

+0

Hiç XD değil ama onun temiz onun temizleyici, diğer yol birçok özyinelemelere verdiğini düşündüm ... – api55

+0

Cevabınız için teşekkür ederim, bu örnek üzerinde çalışacaktı. Sorun şu ki, gerçek uygulamada bunu birçok kez yapmak zorundayım ve bunu daha modüler yapmak istiyorum (kullanmak için "etkin" modeller içeren bir diziye sahip olmak). Söylediklerinizi yaparak, her seferinde tüm koşulları da ayarlamalıyım. Ayrıca, çalışmamın beni rahatsız ediyor, İçinde Davranış Davranışının olması gerekiyordu, bir şey eksik mi bilmiyorum. Yine de teşekkür ederim. –