PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, March 9, 2022

[FIXED] CakePHP 3: Empty result set returned while database has rows for same query

 March 09, 2022     cakephp, cakephp-3.0, mysql, php     No comments   

Issue

I am working on limiting number of rows returned by a specific query to ones that have been modified within last 30 days using column modified. The code for this selection goes like this:

            $conditions = ['Models.receiver'   => $Model->receiver,
                           'Models.status IN'  => [40, 50],
                           //'Models.modified >' => 'NOW() - INTERVAL 30 DAY'
            ];
            $options = [
                'limit'      => 1,
                'conditions' => $conditions,
                'order'      => ['Models.modified' => 'DESC']
            ];
            $result = $this->Models->find('all', $options)->first();
            debug($this->Models->find('all', $options));

The raw query when executed on MySQL command line prompt, without limitation by date on column modified, gives me following output:

SELECT
     receiver,
     status,
     modified
FROM
    printouts
WHERE
    receiver = (INT) X AND
    status IN (40, 50)
ORDER BY
    modified DESC LIMIT 1;

+----------+--------+---------------------+
| receiver | status | modified            |
+----------+--------+---------------------+
|  (INT) X |     50 | 2016-11-21 05:33:02 |
+----------+--------+---------------------+
1 row in set (0.00 sec)

The corresponding result set received in CakePHP 3 Controller is also correct:

object(App\Model\Entity\Model) {

    'receiver' => (int) X,
    'status' => (int) 50,
    'modified' => object(Cake\I18n\Time) {

            'time' => '2016-11-21T05:33:02+0000',
            'timezone' => 'UTC',
            'fixedNowTime' => false

    },
    '[new]' => false,
    '[accessible]' => [
            //... removed
    ],
    '[dirty]' => [],
    '[original]' => [],
    '[virtual]' => [],
    '[errors]' => [],
    '[repository]' => 'Models'

}

The query received from debugger is mentioned here:

object(Cake\ORM\Query) {

    '(help)' => 'This is a Query object, to get the results execute or iterate it.',
    'sql' => 'SELECT Models.receiver AS `Models__receiver`, Models.status AS `Models__status` Models.modified AS `Models__modified` FROM models Models WHERE (Models.receiver = :c0 AND Models.status in (:c1,:c2)) ORDER BY Models.modified DESC LIMIT 1', // extra columns have been removed for simplicity
    'params' => [
            ':c0' => [
                    'value' => (int) X,
                    'type' => 'integer',
                    'placeholder' => 'c0'
            ],  
            ':c1' => [
                    'value' => (int) 40, 
                    'type' => 'integer',
                    'placeholder' => 'c1'
            ],  
            ':c2' => [
                    'value' => (int) 50, 
                    'type' => 'integer',
                    'placeholder' => 'c2'
            ]   
    ],
    // .... more details
}

Now, I rerun the same query with limitation on modified column, by uncommenting this line:

'Printouts.modified >' => 'NOW() - INTERVAL 30 DAY'

This time I receive an empty result set. The $result variable is set to null in the following line:

$result = $this->Models->find('all', $options)->first();

The raw query output still remains the same on MySQL command line prompt:

SELECT
    receiver,
    status,
    modified
FROM
    printouts
WHERE
    receiver = (int) X AND
    status IN (40, 50) AND
    MODIFIED > NOW() - INTERVAL 30 DAY
ORDER BY
    modified DESC LIMIT 1;
+----------+--------+---------------------+
| receiver | status | modified            |
+----------+--------+---------------------+
|  (int) X |     50 | 2016-11-21 05:33:02 |
+----------+--------+---------------------+
1 row in set (0.01 sec)

On debugging the same query object this time, I receive following SQL:

object(Cake\ORM\Query) {

    '(help)' => 'This is a Query object, to get the results execute or iterate it.',
    'sql' => 'SELECT Models.receiver AS `Models__receiver`, Models.status AS `Models__status`, Models.modified AS `Models__modified` FROM models Models WHERE (Models.receiver = :c0 AND Models.status in (:c1,:c2) AND Models.modified > :c3) ORDER BY Models.modified DESC LIMIT 1',
    'params' => [
            ':c0' => [
                    'value' => (int) X,
                    'type' => 'integer',
                    'placeholder' => 'c0'
            ],
            ':c1' => [
                    'value' => (int) 40,
                    'type' => 'integer',
                    'placeholder' => 'c1'
            ],
            ':c2' => [
                    'value' => (int) 50,
                    'type' => 'integer',
                    'placeholder' => 'c2'
            ],
            ':c3' => [
                    'value' => 'NOW() - INTERVAL 30 DAY',
                    'type' => 'datetime',
                    'placeholder' => 'c3'
            ]
    ],
}

Assume value of X to be integer and same at all times. Model is a placeholder name.

How do I identify the gap in the two query executions and remove the difference in order achieve my initial objective of limiting rows by datetime stored in column modified.


Solution

By using 'Printouts.modified >' => 'NOW() - INTERVAL 30 DAY', you are telling it to look for columns where the modified date is greater than the literal string 'NOW() - INTERVAL 30 DAY'. Try 'Printouts.modified > NOW() - INTERVAL 30 DAY' instead.



Answered By - Greg Schmidt
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing