【问题标题】:CakePHP - problem with HABTM paginate queryCakePHP - HABTM 分页查询的问题
【发布时间】:2011-08-05 02:04:51
【问题描述】:

表格

restaurants
cuisines
cuisines_restaurants

餐厅和美食模型相互设置为HABTM。

我正在尝试获取 Cuisine.name = 'italian'(示例)的餐厅的分页列表,但不断收到此错误:

1054: Unknown column 'Cuisine.name' in 'where clause'

它正在构建的实际查询:

SELECT `Restaurant`.`id`, `Restaurant`.`type` ..... 
`Restaurant`.`modified`, `Restaurant`.`user_id`, `User`.`display_name`,
`User`.`username`, `User`.`id`, `City`.`id`,`City`.`lat`  ..... 
FROM `restaurants` AS `Restaurant` LEFT JOIN `users` AS `User` ON 
(`Restaurant`.`user_id` = `User`.`id`) LEFT JOIN `cities` AS `City` ON 
(`Restaurant`.`city_id` = `City`.`id`) WHERE `Cuisine`.`name` = 'italian' 
LIMIT 10

“.....”部分只是我删除的附加字段,以缩短向您展示的查询。

我不是 CakePHP 专业人士,所以希望有一些明显的错误。我这样称呼分页:

$this->paginate = array(
    'conditions' => $opts,
    'limit' => 10,
);
$data = $this->paginate('Restaurant');
$this->set('data', $data);

$opts 是一个选项数组,其中一个是 'Cuisine.name' => 'italian'

我也尝试设置 $this->Restaurant->recursive = 2;但这似乎没有任何作用(我认为我不应该这样做?)

非常感谢任何帮助或指导。


编辑

models/cuisine.php
    var $hasAndBelongsToMany = array('Restaurant');

models/restaurant.php
    var $hasAndBelongsToMany = array(
    'Cuisine' => array(
        'order' => 'Cuisine.name ASC'
    ),
    'Feature' => array(
        'order' => 'Feature.name ASC'
    ),
    'Event' => array(
        'order' => 'Event.start_date ASC'
    )
);

