CakePHP HABTM ilişkileri benzersiz yapma

4 Cevap php

Ben bir HABTM ilişki içinde olan Kitap ve Tag olarak adlandırılan iki model, var. Bir çift (kitap, etiket) sadece bir kez kaydedilmesini istiyorum. Benim modellerde ben var

var $hasAndBelongsToMany = array(
    'Tag' => array(
        'className' => 'Tag',
        'joinTable' => 'books_tags',
        'foreignKey' => 'book_id',
        'associationForeignKey' => 'tag_id',
        'unique' => true
    )
);

ve tam tersi, ama Benzersiz bayrağı bana yardım etmez; Hala iki kez aynı çift kaydedebilirsiniz.

CakePHP Bunu nasıl yaparsınız? Ben doğrudan veritabanında çift (kitap, etiket) eşsiz beyan etmelidir, ya da bu CakePHP fındık gitmek yapacak? Bu durumun üstesinden gelmek için bir Cakey yolu var mı?

DÜZENLEME: (Ben MySQL kullanıyorum) sorgu ile çift benzersiz yapmaya çalıştık

ALTER TABLE books_tags ADD UNIQUE (book_id,tag_id);

ama bu iyi çalışmaz. Bir kerede birden fazla etiket kaydettiğinizde tüm çiftler yeni iseniz, her şey iyi gider. Çiftlerin en az bir tekrarlanırsa, CakePHP tüm işlemi yapmak için başarısız, bu yüzden HERHANGİ yeni çift (hatta iyi olanlar) kaydetmek değildir.

4 Cevap

Kek genellikle HABTM verileri kaydeder yolu HABTM tablosundan model için varolan tüm verileri silme ve save() içine yem veri diziden yeniden tüm ilişkileri ekleyerek gereğidir. Eğer sadece HABTM ilişki ile başa çıkmak için bu şekilde kullanıyorsanız, bir sorun olmamalıdır.

Tabii ki, her zaman ideal bir yol değil. HABTM masaya doğrulama zorlamak için, bu böyle, bunun için model oluşturmak ve bazı özel doğrulama eklemek gerekir:

class BooksTag extends AppModel {

    var $validate = array(
        'book_id' => array('rule' => 'uniqueCombi'),
        'tag_id'  => array('rule' => 'uniqueCombi')
    );

    function uniqueCombi() {
        $combi = array(
            "{$this->alias}.book_id" => $this->data[$this->alias]['book_id'],
            "{$this->alias}.tag_id"  => $this->data[$this->alias]['tag_id']
        );
        return $this->isUnique($combi, false);
    }

}

Sadece saveAll($data, array('validate' => 'first')) doğrulama tetiklemek için kullanarak verileri kaydetmek emin olun.

Sen may ilişkide açıkça BooksTag modelini belirtmeniz gerekir:

var $hasAndBelongsToMany = array(
    'Tag' => array(
        ...
        'with' => 'BooksTag'
    )
);

Ayrıca DB düzeyinde benzersizliği zorlanarak olduğunuzu üstüne, tüm iyi.

Benim düşünceme göre, veri gereksinimleri var any zaman, bu gereksinimleri verileri (taban) düzeyinde belirtilmelidir. Mümkün olan en düşük düzeyde kurallarını uygulamak. Uygulama hem de bu kuralları uygulamak olabilir, ve bunu yapmayı seçerseniz, o zaman ben zarar veremezler söyleyebilirim. Gerçi, veri kısıtlamaları dayatmanın tek aracı gibi bir uygulama kullanarak karşı tavsiye ediyorum.

Ben veritabanı şeması kısıtlama koymak öneriyoruz. Eğer birincil anahtar olarak birleştirilen sütunları beyan eğer ben bu pasta bazı sorunlara neden olacağını düşünüyorum, ancak kolay olurdu.

Kullandığınız RDBMS hangi bağlı olarak, bir birleşik satır dizini oluşturmak ve bu konuda eşsiz bir kısıtlama bildirmek mümkün olabilir.

Diğer seçenek, Cake bu mantığı tutmak için, ilk geçirilen veriler üzerinde) (a find çalışır, böylece Kitap modelinde BeforeSave () işlevini değiştirmek olacaktır, ve find (yani yanlış döndürür yalnızca kurtaracak hiçbir önceki çifti) benzersiz kısıtlama yerine getirdim anlamı vardır.

Ben söz yok bir seçenek çalışır, ama olabilir gibi görünüyor olacak, CakePHP Sayaç Önbellek davranış olacaktır. Bu habtm ile varsayılan olarak çalışır, ama burada pasta kitap (http://book.cakephp.org/view/816/counterCache-Cache-your-count) için bağlantı ve yapacak addon link emin değil o habtm ile çalışmak (http://bakery.cakephp.org/articles/view/counter-cache-behavior-for-habtm-relations)

Hackish yol:

(Yukarıdaki gibi) üçüncü bir DB alan olabilir eğer ilk iki bir MD5 hash EŞSİZ bir varchar (32) yapmak.

Hepiniz olmak için kaydeder değiştirmek olurdu $md5_unique_field = md5( $field_one.$field_two );

CakePHP özel bir doğrulama ya da otomatik olarak bu yapabileceği özel bir modeldir uzantısı için izin verebilir.

Bu da olsa DB düzeyde uygulanması gerektiğini, ve CakePHP hataları yakalamak gerektiğini kabul ediyoruz.