【问题标题】:CakePHP 2.2.4: Why does this Union $this->Model->query not work?CakePHP 2.2.4:为什么这个 Union $this->Model->query 不起作用?
【发布时间】:2013-02-22 14:20:12
【问题描述】:

我在 PhotosController.php 的视图操作中。我想要做的是给定我正在查看的当前照片的 id,创建一个照片轮播,其中包含当前照片之前的两张照片和当前照片之后的两张照片,当前照片在中间(总共 5 张)。

我被指向this solution,但我似乎无法使用 $this->Photo->query 将其转换为 CakePHP。

我的控制器

$this->set('photos', $this->Photo->query("
    SELECT id, file FROM photos WHERE id <= $id AND page_id = $page_id ORDER BY id DESC LIMIT 3 
    UNION ALL
    SELECT id, file FROM photos WHERE id > $id AND page_id = $page_id ORDER BY id ASC LIMIT 2
"));

不幸的是,当我打开调试时什么都看不到。 id、file 和 page_id 都是 photos 表中的列。 #id 和 $page_id 都从路由器传递给操作。我的语法错了吗?

编辑:如果我删除 UNION ALL 和第二个 SELECT 语句,则查询工作正常,因此模型未加载不是问题,因为它是。

编辑(解决方法):目前我正在执行两个不理想的查询。

$this->set('photos_before', $this->Photo->find('all', array(
    'conditions' => array(
        'Photo.page_id' => $page_id,
        'Photo.id <' => $id
    ),
    'order' => array('Photo.id ASC'),
    'limit' => 2
)));

$this->set('photos_after', $this->Photo->find('all', array(
    'conditions' => array(
        'Photo.page_id' => $page_id,
        'Photo.id >' => $id
    ),
    'order' => array('Photo.id ASC'),
    'limit' => 2
)));

我之前有一个包含只返回我需要的字段和关联模型。

下面是我想要显示的内容,它目前可以使用上面的两个查询,但我希望这可以通过一个对 Cake 友好的查询来实现

【问题讨论】:

  • 你创建了模型照片吗?
  • 执行查询时是否出现错误?
  • 是的照片是模特。在呈现我的其余视图时执行查询时似乎没有错误,只有包含查询的部分显示“发生内部错误”
  • 如果开启调试,生成的SQL是什么?您是否尝试过在 MySQL 中运行该 SQL(例如通过 PhpMyAdmin)。此外,您使用的是低级“查询”方法,它不处理任何转义,所以请非常小心以防止 SQL 注入!

标签: mysql cakephp union cakephp-2.1


【解决方案1】:

我的猜测是您的原始查询是无效的 SQL。 Afaik UNIONS 不能包含多个“order by”子句。作为一种解决方法,您可以考虑重写它以使用如下子查询:

SELECT * FROM (SELECT id, file FROM photos WHERE id <= $id AND page_id = $page_id ORDER BY id DESC LIMIT 3) AS suba
UNION ALL
SELECT * FROM (SELECT id, file FROM photos WHERE id > $id AND page_id = $page_id ORDER BY id ASC LIMIT 2) AS subb

虽然我认真地认为这样的查询远非最佳。当然,我不知道您的应用程序的工作方式,但似乎带有 OFFSET/LIMIT 的标准分页查询是一种更合乎逻辑的方法。

请考虑我在您问题下方的评论;使用模型->查询不会自动处理清理/转义以防止 SQL 注入!

【讨论】:

  • 此查询有效,唯一的问题是说我正在查看 Photo.id = 71,查询结果按以下 ID 顺序显示:71、70、69、72, 73. 如果我将“suba”更改为 ORDER BY id ASC,则 ID 的顺序为:1、2、3、72、73。第一个示例包含正确的 ID,但顺序不正确。我正在寻找这个订单:69、70、71、72、73。请参阅我的编辑“解决方法”。它以正确的顺序显示正确的 ID,但它是两个单独的查询。
  • 好的,所以在“subb”之后,我在整个联合中添加了一个 ORDER BY id ASC 并且它按预期工作。您的意见,我应该使用 this->Photo->query 还是我的两个单独的查询?哪个性能更好?
  • 我会尝试在没有这种复杂查询的情况下实现这一目标。我看到了您添加的屏幕截图,我猜您希望每个“节目”显示 5 张图片。这将是类似的东西;显示-> hasMany->图片。然后选择节目并对图片进行分页,'page'大小为5?
  • 我有页面(显示,还有其他娱乐类别)有很多照片,其中有很多评论,但您的建议不适用于我的应用程序。我不是每页显示 5 张照片,而是每张照片最多显示 5 张照片。我也不确定这是否重要,但我已经在照片缩略图下分页了 cmets。不确定您是否可以在同一个视图中有两个不同的分页列表?
  • 您显示的屏幕截图,是否属于“页面”(例如,有人选择了“dexter”页面,还是仅显示“任何”照片?这 5 张照片是否“相关”任何方式?如果没有,“主要”照片是如何选择的?例如,主要照片是从“列表”还是通过“节目”选择的?
【解决方案2】:

您必须将模型加载为

  $this->loadModel('Photo');

执行查询之前。

【讨论】:

  • 我必须这样做,即使我在默认情况下已经使用 Photo 模型的 PhotoController 的内部?
  • 实际上,我什至在页面顶部有var $uses = array('Photo', 'PhotoSetting');,所以模型已经加载了。
【解决方案3】:

您应该在 MySQL 中创建一个 VIEW,然后将其用作模型,并在其上执行传统的 CakePHP 查找。

阅读在 MySQL 中创建视图,然后根据该视图名称创建模型。

【讨论】:

  • 能否请您发布指向相关烹饪书条目或其他指南的链接?谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-06
  • 2013-03-10
相关资源
最近更新 更多