How to get values between two given values in Cakephp 3 - cakephp

I want to get product with specified price range supplied using the below query but getting following error:
Cannot convert value to string InvalidArgumentException
$product_List=$this->Products->find('all',array('conditions' => array('product_price BETWEEN ? and ?' => array($min, $max))));
Here product_price is of type varchar(100). Please help to sort out my issue.

I think it's help you
$product_List = $this->Products->find('all')
->where(function ($exp) use($min,$max) {
return $exp->between('product_price', $min, $max); //Consider $min=100 ; $max =1000; product_price BETWEEN 100 AND 1000;
});

Another way.
$product_List = $this->Products->find('all')
->where(['product_price <=' => $max, 'product_price >=' => $min]);

Related

CakePHP count query gives different result when run in phpmyadmin

I am running the following query on my database:-
SELECT COUNT(*) AS COUNT, `Doctor`.`device_type` FROM `doctors` AS `Doctor` WHERE 1 = 1 GROUP BY `Doctor`.`device_type`
and it gives the result:-
count device_type
47 Android
23 iPhone
Whereas when running this query as a CakePHP query it gives the result as '2':-
$this->Doctor->find('count',array('group'=>'Doctor.device_type'));
Can anyone please suggest why this is happening?
The CakePHP result is correct as it is returning a count of the number of results returned by your query. In your case you have 2 rows: 'Android' and 'iPhone'.
find('count') always returns an integer, not an array. What Cake is doing is basically this:-
$data = $this->Doctor->find('all', array('group' => 'Doctor.device_type'));
$count = count($data); // This is what find('count') will return.
You need to do something like the following instead:-
$data = $this->Doctor->find('all', array(
'fields' => array(
'Doctor.device_type',
'COUNT(Doctor.*) AS count'
)
'group' => 'Doctor.device_type'
));

How to find items by date when the field is datetime?

I have a model with a DateTime field.
How can I get all entries by Date even if the column is DateTime?
Example table Cars:
id; expiration
1;2014-12-22 00:00:00
2;2014-12-22 03:12:00
3;2014-10-09 01:10:29
If I do this:
$this->Car->find("all", array('conditions' => array('expiration' => '2014-12-22' ) ))
I get only the item with ID 1 (2014-12-22 00:00:00)
But I need all the items (1 and 2)
Any ideas how to accomplish this? in MySql I could do something like this:
SELECT * ... FROM..WHERE DATE_FORMAT(conditions, '%Y-%m-%d') = '2014-12-22'
Try this
$this->Car->find("all", array('conditions' => array('DATE(ondate)' => '2014-12-22') ));
This will generate
SELECT * ... FROM..WHERE WHERE DATE(ondate) = '2014-12-22'
You need to update your query as shown below:
$this->Car->find("all", array(
'conditions' => array(
'DATE(expiration)' => '2014-12-22'
)
)
);
In the above query, Mysql now compare only date not the date and time as it was using in the query mentioned by you.
You will need to search trough a range: 00:00:00 - 23:59:59
http://cookbook.mongodb.org/patterns/date_range/

findall ignoring order parameter?

I'm trying to use the following:
$this->Chapter->recursive=1;
$chaps = $this->Chapter->find('all', array(
'order'=> array('sequence_number' => 'ASC')
));
$this->set('chapters', $chaps );
to retrieve all my chapters by increasing order, but CakePHP seems to be ignoring the 'order' parameter. I believe that I have the syntax correct (based on view-source:http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#creating-custom-find-types, which says the following should work:
public function index() {
$articles = $this->Article->find('available', array(
'order' => array('created' => 'desc')
));
}
). The SQL for the table looks like:
CREATE TABLE chapters (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
sequence_number INT UNSIGNED,
title VARCHAR(50)
);
and I'm not getting any syntax or run-time errors. However, the SQL generated by Cake to actually get the chapter records is:
SELECT `Chapter`.`id`, `Chapter`.`sequence_number`, `Chapter`.`title`
FROM `Tutorial`.`chapters` AS `Chapter` WHERE 1 = 1
Clearly I'm doing something wrong, but I don't know what it is.
As a work-around I'm happy to put an order property on the Model. Since I typically want to retrieve chapters by sequence number I'm fine with adding this to the model:
public $order = 'Chapter.sequence_number ASC';
Once I do that Cake generates
SELECT `Chapter`.`id`, `Chapter`.`sequence_number`, `Chapter`.`title`
FROM `Tutorial`.`chapters` AS `Chapter` WHERE 1 = 1
ORDER BY `Chapter`.`sequence_number` ASC
What if you try something like this, instead:
$chaps = $this->Chapter->find('all', array(
'order' => array('Chapter.sequence_number ASC')
));
The main difference being this part: Chapter.sequence_number ASC

CakePHP : Search date from form helper

