I want to query as below in cakePHP.so, How can I do query using 'find' function of cakePHP .
Help me.
SELECT DISTINCT(Property.City),'city' as Fieldname FROM `properties` as Property WHERE Property.City LIKE 'las%'
Try:
$this->Property->find(
'all',
array(
'fields' => array( 'DISTINCT ( Property.city )' ),
'conditions' => array( 'Property.city LIKE' => 'las%' )
)
I threw this up from memory, but it should be close. I'm also sure that DISTINCT queries are at least mentioned in the documentation. Probably in the "complex finds" section.
Hope that helps some.
Related
I am here trying to improve one of my select.
My model is as follows:
Network
--->hasMany Esx
--->hasAndBelongToMany Environment
A network might have 0 Esx and/or 0 environments
So here I want to select some network information and the Esx section, but not the environment information.
$this->Network->find('all',array(
'conditions'=>array(
'Network.plateform'=>IAAS,
'Network.active'=>true),
'fields'=>array(
'Network.id',
'Network.name')
));
So, I can't use fields to only select the vlan field
I can't lower recursive to remove environment because it would also remove Esx
I found on SO an other question that suggest to use $this->Network->schema() and remove the unwanted fields, but it doesn't return the hm and habtm structure.
In short, how can I transform the result of this query from this
0 => array(
'Network' => array(
'id' => '38',
'name' => 'HP_LOW'),
'Esx' => array(...),
'Environment' => array(...)
)...
To this
0 => array(
'Network' => array(
'id' => '38',
'name' => 'HP_LOW'),
'Esx' => array(...)
)...
The purpose is not to just unset the Environment field, but to not select it in order to improve database perfomance.
Thank you!
Ps: Im' workin with cakephp 2.6.2
use containable
see the manual here
in your Model you have to enable the Containable Behavior
class Networkextends AppModel {
public $actsAs = array('Containable');
}
then in the controller you can do
$this->Network->find('all',array(
'conditions'=>array(
'Network.plateform'=>IAAS,
'Network.active'=>true),
'fields'=>array(
'Network.id',
'Network.name'),
'contain'=>array(
'Esx')
));
Tables
User(id)
Profile(id, *user_id*, type)
Attribute(id, *attribute_name_id*, value)
AttributeName(id, name)
ProfileAttribute(id, *profile_id*, *attribute_id*)
Relationships
The relationships are set up correctly (and go both ways, hasMany/belongsTo).
User hasMany Profile
Profile hasMany ProfileAttribute
Attribute hasMany ProfileAttribute
(could be written Profile hasMany Attribute through ProfileAttribute)
AttributeName hasMany Attribute
Goal
For a specified User id, with a find() in the User model, I only want the following fields, laid out as such:
$results[Profile.type][AttributeName.name][Attribute.value]
Is it even possible to retrieve results arranged like this? I've been playing around with Find and Containable for hours, but, first time trying to do anything complicated like this with Cake, I can't get the hang of it.
Thanks!
EDIT
I'm getting these results now, all that I need, but nowhere near the desired format above -can it be done as part of the find, or does it need to be sorted after?
Yep, it's possible. You just have to specify fields on containable:
$this->User->find('all', array(
'conditions' => array('User.id' => $id),
'fields' => array('id'),
'contain' => array(
'Profile' => array(
'fields' => array('id','type'),
'ProfileAttribute' => array(
'fields' => array('id'),
'AttributeName' => array(
'fields' => array('id','name'),
'Attribute' => array(
'fields' => array('id','value')
)
)
)
)
)
);
Be wary that when you use contain and fields options, you have to specify the id so it can make the association (check the docs)
EDIT: I don't know if you can group contained data as the docs didn't say anything about that, but probably you can, as they accept some parameters as in the main query. You can try it, adding group to any contained data that you want to group
I was just reading that in newer versions of Cake, the Sanitize class will be removed. I'm using CakePHP 2.3 in which it I believe is already deprecated. Normally I'd use prepared statements for the query I'm trying to write, but I don't believe that's possible while using the paginate Component. ultimately I will be paginating the results, but here's the options I have so far for the query:
$options = array(
'joins' => array(
array(
'table' => '(SELECT search_terms.name, product_search_terms.product_id AS product_id_1
FROM product_search_terms
JOIN search_terms ON search_terms.id = product_search_terms.search_term_id
)',
'alias' => 'SearchTerm',
'conditions' => array(
'SearchTerm.product_id_1 = Product.id',
'LOWER(SearchTerm.name) REGEXP "[[:<:]]' . $word . '[[:>:]]"', //Here's the line that is vulnerable
)
)
),
'fields' => array('Product.id', 'SearchTerm.name'),
);
The line 'LOWER(SearchTerm.name) REGEXP "[[:<:]]' . $word . '[[:>:]]"', is surely vulnerable to SQL injection. Can this be prevented without using Sanitize or prepared statements?
I'm working with a legacy database whose keys follow a convention, but not the cake convention, unfortunately, and I've bumped into something odd with the containable behavior -- it's pulling the wrong data. Here's my setup:
TechnologyIncentive belongsTo...
array(
'Incentive' => array(
'className' => 'Incentive',
'type' => 'inner',
'foreignKey' => false, # actually 'incentive_id', but we need to fool Cake
'conditions' => array( 'TechnologyIncentive.incentive_id = Incentive.incentive_id' ),
),
'Technology' => array(
'className' => 'Technology',
'type' => 'inner',
'foreignKey' => false, # actually 'incentive_tech_id', but we need to fool Cake
'conditions' => array( 'TechnologyIncentive.incentive_tech_id = Technology.incentive_tech_id' )
),
);
You can see that I've had to fool Cake into working with my non-standard keys by setting the foreignKey to false and defining the link in my where clause. So far so good.
Now, when I try to run a query from the TechnologyIncentive model:
$this->find( 'all', array(
'contain' => array( 'Incentive', 'Technology' ),
'fields' => array( 'Incentive.name', 'Technology.name', 'TechnologyIncentive.amount' ),
'conditions' => array( /** conditions... */ )
);
Everything works great. Stuff is nicely contained and I get exactly what I'd expect. Then I need to include a TechnologyGroup, which hasMany Technology and things breakdown for some reason.
Now my contain option looks like this:
'contain' => array( 'Incentive', 'Technology' => array( 'TechnologyGroup' ) )
And what I get back is an Incentive record contains an incentive record. That's not entirely surprising since I'm specifying a few fields in one place (the main fields option) and implicitly all fields in the contain option, but what's really weird to me is that they're different incentives. The "contained" incentive is just wrong.
Inspecting the SQL, it looks like the query was run with no effective where clause at all, so everything is being pulled and then artificially limited to a single record. Note the difference between $result['Incentive']['incentive_id'] and $result['Incentive']['Incentive']['incentive_id'].
Array
(
[Incentive] => Array
(
[incentive_id] => MD046
[name] => Incentive name
[category] =>
[Incentive] => Array
(
[incentive_id] => AK004
[code] => AK04F
[version] => 2
[category] => Incentive Category
)
)
)
Has anyone ever bumped into this? It's not a problem until I want to retrieve an extended record (TechnologyGroup). Any thoughts would be much appreciated.
It looks like this was directly attributed to the non-standard keys. The Containable behavior, more so, it seems, that other elements of Cake really wants the convention followed. Moreover, some of the key associations included a double underscore (__) in the field name and that caused other problems.
Kids, don't try this at home. Follow the conventions, even if it means manipulating a legacy database.
i m facing some problem in find function. im fetching value fro find function.i have model.contian another model .
Can i give conditions in contain in cakephp
is it possiblehi
$this->Post->find('all', array('contain' => array(
'Comment' => array(
'conditions' => array('Comment.author =' => "Daniel"),
'order' => 'Comment.created DESC'
)
)));
You should always try the documentation first :).
isnt conditions in the format $this->ModelName->find('all',array('conditions'=>array('Table.name'=>1))); working for you?
Yes you can give conditions in contain