Complex query with WP_Query - sql

I am still learning wordpress and trying to perform a query of posts with WP_Query, meta_query to be precise, the thing is after trying different possible ways and finding out that I can't nest arrays with relations I dont know if the next possible way is to make a sql query directly.
To better explain what I would like to do, the next array hopefully will help:
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'Meta_geo',
'value' => '46',
'compare' => '=',
),
array(
'key' => 'Meta_dest',
'value' => 'si',
'compare' => '=',
),
array(
'relation' => 'OR',
array(
array(
'key' => 'Meta_1',
'value' => '10',
'compare' => '<=',
),
array(
'key' => 'Meta_1',
'value' => '30',
'compare' => '>=',
)
),
array(
'relation' => 'OR',
array(
'key' => 'Meta_1',
'value' => '',
'compare' => '=',
),
array(
'key' => 'Meta_1',
'value' => '',
'compare' => '=',
)
)
)
),
many Thanks for the time, if there are an expertet who can give me a hint I will be grateful.
Sorry for my english.

Based on what you have above the below is the closest your are going to get...
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'Meta_geo',
'value' => '46',
'compare' => '=',
),
array(
'key' => 'Meta_dest',
'value' => 'si',
'compare' => '=',
),
array(
'key' => 'Meta_1',
'value' => array('10','11','12' etc),
'compare' => 'IN',
),
)
This will leave you a little sorting out to do however. This can be done with a loop and as you normally display the results of a query using the loop you can use that.
e.g.
while ( $my_query->have_posts() ) : $my_query->the_post();
$metavalue = get_post_meta($post->ID, 'meta_geo', true);
$metavalue = get_post_meta($post->ID, 'meta_dist', true);// if there are a lot of conds, use get_post_meta($post->ID) to return object of value arrays
if($metavalue == 46 && ): //proceed
//html here!
endif;
endwhile;

Related

Get post meta value array in serialized data

I saved the information inside the database by Select-Option as serialized data.
this is my data in db :
a:2:{i:0;s:7:"#00CC6A";i:1;s:7:"#8E8CD8";}
when i want get posts with this query :
$the_query = new WP_Query(array(
'post_type' => 'product',
'showposts' => 5,
'meta_query' => array(
array(
'key' => '_my_color',
'value' => '#8E8CD8',
'compare' => 'LIKE'
)
)
));
This works . and i can get the post which value_meta is #8E8CD8
when i want to get post with array value , like this :
$the_query = new WP_Query(array(
'post_type' => 'product',
'showposts' => 5,
'meta_query' => array(
array(
'key' => '_my_color',
'value' => array('#8E8CD8','#00CC6A'),
'compare' => 'IN'
)
)
));
It doesn 't works .
i tried everything like :
serialize(array('#8E8CD8','#00CC6A'))
and this :
'relation' => 'OR',
array(
'key' => '_my_color',
'value' => '#8E8CD8',
'compare' => 'LIKE',
),
array(
'key' => '_my_color',
'value' => '#00CC6A',
'compare' => 'LIKE',
),array(
'key' => '_my_price_wd',
'value' => '585000',
'compare' => 'LIKE'
)
but i want AND result with _my_color_ and _my_price_wd_
i can't get relation with OR

CakePHP Multiple NOT Find's

