带有无用条目的 CakePhp 可包含查询

Posted

技术标签:

【中文标题】带有无用条目的 CakePhp 可包含查询【英文标题】:CakePhp containable query with useless entries 【发布时间】:2012-11-10 20:29:47 【问题描述】:

我卡在 Cakephp 中使用可包含行为的查询。 所以我有 - 型号订购HABTM产品

我想接受特定州的订单以及在特定餐厅至少有一种产品的订单。

为了让您更好地理解,这里是架构的样子

(int) 110 => array(
    'Order' => array(
        'id' => '10',
        'customer_id' => '3',
        'state_id' => '6',
        'payment_id' => '3',
        'created' => '2012-11-10 12:23:03',
        'user_id' => '10',
        'date_delivery' => '2012-10-12 20:30:00',
        'km' => '2.76'
    ),
    'Product' => array(
        (int) 0 => array(
            'id' => '51',
            'category_id' => '2',
            'restaurant_id' => '10001',
            'title' => 'aaa',
            'description' => 'aaa',
            'price' => '8.2',
            'tva_id' => '2',
            'img' => 'aaa',
            'maj_img' => '2012-10-24 15:38:56',
            'ProductsOrder' => array(
                'id' => '57',
                'product_id' => '51',
                'order_id' => '10',
                'quantity' => '1',
                'price' => '8.2',
                'tva_id' => '2',
                'meal' => null
            )
)))

(ProductsOrder 是连接表)

所以,我正在使用可包含的行为,这是我的查询:

$q = $this->Order->find('all', array(
        'conditions' => array(
            'Order.date_delivery BETWEEN ? AND ?' => array($dateDebut->format('Y-m-d H:i:s'), $dateFin->format('Y-m-d H:i:s')),
            'Order.state_id' => array(6, 8)),
        'order' => 'Order.date_delivery',
        'contain' => array(
            'Product' => array(
                'conditions' => array('Product.restaurant_id' => $id),
            )
        )
            ));

问题是查询的结果返回了一些我不想要的条目。 这是一个示例,它是结果查询的一部分,并且假设不存在。 注意 Product 是一个空数组。