【问题讨论】:

    标签: php cakephp cakephp-1.3 has-and-belongs-to-many


    【解决方案1】:

    这会失败,因为 Cake 实际上是使用 2 个不同的查询来生成您的结果集。正如您所注意到的,第一个查询甚至不包含对美食的引用。

    正如@vindia 解释的here,使用Containable 行为通常可以解决此问题,但它不适用于Paginate

    基本上,您需要一种方法来强制 Cake 在第一次查询期间查看美食。这不是框架通常做事的方式,所以不幸的是,它需要constructing the join manually . paginate 采用与 Model->find('all') 相同的选项。在这里,我们需要使用joins 选项。

    var $joins = array(
        array(
            'table' => '(SELECT cuisines.id, cuisines.name, cuisines_restaurants.restaurant_id
                     FROM cuisines_restaurants 
                     JOIN cuisines ON cuisines_restaurants.cuisines_id = cuisines.id)',
            'alias' => 'Cuisine',
            'conditions' => array(
                'Cuisine.restaurant_id = Restaurant.id',
                'Cuisine.name = "italian"'
            )
        )
    );
    
    $this->paginate = array(
        'conditions' => $opts,
        'limit' => 10,
        'joins' => $joins
    );
    

    此解决方案比其他解决方案笨重得多,但具有工作的优势。

    【讨论】:

    • 我已经可以让菜品名称出现在我的分页结果中,而无需使用任何手写 JOIN - 问题在于尝试按菜品字段排序。您的解决方案适用于此吗?如果是这样 - 你有没有机会编辑你的答案/解释如何?提前谢谢!
    • @Dave - 在你的问题中,它仍然说整个查询失败并出现错误Unknown Column。问题是出现了美食但未正确订购,还是当您尝试按美食订购时整个查询中断?
    • CakePHP 在基于表关系运行 paginate() 时会创建大量查询。其中一个查询会提取必要的美食数据(因此餐厅列表会在其名称旁边显示其各自的美食)。问题是,我需要根据他们的美食来检索餐厅——当前查询实际上会拉出我尝试执行的餐厅,这会给出错误,因为该查询中不包含美食。通用美食数据在另一个查询中被提取得很好。我需要像“WHERE Cuisine.name='italian'”这样的东西,这是澄清还是混淆了更多?
    • 好的,有道理。所以是的,我认为上面的解决方案会帮助你。 joins 选项将强制您指定的任何表加入到分页运行的 first 查询中 - 即当前不包含 Cuisine 的表。
    • 如果没有 SQL 错误,我无法让您的答案正常工作 - 其中之一是:1064:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取正确的语法,以便在第 1 行的“cuisines Cuisine Array LEFT JOIN users AS User ON (Restaurant.user_id = ' at line 1
    【解决方案2】:

    如果您在 Restaurant 模型中删除 HABTM 链接的 Feature 和 Event 部分,它会起作用吗? 在我看来,您没有为 Cuisine 模型定义正确的主键和外键,因为 HABTM 模型甚至不包括您在此处发布的查询中的 Cuisine 表。

    【讨论】:

    • 我 95% 确定我的关系是正确的——我在分页结果中得到了美食名称——它在单独的查询中运行(由 Cake 创建)。问题是,Cake 的做法(运行单独的查询以获取相关信息)不允许我按给定的美食检索餐馆。
    【解决方案3】:

    Cuisine 必须是 SELECT 的 FROM 子句中的表(或别名)。 所以错误:
    1054:“where 子句”中的未知列“Cuisine.name”
    只是因为它没有在 FROM 子句中引用

    【讨论】:

    • 对...我认为这是显而易见的部分 - 问题是如何添加它或让它通过 CakePHP 工作。
    • 我只会给你解决方法和问题:CakePHP 有接受原始 sql 语句的方法吗?你能参考一下吗?为什么它会为“城市”和“用户”生成“左连接”?他们在哪里被提及?
    • 非常感谢您的帮助。此问题现已得到解答。
    【解决方案4】:

    正如this blogpost by me 中所述,您必须将相关模型的条件放在分页数组的contain 选项中。

    所以这样的事情应该可以工作

    # in your restaurant_controller.php
    var $paginate = array(
        'contain' => array(
            'Cuisine' => array(
                'conditions' => array('Cuisine.name' => 'italian')
            )
        ),
        'limit' => 10
    );
    
    # then, in your method (ie. index.php)
    $this->set('restaurants', $this->paginate('Restaurant'));
    

    【讨论】:

    • 优秀的解决方案。我更新了您的帖子以将数组包含在您的 var $paginate 中。我已经确认这适用于一些测试代码。做得很好!
    • 听起来这正是我想要的——我会在今天或明天试一试,并在我开始工作时将其标记为答案——谢谢!
    • 它似乎没有工作 - 它甚至没有在查询中的任何地方添加“意大利语”:(
    • 我周末不在家,但我可以在星期一找你。我会及时通知你。
    • 根据 declan(下面的答案),包含不适用于分页。我希望他是错的,但是 - 你的博客没有提到分页,我无法让它工作,所以我倾向于认为他是对的 - 有什么想法吗?
    【解决方案5】:

    我的一些想法:

    祝你好运!

    【讨论】:

    • 我假设我的 HABTM 是正确的(将它们添加到原始帖子中)。至于其余的,我宁愿不必解决 - 我想让它按预期的方式正常工作。
    • 当我进行正常查询时,没有“Cuisine.name”=>“italian”,它工作正常 - 我的美食通过在 a 中引用 $restaurant['Cuisine'] 显示在页面上foreach($data as $restaurant) 循环
    • 尝试向 habtm 关系添加更多信息:诸如“joinTable”、“foreignKey”和“associationForeignKey”等信息
    • 有这样做的理由吗?如果您正确命名所有内容,我的印象是过度/不必要的。
    • 试过 - 同样的问题。我可以在查询中看到问题 - 它根本没有加入 Cuisine,那么它如何获得 Cuisine.name?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    相关资源
    最近更新 更多