我有一堆模型,它们之间设置了各种关联,似乎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' => ''
)
);
}
?>
这就是它的重点。为简洁起见,我删除了验证 代码。
非常感谢!
答案 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()错误地提交未在该函数调用本身中启动的事务的问题。
答案 3 :(得分:0)
在设置id和save / find之前尝试坚持$ this-ModelName-&gt; create()。所有这一切都清楚任何其他数据。有点黑客,但如果它有效可以为真正的问题提供一些线索。
答案 4 :(得分:0)
我在过去的几个月里一直在学习CakePHP,这种事偶尔会让我发疯。 dogmatic关于在你的调用之前使用 - &gt; create()的评论如果你在函数中早先使用过该模型会有所帮助,它会重置模型的内部状态,因此陈旧的值不会干扰。这可能不是你的问题。
我同意yvover和bancer这可能是一个关系问题。发布模型(或代码链接)将是一个很大的帮助。在开发过程中不止一次抓住我的事情是,当我因为名称不匹配而实际编辑其他内容时,我正在编辑类的模型,因此没有反映更改,因为我的“模型”从未加载过。