CakePHP模型在SQL语句中使用了错误的字段!

时间:2010-11-15 17:53:37

标签: mysql cakephp cakephp-1.3

我有一堆模型,它们之间设置了各种关联,似乎Cakephp有时执行不正确的SQL语句并导致MySQL进行barf。

例如,如果我有两个模型,Comment和Tag以及类似的代码:

$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不是Song的一列,因为它属于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 个答案:

答案 0 :(得分:1)

我可能遇到过同样的问题。我遇到的问题是在缓存已解析的sql的条件(即WHERE子句)的cake的实现中缓存冲突。

对于cake 1.3,默认情况下会缓存DboSource::conditions()DboSource::name()的结果。见:DboSource。缓存使用crc32散列算法,该算法具有更高的冲突机会。此外,在紧密循环中运行查询也会增加冲突的可能性。这可以解释为什么你的表名不匹配

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

解决方案是将数据源设置为不执行此缓存。所以,试试

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

在使用生成sql语句的方法之前。

答案 1 :(得分:0)

确保没有这样的东西:

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

答案 2 :(得分:0)

不确定这个bug是否与它有关,你在运行什么版本:

[eb76ab9]修复了Model :: saveAll()错误地提交未在该函数调用本身中启动的事务的问题。

http://cakephp.org/changelogs/1.3.6

答案 3 :(得分:0)

在设置id和save / find之前尝试坚持$ this-ModelName-&gt; create()。所有这一切都清楚任何其他数据。有点黑客,但如果它有效可以为真正的问题提供一些线索。

答案 4 :(得分:0)

我在过去的几个月里一直在学习CakePHP,这种事偶尔会让我发疯。 dogmatic关于在你的调用之前使用 - &gt; create()的评论如果你在函数中早先使用过该模型会有所帮助,它会重置模型的内部状态,因此陈旧的值不会干扰。这可能不是你的问题。

我同意yvover和bancer这可能是一个关系问题。发布模型(或代码链接)将是一个很大的帮助。在开发过程中不止一次抓住我的事情是,当我因为名称不匹配而实际编辑其他内容时,我正在编辑类的模型,因此没有反映更改,因为我的“模型”从未加载过。