109 => array(
    'Order' => array(
        'id' => '179',
        'customer_id' => '139',
        'state_id' => '6',
        'payment_id' => '3',
        'created' => '2012-11-18 22:29:16',
        'user_id' => '10',
        'date_delivery' => '2012-10-12 20:00:00',
        'coursier_id' => '19',
        'comment' => '',
        'km' => '10.7'
    ),
    'Product' => array()

如果你知道如何解决这个问题,你可以救我... 谢谢

编辑转储 SQL

选择 COUNT(*) AS count FROM live_resto_manager.restaurants AS Restaurant WHERE Restaurant.id = 10001

选择Order.id, Order.customer_id, Order.state_id, Order.payment_id, Order.@9876544340@.@9876544341@.@98 @,Orderdate_deliveryOrdercoursier_idOrdercommentOrderkm FROM live_resto_managerorders AS Order WHERE Orderdate_delivery 在 '2012-10-01 00:00:00' 和 '2012-10-31 23:59:00' 和 Order.state_id 在 (6, 8) 之间订购 Order.@ 987654359@ASC

选择Product.id, Product.category_id, Product.restaurant_id, Product.title, Product.price.@9876547369@.@89 @,Product.tva_id,Product.img,Product.maj_img,ProductsOrder.id,ProductsOrder.product_id,product_id,@987654382. ProductsOrderquantityProductsOrderpriceProductsOrdertva_idProductsOrdermeal FROM live_resto_managerproducts AS Product JOIN live_resto_managerproducts_orders AS ProductsOrder ON (ProductsOrder.order_id IN (99, 100, 102, 105, 101, 103, 104, 1, 58, 3, 106, 108, 2, 31, 107, 109, 110, 111, 59, 112, 114, 115, 117, 118, 61, 113, 33, 116, 60, 119, 120, 121, 122, 4, 62, 34, 123, 63, 124, 125, 5, 6, 126, 129, 127, 128, 130, 131, 133, 132, 134, 135, 138, 137, 139, 140, 141, 64, 136, 142, 143, 35, 36, 37, 144, 145, 146, 147、149、148、150、151、152、153、7、154、155、65、156、158、159、161、8、157、162、160、163、9、165、166、66、164、 168、38、167、169、39、170、171、172、173、67 , 174, 175, 68, 69, 176, 177, 178, 179, 10, 40, 180, 181, 182, 192, 183, 184, 186, 187, 70, 185, 189, 190, 12, 188, 191 , 193, 13, 14, 41, 194, 11, 195, 15, 71, 196, 197, 200, 201, 72, 198, 199, 202, 16, 73, 203, 42, 204, 205, 74, 206 , 207, 208, 209, 43, 210, 212, 44, 211, 45, 17, 76, 213, 214, 215, 75, 77, 216, 78, 217, 218, 219, 79, 220, 221, 222 , 223, 80, 224, 46, 225, 81, 18, 229, 233, 226, 227, 228, 230, 231, 232, 234, 47, 236, 235, 237, 238, 239, 19, 242, 243 , 244, 48, 49, 50, 240, 241, 245, 20, 51, 246, 247, 248, 250, 251, 253, 254, 256, 257, 258, 260, 262, 252, 255, 82, 249 , 259, 261, 263, 265, 264, 266, 267, 83, 84, 269, 85, 268, 270, 271, 86, 272, 21, 87, 274, 273, 275, 90, 276, 277, 88 , 89, 278, 279, 280, 281, 282, 284, 285, 287, 288, 283, 91, 22, 286, 289, 290, 294, 298, 24, 291, 292, 295, 296, 297, 25 , 52, 92, 93, 23, 299, 300, 301, 302, 53, 32, 303, 304, 305, 306, 309, 307, 308, 54, 94, 293, 55, 310, 312, 311, 313 , 314, 316, 315, 317, 318, 319, 95, 320, 321, 96, 56, 26, 32 2, 325, 323, 324, 326, 328, 329, 330, 327, 97, 27, 28, 29, 30, 98, 331, 333, 332, 334, 335, 57, 336, 337, 338) 和 @ 987654400@.product_id = Product.id) 其中Product.restaurant_id = 10001

哇哦,这太丑了

【问题讨论】:

空的 Product 数组是 Containable 行为的预期结果。当相关数据库表中没有结果时,Containable 为包含模型返回一个空数组是标准的。至于问题的另一部分,您可能希望使用 find 调用输出的 SQL 以及 Product.restaurant_id 的值和两个日期来更新您的问题。为什么该 Order 不应该出现在结果集中? 那么,如果 Product 为空,我该怎么做才能不返回条目?我可以在 PHP 代码中检查它,但这不是我想要的。 恐怕这对于 Containable 是不可能的,您必须遍历数组来过滤结果。本文提出解决方案afterFind():nuts-and-bolts-of-cakephp.com/2008/08/06/… 我看到我的链接离线,我已经发布了一个答案。 【参考方案1】:

我将发表我的评论作为答案并详细说明。首先,空 Product 数组是 Containable 行为的预期结果。当相关数据库表中没有结果时,Containable 为包含模型返回一个空数组是标准的。

找到订单是因为它的 state_id 为 6,并且 date_delivery 在请求的范围内。

您希望按关联的 HABTM 模型进行过滤,以便在没有附加任何产品时不返回订单。使用 Containable 时,这意味着您必须手动过滤具有空 Product 数组的订单。 Containable 只是“包含”返回的关联模型数据的数量,它不会根据关联模型的条件排除父模型。

您也可以忽略适用于相关模型的自动魔术蛋糕并使用find 调用的joins 参数,如this question 上接受的答案中所述。还有一个bindModel 技巧,在this thread 的anwser 部分中有详细说明。

还有the Linkable behaviour 共享Containable 的结构,但实际上执行连接。请注意,代码已经很久没有更新了,所以在 CakePHP 2.* 中可能无法正常工作(有 2.0 分叉,like this one,但我不能说更新后的代码库质量如何)。

【讨论】:

感谢您的解释!对我帮助很大

以上是关于带有无用条目的 CakePhp 可包含查询的主要内容,如果未能解决你的问题,请参考以下文章

调用未定义的方法 Cake\ORM\Entity::query() CakePhp

CakePHP:hasOne 相关表在更新时保存多个条目

CakePHP中基于三级关系查询数据

php [cakephp:MediaController]用文件二进制文件返回cake的响应对象。 #cakephp

Cake PHP - 如何仅检查最后一个条件

cakephp的 cake24CakeControllerBaseController.php