I've got the below code which will not 'work'... How can I go about excluding multiple items from the SQL query? I've tried many different combinations without any luck :(
$this->autoLayout = false;
$this->set('songs', $this->CcFile->find('all', array(
'fields' => array(
'track_title',
'artist_name',
'lptime',
'id'
),
'conditions' => array(
'AND' => array(
'NOT' => array(
'artist_name' => 'Jam FM Bed',
),
'NOT' => array(
'artist_name' => 'Airtime Show Recorder',
),
'NOT' => array(
'artist_name' => 'Jam FM Jingles',
),
'NOT' => array(
'artist_name' => 'Kent Scout Jingles',
),
),
),
'order' => array(
'lptime' => 'desc nulls last',
'artist_name' => 'asc'
)
)));
Try that:
'NOT' => array(
'artist_name' => array(
'Jam FM Bed',
'Airtime Show Recorder',
// ...
)
)
or
'artist_name NOT IN' => array(
'Jam FM Bed',
'Airtime Show Recorder',
// ...
)
Try this
fixed code
$this->autoLayout = false;
$this->set('songs', $this->CcFile->find('all', array(
'fields' => array(
'track_title',
'artist_name',
'lptime',
'id'
),
'conditions' => array(
'NOT' => array(
'artist_name' => Array(
'Jam FM Bed',
'Airtime Show Recorder',
'Jam FM Jingles',
'Kent Scout Jingles')
),
),
'order' => array(
'lptime' => 'desc nulls last',
'artist_name' => 'asc'
)
)));

CakePHP many conditions to one field

This code:
$conditions = array(
'fields' => array(
'User.id'
),
'conditions' => array(
'AND' => array(
'UsersProblem.problem_id' => 38,
'UsersProblem.problem_id' => 34,
),
),
'recursive' => -1
);
$conditions['joins'][] = array(
'table' => 'users_problems',
'alias' => 'UsersProblem',
'type' => 'INNER',
'conditions' => array(
'User.id = UsersProblem.user_id',
));
Is transforming to this SQL query:
SELECT `User`.`id`
FROM `lawyers`.`users`
AS `User`
INNER JOIN `lawyers`.`users_problems`
AS `UsersProblem`
ON (`User`.`id` = `UsersProblem`.`user_id`)
WHERE `UsersProblem`.`problem_id` = 34
Where is AND UsersProblem.problem_id = 38"?
How to create correct find condition to get users with some list of problems? Which are linked as many to many relationship.
Using $this->Problem->find is not possible, beause I need to use 2 joins: users_problems and users_practices. And use for them AND condition, like this:
'AND' => array(
'UsersProblem.problem_id' => 38,
'UsersProblem.problem_id' => 34,
'UsersPractices.practice_id' => 1,
'UsersPractices.practice_id' => 2,
),
You're overwriting 'UsersProblem.problem_id'. Just think about it like the array it is. CakePHP is just using the PHP array structure to do these finds, and that means it follows array rules. But to get around that in cakephp, you're supposed to use a two dimensional array
Like this:
'AND' => array(
array('UsersProblem.problem_id' => 38),
array('UsersProblem.problem_id' => 34)
),
Instead of this:
'AND' => array(
'UsersProblem.problem_id' => 38,
'UsersProblem.problem_id' => 34
),
That way, instead of trying to set the key 'UsersProblem.problem_id' twice, you're making an array that looks like
0 -> array('UsersProblem.problem_id' => 38)
1 -> array('UsersProblem.problem_id' => 34)
And that will work, it's a workaround the CakePHP guys built into the system for this kind of situation.
I think you need to use OR instead of AND:
$conditions = array(
'fields' => array(
'User.id'
),
'conditions' => array(
'OR' => array(
array('UsersProblem.problem_id' => 38),
array('UsersProblem.problem_id' => 34),
),
),
'recursive' => -1
);
You can also roll this up as follows:
$conditions = array(
'fields' => array(
'User.id'
),
'conditions' => array(
'OR' => array(
'UsersProblem.problem_id' => array(34, 38)
),
'recursive' => -1
);
Change your conditions array as shown below:
$options = array(
'fields' => array('User.id'),
'conditions' => array('UsersProblem.problem_id' => array(38,34)),
'recursive' => -1
);
$options['joins'] = array(
array(
'table' => 'users_practices',
'alias' => 'UsersPractices',
'type' => 'INNER',
'conditions' => array(
/CONDITION OF JOIN/
),
array(
'table' => 'users_problems',
'alias' => 'UsersProblem',
'type' => 'INNER',
'conditions' => array(
'User.id = UsersProblem.user_id',
)
);
From User Model:
$this->find('list',$options);
Do not use AND/ OR because they are not optimized for above case.
For reference:
MYSQL OR vs IN performance
and
CakePHP right way to do this (get value from setting's table)
**Try the code for join tables in cakephp.......**
$options = array('joins' => array(
array(
'table' => 'modelname1',
'alias' => 'modelName1',
'type' => 'LEFT',
'foreignKey' => false,
'conditions' => array('modelname1.id = modelname2.mid')
)
),
'fields' => array('modelName1.field1', 'modelName1.field2', 'modelName2.field1', 'modelName2.field2'),
'conditions' => array('modelname.id' => 1, 'modelname2.field1' => ''),
'limit' => 10, 'page' => 1);
$this->modelName2->find($options);

restrict selected columns in cakephp query

I want to reduce the number of fields returned by cakephp's find('all') but don't know if this is possible.
$this->Group->find('all', $params);
where $params
$params = array(
'conditions' => array(
'Group.featured' => 1,
),
'contain' => array(
'User',
'Class' => array(
'conditions' => array(
'Class.exp IS NOT NULL',
'Class.tb <20',
)
)
)
));
The problem is that my Class table has many columns that i don't need and that take a long time to load, so i would line to only select 5 fields.
Can this be done in Cakephp or am i better off writing a regular query?
something like
$params = array(
'conditions' => array(
'Group.featured' => 1,
),
'contain' => array(
'User',
'Class.a',
'Class.b',
'Class.exp',
'Class.tb',
'Class' => array(
'conditions' => array(
'Class.exp IS NOT NULL',
'Class.tb <20',
)
)
)
));
Thank you
That's what the fields parameter is for.
$params = array(
...
'contain' => array(
'Class' => array(
'conditions' => array(
'Class.exp IS NOT NULL',
'Class.tb <20',
),
'fields' => array('a', 'b')
)
)
);

Populating CGridView one to many relation

In my project one of the model named types having multiple relation to other models the criteria with part is giving below its like
$criteria->with = array(
'category',
'subCategory',
'accountsSupplierPriceDetails' => array(
'with' => 'serviceLevel'
)
);
the relationship goes like
types - category - relation(1-1)
types - subcategory - relation(1-1)
types - accountsSupplierPriceDetails - relation(1-1)
accountsSupplierPriceDetails - serviceLevel - relation(1-n)
my problem is how to display the names from each table in a grid. the result of (1-n) should be displayed in a dropdownbox. when i try to access the data from column it shows the error Trying to get property of non-object ($data->accountsSupplierPriceDetails->serviceLevel ->name). can anyone please help me.
Thanks in advance.
in my view i create a cgridview with 5 rows in which one row data is populated using dropdownlist.
<div style="width:700px; height:auto;">
<?php
$widget = $this->widget('zii.widgets.grid.CGridView', array(
'id' => 'response-grid',
'dataProvider' => $pickdataset->pickCategorylistingForMain(),
'cssFile' => Yii::app()->baseUrl . '/media/css/gridview.css',
'summaryText' => '',
'ajaxUpdate' => 'response-grid',
'enablePagination' => true,
'pager' => array(
'class' => 'LinkPager',
'cssFile' => false,
'header' => false,
'firstPageLabel' => 'First',
'prevPageLabel' => 'Previous',
'nextPageLabel' => 'Next',
'lastPageLabel' => 'Last',
),
'columns' => array(
array(
'name' => 'id',
'header' => '#',
'value' => '$this->grid->dataProvider->pagination->currentPage * $this->grid->dataProvider->pagination->pageSize + ($row+1)',
),
array(
'type' => 'raw',
'name' => 'categoryExt',
'header' => 'Category',
),
array(
'type' => 'raw',
'header' => 'Sub Category',
'value' => '$data->subCategory->name',
),
array(
'type' => 'raw',
'name' => 'locationExt',
'header' => 'Location',
),
array(
'type' => 'raw',
'header' => 'Name',
'value' => 'CHtml::dropDownList($data->corporate_id."-".$data->category_id."-".$data->sub_category_id."-".$data->location_id,"",popDropBox($data->masterCategoryServiceLevels), array("class" => "listbox"), array("empty" => "Select a Location"))',
),
array(
'type' => 'raw',
'header' => 'Pick',
'value' => 'CHtml::image(Yii::app()->baseUrl . "/media/images/edit_icon.png",$data->corporate_id."-".$data->category_id."-".$data->sub_category_id."-".$data->location_id,array("title" => "Select this Combination"))',
),
),));
function popDropBox($data)
{
$list = array();
foreach ($data as $row)
{
$list[$row->serviceLevel->id] = $row->serviceLevel->name;
}
return $list;
}
?>
</div>
the relation in model is:
'masterCategoryServiceLevels' => array(self::HAS_MANY, 'MasterCategoryServiceLevel', 'category_template_id'),
'corporate' => array(self::BELONGS_TO, 'AccountsCorporate', 'corporate_id'),
'category' => array(self::BELONGS_TO, 'MasterCategory', 'category_id'),
'subCategory' => array(self::BELONGS_TO, 'MasterCategory', 'sub_category_id'),
'location' => array(self::BELONGS_TO, 'MasterLocation', 'location_id'),
the row is
array(
'type' => 'raw',
'header' => 'Name',
'value' => 'CHtml::dropDownList($data->corporate_id."-".$data->category_id."-".$data->sub_category_id."-".$data->location_id,"",popDropBox($data->masterCategoryServiceLevels), array("class" => "listbox"), array("empty" => "Select a Location"))',
),
and i use a function to create dropdown data is
function popDropBox($data)
{
$list = array();
foreach ($data as $row)
{
$list[$row->serviceLevel->id] = $row->serviceLevel->name;
}
return $list;
}
please comment if you have any doubt. i am free to share... have a nice day SO friends... wishes and prayers.