Модель CakePHP использует неправильные поля в операторах SQL! - PullRequest
2 голосов
/ 15 ноября 2010

У меня есть куча моделей с различными ассоциациями, установленными между ними, и кажется, что Cakephp время от времени выполняет неверный оператор SQL и приводит к тому, что MySQL прекратит работу.

Например, если у меня есть две модели, Комментарий и Тег и код, подобный этому:

$this->Comment->id = 5;
$this->Comment->saveField('read_count', 3);

дает оператор SQL:

UPDATE comments SET read_count = 3 WHERE Tag.id = 3;

Это не происходит постоянно, но в конечном итоге это происходит, потому что я делаю все по кругу.

Пожалуйста, помогите. Это действительно заставляет меня усомниться в моем решении пойти с Cake, так как это звучит плохо.

Спасибо.

РЕДАКТИРОВАТЬ 1 Я только что столкнулся с проблемой, и вот неисправный SQL:

SELECT COUNT(*) AS `count` FROM `albums_songs` AS `AlbumSong`   WHERE `ArtistGenre`.`id` = 26482

AlbumSong и ArtistGenre - две совершенно разные таблицы, и они вообще не связаны между собой.

РЕДАКТИРОВАТЬ 2 Просто столкнулся с очередной неудачей. Код:

$this->Song->find('first', array('conditions' => array('Song.artist_id' => 30188, 'Song.name' => 'Pal Pal (By.Tarkhanz)'), 'fields' => array('Song.id')))

Пока генерируется SQL:

SELECT `Song`.`id` FROM `songs` AS `Song`   WHERE `Artist`.`name` = 'Annie Villeneuve'    LIMIT 1 

Как вы можете видеть, что не было условий, я должен указать Artist.name, но сгенерированный SQL смотрит на него.

РЕДАКТИРОВАТЬ 3 Еще один пример неудачи. Вызов осуществляется следующим образом:

$this->Song->id = $song_id;
$library_count = $this->Song->field('Song.library_count');

Тем не менее, SQL:

SELECT `Song`.`library_count` FROM `songs` AS `Song`   WHERE `Artist`.`name` = 'Mazikana_Ragheb_Allama'    LIMIT 1

, где Artist.name не является столбцом песни, поскольку принадлежит модели Artist.

Спасибо.

РЕДАКТИРОВАТЬ 4

models/album.php

    <?php
    class Album extends AppModel {
            var $name = 'Album';
            var $belongsTo = array(
                    'Artist' => array(
                            'className' => 'Artist',
                            'foreignKey' => 'artist_id',
                            'conditions' => '',
                            'fields' => '',
                            'order' => ''
                    )
            );

            var $hasAndBelongsToMany = array(
                    'Song' => array(
                            'className' => 'Song',
                            'joinTable' => 'albums_songs',
                            'foreignKey' => 'album_id',
                            'associationForeignKey' => 'song_id',
                            'unique' => true,
                            'conditions' => '',
                            'fields' => '',
                            'order' => '',
                            'limit' => '',
                            'offset' => '',
                            'finderQuery' => '',
                            'deleteQuery' => '',
                            'insertQuery' => ''
                    )
            );

            var $hasMany = array(
                    'AlbumSong' => array(
                            'className' => 'AlbumSong',
                            'foreignKey' => 'album_id',
                            'dependent' => false,
                            'conditions' => '',
                            'fields' => '',
                            'order' => '',
                            'limit' => '',
                            'offset' => '',
                            'exclusive' => '',
                            'finderQuery' => '',
                            'counterQuery' => ''
                    )
            );
    }

    ?>

    models/album_song.php

    <?php
    class AlbumSong extends AppModel {
            var $name = 'AlbumSong';
            var $useTable = 'albums_songs';
            var $belongsTo = array(
                    'Song' => array(
                            'className' => 'Song',
                            'foreignKey' => 'song_id',
                            'conditions' => '',
                            'fields' => '',
                            'order' => ''
                    ),
                    'Album' => array(
                            'className' => 'Album',
                            'foreignKey' => 'album_id',
                            'conditions' => '',
                            'fields' => '',
                            'order' => ''
                    )
            );
    }

    ?>

    models/artist.php
    <?php
    class Artist extends AppModel {
            var $name = 'Artist';
            var $hasMany = array(
                    'Album' => array(
                            'className' => 'Album',
                            'foreignKey' => 'artist_id',
                            'dependent' => false,
                            'conditions' => '',
                            'fields' => '',
                            'order' => '',
                            'limit' => '',
                            'offset' => '',
                            'exclusive' => '',
                            'finderQuery' => '',
                            'counterQuery' => ''
                    ),
                    'Song' => array(
                            'className' => 'Song',
                            'foreignKey' => 'artist_id',
                            'dependent' => false,
                            'conditions' => '',
                            'fields' => '',
                            'order' => '',
                            'limit' => '',
                            'offset' => '',
                            'exclusive' => '',
                            'finderQuery' => '',
                            'counterQuery' => ''
                    ),
                    'ArtistGenre' => array(
                            'className' => 'ArtistGenre',
                            'foreignKey' => 'artist_id',
                            'dependent' => false,
                            'conditions' => '',
                            'fields' => '',
                            'order' => '',
                            'limit' => '',
                            'offset' => '',
                            'exclusive' => '',
                            'finderQuery' => '',
                            'counterQuery' => ''
                    )
            );
    }

    ?>

    models/artist_genre.php

    <?php
    class ArtistGenre extends AppModel {
            var $name = 'ArtistGenre';
            var $useTable = 'artists_genres';
            var $belongsTo = array(
                    'Artist' => array(
                            'className' => 'Artist',
                            'foreignKey' => 'artist_id',
                            'conditions' => '',
                            'fields' => '',
                            'order' => ''
                    ),
                    'Genre' => array(
                            'className' => 'Genre',
                            'foreignKey' => 'genre_id',
                            'conditions' => '',
                            'fields' => '',
                            'order' => ''
                    )
            );
    }

    ?>

    models/genre.php

    <?php
    class Genre extends AppModel {
            var $name = 'Genre';
            var $hasAndBelongsToMany = array(
                    'Artist' => array(
                            'className' => 'Artist',
                            'joinTable' => 'artists_genres',
                            'foreignKey' => 'genre_id',
                            'associationForeignKey' => 'artist_id',
                            'unique' => true,
                            'conditions' => '',
                            'fields' => '',
                            'order' => '',
                            'limit' => '',
                            'offset' => '',
                            'finderQuery' => '',
                            'deleteQuery' => '',
                            'insertQuery' => ''
                    )
            );

            var $hasMany = array(
                    'ArtistGenre' => array(
                            'className' => 'ArtistGenre',
                            'foreignKey' => 'genre_id',
                            'dependent' => false,
                            'conditions' => '',
                            'fields' => '',
                            'order' => '',
                            'limit' => '',
                            'offset' => '',
                            'exclusive' => '',
                            'finderQuery' => '',
                            'counterQuery' => ''
                    )
            );
    }

    ?>

    models/song.php

    <?php
    class Song extends AppModel {
            var $name = 'Song';
            var $belongsTo = array(
                    'Artist' => array(
                            'className' => 'Artist',
                            'foreignKey' => 'artist_id',
                            'conditions' => '',
                            'fields' => '',
                            'order' => ''
                    )
            );
            /*
            var $hasAndBelongsToMany = array(
                    'Album' => array(
                            'className' => 'Album',
                            'joinTable' => 'albums_songs',
                            'foreignKey' => 'song_id',
                            'associationForeignKey' => 'album_id',
                            'unique' => true,
                            'conditions' => '',
                            'fields' => '',
                            'order' => '',
                            'limit' => '',
                            'offset' => '',
                            'finderQuery' => '',
                            'deleteQuery' => '',
                            'insertQuery' => ''
                    )
            );
            */
            var $hasMany = array(
                    'AlbumSong' => array(
                            'className' => 'AlbumSong',
                            'foreignKey' => 'song_id',
                            'dependent' => false,
                            'conditions' => '',
                            'fields' => '',
                            'order' => '',
                            'limit' => '',
                            'offset' => '',
                            'exclusive' => '',
                            'finderQuery' => '',
                            'counterQuery' => ''
                    )
            );
    }

    ?>

