CakePHP - HABTM 分页查询问题

发布于 2024-10-31 19:39:01 字数 1556 浏览 7 评论 0原文

餐厅

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'
    )
);

Tables

restaurants
cuisines
cuisines_restaurants

Both restaurant and cuisine model are set up to HABTM each other.

I'm trying to get a paginated list of restaurants where Cuisine.name = 'italian' (example), but keep getting this error:

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

Actual query it's building:

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

The "....." parts are just additional fields I removed to shorten the query to show you.

I'm no CakePHP pro, so hopefully there's some glaring error. I'm calling the paginate like this:

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

$opts is an array of options, one of which is 'Cuisine.name' => 'italian'

I also tried setting $this->Restaurant->recursive = 2; but that didn't seem to do anything (and I assume I shouldn't have to do that?)

Any help or direction is greatly appreciated.


EDIT

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'
    )
);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

晨曦慕雪 2024-11-07 19:39:01

正如我的这篇博文中所解释的,您有将相关模型的条件放入分页数组的 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'));

As explained in this blogpost by me you have to put the condition of the related model in the contain option of your pagination array.

So something like this should work

# 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'));
浪菊怪哟 2024-11-07 19:39:01

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

正如 @vindia 此处 所解释的,使用 < href="http://book.cakephp.org/view/1323/Containable" rel="noreferrer">Containable 行为通常可以解决这个问题,但是它不适用于分页

基本上,您需要一种方法来强制 Cake 在第一次查询期间查看 Cuisine。这不是框架通常做事的方式,所以不幸的是,它需要 手动构建连接
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
);

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

This fails because Cake is actually using 2 different queries to generate your result set. As you've noticed, the first query doesn't even contain a reference to Cuisine.

As @vindia explained here, using the Containable behavior will usually fix this problem, but it doesn't work with Paginate.

Basically, you need a way to force Cake to look at Cuisine during the first query. This is not the way the framework usually does things, so it does, unfortunately, require constructing the join manually
. paginate takes the same options as Model->find('all'). Here, we need to use the joins option.

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
);

This solution is a lot clunkier than the others, but has the advantage of working.

失退 2024-11-07 19:39:01

我脑海中浮现出几个想法:

祝你好运!

a few ideas on the top of my mind:

good luck!

蓝天白云 2024-11-07 19:39:01

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

Cuisine must be a table (or alias) on the FROM clausule of your SELECT.
so the error:
1054: Unknown column 'Cuisine.name' in 'where clause'
Is just because it isn't referenced on the FROM clausule

丿*梦醉红颜 2024-11-07 19:39:01

如果您删除餐厅模型中 HABTM 链接的功能和事件部分,它还能工作吗?
在我看来,您似乎未能为 Cuisine 模型定义正确的主键和外键,因为 HABTM 模型甚至没有在您在此处发布的查询中包含 Cuisine 选项卡。

If you remove the Feature and Event part of your HABTM link in the Restaurant model, does it work then?
Sounds to me like you've failed to define the right primary and foreing keys for the Cuisine model, as the HABTM model is not even including the Cuisine tabel in the query you posted here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文