I use form helpers to show drop down select date. My problem is, i can't compare date from ms sql with form data.
My View :
<?php echo $this->Form->input('collect_date', array('label' => 'Collect Date','type'=>'date','dateFormat'=> 'DMY','minYear' => date('Y'),'maxYear' => date('Y')+1));?>
My Controller
$status =array(0,2,4);
$find_date = $this->data['Transaction']['collect_date'];
$field = array('Transaction.status','Catalogue.title', 'Catalogue.author', 'Catalogue.isbn', 'Location.rack');
$condition = array('OR' => array('AND' =>array('Transaction.return_date <'=> $find_date,'Transaction.status '=> '3'),array('Transaction.status'=> $status)));
$data = $this->Catalogue->Transaction->find('count',array('fields' => $field,'conditions'=>$condition,'order'=>array('Transaction.id desc') ));
$this->set('Found', $data);
And the sql dump
SELECT COUNT(*) AS [count] FROM [transactions] AS [Transaction]
LEFT JOIN [catalogues] AS [Catalogue] ON ([Transaction].[catalogue_id] = [Catalogue].[id])
LEFT JOIN [users] AS [User] ON ([Transaction].[user_id] = [User].[id])
WHERE (((([Transaction].[return_date] < ('01', '09', 2013))
AND ([Transaction].[status] = 3))) OR ([Transaction].[status] IN (0, 2, 4)))
As you can see the date format ('01', '09', 2013). But when try to convert use this
'Transaction.return_date <'=> date('Y-m-d', strtotime($find_date))
it show error:
Warning (2): strtotime() expects parameter 1 to be string, array given [APP\Controller\CataloguesController.php, line 66]
and the sql show:
[Transaction].[return_date] < '1970-01-01'
You could use:
$date = DateTime::createFromFormat('d/m/y', implode('/', $find_date));
'Transaction.return_date <'=> $date->format('Y-m-d');
Edit:
I think the way its meant to be 'flattened' is with
$this->Model->deconstruct('find_date', $find_date);
However, last time i tried to use this, i couldn't get it to work properly, so i went with the above.
http://api21.cakephp.org/class/model#method-Modeldeconstruct
Try converting return date using UNIX_TIMESTAMP in sql query and then comparing it with
strtotime($find_date).

CakePHP Search between 2 Date Records

I am building a small Web App that lets users reserve Office Rooms and Equipment. For the Reservation they enter a Start and an End Date.
When a user tries to find out if any (for example) car is available on 2012-10-23, and the database holds reservation date records of Start: 2012-10-20 and End: 2012-10-25 for (lets say) all the cars, how do I include all the dates between my date entries in the search?
The $date variable gets it's value from the Date Search Form Field.
This, unfortunately does not work, and I can't figure out how to use daysAsSql for this query:
$conditions = array(
'conditions' => array(
'? BETWEEN ? AND ?' => array($date,'Equipment.date_start','Equipment.date_end'),
)));
$this->set('equipments', $this->Equipment->find('all', $conditions));
There is a simpler solution to this, but thanks for the help:
(As a condition in the find:)
array('Equipment.date_start <= ' => $date,
'Equipment.date_end >= ' => $date
),
In case if you have one date and you want to use BETWEEN
$date_start = start date;
$date_end = date_end;
$conditions = array(
'conditions' => array(
'date(Equipment.create) BETWEEN ? AND ?' => array($date_start, $date_end),
)));
$this->set('equipments', $this->Equipment->find('all', $conditions));
This is the case if you have From AND To
in your case
$date_start = start date;
$date_end = date_end;
$conditions = array(
'conditions' => array(
'Equipment.start_date >=' => array($date_start),
'Equipment.end_date <=' => array($date_end)
));
$this->set('equipments', $this->Equipment->find('all', $conditions));
Here is CakePHP BETWEEN query example.
I'm defining my arrays as variables, and then using those variables in my CakePHP find function call:
// just return these two fields
$fields = array('uri', 'page_views');
// use this "between" range
$conditions = array('Event.date BETWEEN ? and ?' => array($start_date, $end_date));
// run the "select between" query
$results = $this->Event->find('all',
array('fields'=>$fields,
'conditions'=>$conditions));
Ref from
$start = date('Y-m-d');
$end = date('Y-m-d', strtotime('+1 month'));
$conditions = array('Event.start <=' => $end, 'Event.end >=' => $start);
$this->Event->find('all', array('conditions' => $conditions));
If you are on cakephp 2.0 this is the answer http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::daysAsSql
If you are on cakephp 1.3 you can use TimeHelper, just import it and use the same function as per example in documentation here http://book.cakephp.org/1.3/en/view/1471/Formatting
You cannot use database columns with this BETWEEN-syntax. If you assign strings in the array, CakePHP will quote them. Same for numeric values depending on your database setup.
CakePHP will quote the numeric values depending on the field type in your DB.
– see http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#complex-find-conditions
If you still want to use the BETWEEN, you can write your queries into the array key because CakePHP will not escape the keys, but only the values.
CakePHP only escapes the array values. You should never put user data into the keys. Doing so will make you vulnerable to SQL injections.
– see http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#complex-find-conditions
Concerning your problem:
$this->Model->find('all', array(
'conditions' => array(
'"YYYY-MM-DD" BETWEEN Model.date_start AND Model.date_end',
),
));
You can even work with MySQL date and time functions:
$this->Model->find('all', array(
'conditions' => array(
'CURDATE() BETWEEN Model.date_start AND Model.date_end',
),
));
If you use date/time functions, do not quote them. If you use a specific date put it in quotes.

Resources