I'm trying to get my head around the complex find conditions of CakePHP and have read the docs but am struggling with this one query.
SELECT field1,
field2
WHERE id = 123456
AND ((holding_date = Last_day(holding_date)
AND Month(holding_date) IN(3, 6, 9, 12))
OR (holding_date = '2013-09-15'))
To produce the above conditions what would my conditions array look like?
CakePHP conditions and sql expressions
While the conditions in the question are not that complex, they touch on a few points which mean they can be tricky to define correctly. Some of the things to know when defining cakephp conditions:
Conditions are defined as an array of key => value pairs, as such the same key cannot be defined twice on the same level
an array element which has a numeric key is interpreted as an sql expression
The default join mode is "AND" - it's not necessary to specify "AND" => ... in conditions
An OR conditions must have more than one elements. There's no error if it has only one but otherwise: OR what?
Bearing in mind the above notes, the conditions in the question can be expressed as:
$foo->find('all', array(
'fields' => array(
'field1',
'field2'
),
'conditions' => array(
'id' => 123456,
'OR' => array(
array(
'holding_date = LAST_DAY(holding_date)',
'MONTH(holding_date)' => array(3,6,9,12)
),
'holding_date' => '2013-09-15'
)
)
));
Which results in:
WHERE
`id` = 123456
AND
(
(
(holding_date = LAST_DAY(holding_date))
AND
(MONTH(holding_date) IN (3, 6, 9, 12)))
)
OR
(`holding_date` = '2013-09-15')
)
Note: whitespace is quite important =) I misread the question originally solely because of the inconsistent whitespace in the question's sql.
OK I have solved it:
$findParams['conditions'] = array(
'Account.client_id' => '12345',
'AND' => array(
'OR' => array(
'Holding.holding_date' => '2013-09-15',
'AND' => array(
'Holding.holding_date = LAST_DAY(Holding.holding_date)',
'MONTH(Holding.holding_date)' => array(3,6,9,12)
)
)
)
);
Try this:
$params['conditions'] = array(
'`id`' => 123456,
'AND' => array(
'`holding_date`' => 'LAST_DAY(`holding_date`)',
'AND' => array(
'MONTH(holding_date)' => array(3, 6, 9, 12),
'OR' => array(`holding_date` => '2013-09-15')
)
)
);
Related
Im looking to create a simple query but i can't seem to figure out how to do it using Cakes conditions (cake 1.3), what im looking to do is quite simple, in SQL its just
SELECT * FROM table WHERE firstvalue != '' OR secondvalue != ''
So basically only return row if there is a value in either firstvalue or second value.
At the moment i have;
$conditions = array(
"NOT" => array(
'firstvalue' => ''
)
);
This works fine for the first value, but if i try and add anything to it, it still only returns the results for the firstvalue
Two ways to go about this:
$conditions = array(
'OR' => array(
array('NOT' => array('firstvalue' => '')),
array('NOT' => array('secondvalue' => ''))
)
);
Or, take advantage of the fact that "NOT a OR NOT b" == "NOT (a AND b)":
$conditions = array(
'NOT' => array(
array('firstvalue' => ''),
array('secondvalue' => '')
)
);
To add multiple fields in OR condition, you have to write the fields in array.
Like,
$conditions = array(
"OR" => array(
"NOT"=>array('firstvalue' => ''),
array('secondvalue'='')
)
)
);
I hope it will work for you.
This should be a really easy answer and I'm probably just being thick, but I have two arrays in PHP:
$data1 = array(
array(
'qid' => 'q-prof-1-1',
'value' => 10,
),
array(
'qid' => 'q-prof-2-1',
'value' => 3,
),
);
$data2 = array(
array(
'qid' => 'q-prof-2-1',
'value' => 5,
),
array(
'qid' => 'q-prof-3-2',
'value' => 1,
),
);
And I want to result in:
$result = array(
array(
'qid' => 'q-prof-1-1',
'value' => 10,
),
array(
'qid' => 'q-prof-2-1',
'value' => 5,
),
array(
'qid' => 'q-prof-3-2',
'value' => 1,
),
);
... so that the two will be merged- but, if it finds a qid that matches another, will replace it with the latter.
I've tried a mixture of array_merge(), array_merge_recursive(), $data1 + $data2, $data2 + $data1, array_replace(), array_replace_recursive(), array_diff() etc, etc, but every options seems to return either two or four values rather than the three. And of course I've done my fair share of S.O hunting.
Any ideas? Would prefer something short and sweet to a massive iterating function of any sort!
Thanks in advance :)
Matt
Edit:
I've just realised that if I turn the arrays inside $data1 & $data2 into key-value pairs most of those merge and replace functions work, eg:
$data1 = array(
'q-prof-1-1' => array(
'qid' => 'q-prof-1-1',
'value' => 10,
) // ... etc etc
);
... but I'd still rather not have to change the original data
Is there a reason you can't use an associative array? That way you can just have
$array = array('q-prof-1-1' => 10, 'q-prof-2-1' => 3);
$array2 = array('q-prof-2-1' => 5, 'q-prof-3-2' => 1);
Then just loop through $array2, push the value on if $array doesn't have a key (key_exists() if i remember right) or if it does have a key merge them how you want?
Also, but not sure, using an associative array would probably make array_merge work correctly (possibly).
I'm working on a rating system. When a user rates, $inc increments the field, and addToSet adds the user_id to make sure the user only clicks rate once. I am checking if the user_id is already in the x field before updating, but that is another query which I'd rather avoid. Can I reach this purpose without having to write another query? I mean, $addToSet only adds if there is no value like that; can I instead get affected rows? Can you suggest other queries?
Thank you!
..->update(
array("_id" => $idob),
array(
'$inc' => array($type => (int) 1),
'$addToSet' => array("x" => (int) $user_id)
)
);
Ok I see the problem.
..->update(
array("_id" => $idob),
array(
'$inc' => array($type => (int) 1),
'$addToSet' => array("x" => (int) $user_id)
)
);
The problem is that you need a conditional $inc there so that it only $incs if it does add to set.
This is not possible with a unique index since unique indexes work from the root of the document atm. Also you probably want to use the $inc as a form of pre-aggregation or what not.
One method could be:
update(
array('_id' => $idob, 'x' => array('$nin' => array($user_id))),
array(
'$inc' => array($type => 1),
'$push' => array('x' => (int)$user_id)
)
)
This will only do the update if that user_id does not already exist in x.
how do I build a find() query in cakePHP using these conditions:
Find where
MyModel.x = 1 and MyModel.y = 2 OR
MyModel.x = 1 and MyModel.y value does not exist (or is equal to empty string)
Can somebody tell me how I can go about building such find query?
I'm gonna give you some pointers, but you need to try to do this as it's very basic and it's always good to practice.
A basic find in cake is in the form of
$this->ModelName->find('all');
This in its default form does a SELECT * from model_names (convention is to have singular ModelName for plural table name - model_names)
To add conditions:
$this->ModelName->find('all', array('conditions' => array('ModelName.x' => 1));
To add AND conditions
$this->ModelName->find('all', array('conditions' => array(
'ModelName.x' => 1, 'ModelName.y' => 2
));
To add OR conditions
$this->ModelName->find('all', array('conditions' => array(
'OR' => array(
'ModelName.x' => 1, 'ModelName.y' => 2
)
));
To combine both
$this->ModelName->find('all', array('conditions' => array(
'ModelName.y is not' => null,
'OR' => array(
'ModelName.x' => 1, 'ModelName.y' => 2
)
));
// where y is not null and (x = 1 or y = 2)
http://book.cakephp.org/1.3/view/1030/Complex-Find-Conditions
(btw I'm sure there will be users giving you the exact answers, so just take my answer for your reference :) )
$this->MyModel->find('all', array('conditions' => array(
'OR' => array(
array(
'MyModel.x' => 1,
'MyModel.y' => 1
),
array(
'MyModle.x' => 1,
'OR' => array(
array('MyModel.y' => NULL),
array('MyModel.y' => '')
)
)
)
)));
Originaly posted on cakephp Q&A but i'll put it up here in hope of getting some answers.
I have a bunch of companies that has a status of 0 as default but sometimes get a higher status. Now i want to use the high status if exists but revert to 0 if not. i have tried a bunch of different approaches but i always get either only the ones with status 0 or the ones with the status i want, never giving me status if exists and 0 if not.
Gives me only the status i specify, not giving me the ones with status 0:
'Company' => array (
'conditions' => array (
'OR' => array(
'Company.status' => 0,
'Company.status' => $status,
)
)
)
Gives me only status of 0:
'Company' => array (
'conditions' => array (
'OR' => array(
'Company.status' => $status,
'Company.status' => 0
)
)
)
Status definition and retrieving data in code:
function getCountry($id = null, $status = null) {
// Bunch of code for retrieving country with $id and all it's companies etc, all with status 0.
$status_less_companies = $this->Country->find...
if ($status) {
$status_companies = $this->Country->find('first', array(
'conditions' => array(
'Country.id' => $id
),
'contain' => array(
'Product' => array (
'Company' => array (
'conditions' => array (
'OR' => array(
'Company.status' => $status,
'Company.status' => 0
)
)
)
)
)
)
}
// Mergin $status_less_companies and $status_companies and returning data to flex application.
}
I changed the name for the models for this question just to make more sense, people are generaly frighten away when i tell them i work with cakephp for my flex application. I guess the logic to this question doesn't make sense but trust me that it makes sense in my application.
Thanks!
Try
'Company' => array (
'conditions' => array (
'OR' => array(
array('Company.status' => 0),
array('Company.status' => $status),
)
)
)
In the cookbook it says to wrap the or conditions in arrays if they are pertaining to the same field
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#complex-find-conditions
I'm not sure to have understood what results you expect. If you want to retrieve all records having status = 0, plus let's say the one having status = 3, you could use an 'IN' instead of an 'OR'.
In Cake, you would write it like this:
$status = 3;
$conditions = array('Company.status' => array(0, $status));
You can also fetch record by using following method:
put values in an array
e.g. $arr=array(1,2);
$res = $this->Model->find('all', array(
'conditions' =>array('Model.filedname'=>$arr),
'model.id' => 'desc'
));
I hope you will find answer.
$this->loadModel('Color');
$colors = $this->Color->find('all', [
'conditions' => [
'Color.is_blocked' => 0,
'Color.is_deleted' => 0,
'OR' => [
[
'Color.isAdmin' => $user_data['id'],
],
[
'Color.isAdmin' => 0,
]
],
]
]);