Это в значительной степени так. Ради краткости я убрал валидацию Код.

Большое спасибо!

Ответы [ 5 ]

1 голос
/ 07 ноября 2013

У меня, возможно, была такая же проблема. Проблема, с которой я столкнулся, была коллизия кеша в реализации кеширования условий (т. Е. Предложения WHERE) анализируемого sql.

Для торта 1.3 результаты DboSource::conditions() и DboSource::name() кэшируются по умолчанию. см .: DboSource . Кэш использует алгоритм хэширования crc32, который имеет более высокую вероятность коллизий. Кроме того, выполнение запросов в узком цикле также может увеличить вероятность столкновения. Это может объяснить, почему у вас не совпадают имена таблиц в виде

select * from `table_A` where `table_B`.`field` ...

Решением было установить источник данных, чтобы он не выполнял это кэширование. Итак, попробуйте

$ds = $this->Comment->getDataSource();
$ds->cacheMethods = false;

перед использованием методов, которые генерируют операторы sql.

0 голосов
/ 22 ноября 2010

За последние несколько месяцев я изучал CakePHP, и подобные вещи иногда сводили меня с ума.Комментарий Dogmatic об использовании -> create () перед вызовом может помочь, если вы ранее использовали эту модель в своей функции, он сбросит внутреннее состояние модели, чтобы устаревшие значения не мешали.Это не может быть вашей проблемой.

Я согласен с Ивовер и Бансером, что это, вероятно, проблема отношений.Размещение ваших моделей (или ссылки на код) будет большой помощью.Во время разработки меня несколько раз поймало то, что я редактировал модель для класса, когда фактически редактировал что-то еще из-за несоответствия имени, поэтому изменения не были отражены, потому что моя «модель» никогда не загружалась.

0 голосов
/ 16 ноября 2010

Не уверен, имеет ли эта ошибка какое-либо отношение к ней, какую версию вы используете:

[eb76ab9] Исправлена ​​ошибка, из-за которой Model :: saveAll () некорректно фиксировала транзакцию, которая не была запущена в самом вызове этой функции.

http://cakephp.org/changelogs/1.3.6

0 голосов
/ 22 ноября 2010

попробуйте прикрепить $ this-ModelName-> create () перед тем, как установить идентификатор и сохранить / найти.все, что делает, это очищает любые другие данные, которые находятся вокруг.немного взломать, но если это сработает, может дать некоторые подсказки для реальной проблемы.

0 голосов
/ 15 ноября 2010

Убедитесь, что у вас нет ничего подобного:

class Tag extends AppModel
{
    public $belongsTo = array (
        'Comment' => array(
            'conditions' => array(
                'id' => 3, // Will add this condition on every query.
            ),
        )
    );
}
...