extend wordpress search query - search

I have a working search query with offset and post_per_page (the user can go through pages)
$args = array(
'post_type' => 'type',
's'=>$the_str,
'posts_per_page' => $the_count,
'offset' => ($the_count*$the_c_page )-$the_count
);
$the_query = new WP_Query( $args );
It works great.
But now I need to add a meta field to the search function. It should get all post where s=>$query OR meta-field=>$query
Something like this:
$args = array(
'post_type' => 'type',
'posts_per_page' => $the_count,
'offset' => ($the_count*$the_c_page )-$the_count,
'meta_query' => array(
'relation' => 'OR',
's'=>$the_str,
array(
'key' => 'key',
'value' => $the_str
)
);
$the_query = new WP_Query( $args );
Unfortunately this will only search after the second condition. Does anybody have an idea?

If you crack open query.php you'll see that it really isn't built with this in mind. It isn't that it isn't a great idea, it's just that each individual query part is concatenated onto the main WHERE using an AND. So "title contains XYZ" AND "whatever the meta query is" AND "whatever the tax query is", etc. Meta and Tax both have sub logic within them that supports AND and OR but there's no way to perform this between these outer parts.
However, you might be able to do what you're looking for by tapping into one of the filters, possibly get_meta_sql. The meta query returns a statement that puts in the AND that you want to be an OR so you can just look for that and replace it:
function change_and_to_or_for_meta( $meta_query, $type, $primary_table, $primary_id_column, $context )
{
if( 0 === strpos( $meta_query['where'], ' AND' ) )
{
$meta_query['where'] = ' OR' . substr( $meta_query['where'], 4 );
}
return $meta_query;
}
//Add our filter to replace the AND at the start with OR
add_filter( 'get_meta_sql', 'change_and_to_or_for_meta', 10, 5 );
$query = new WP_Query( $args );
//Remove our filter so we don't mess other things up
remove_filter( 'get_meta_sql', 'change_and_to_or_for_meta', 10 );

Related

Wordpress Custom taxonomy dropdown list array to tagdiv composer

I am currently working on a new wordpress website which uses the Newspaper theme, which lets me compose pages with the tagdiv composer plugin.
This plugin makes it fairly easy to show posts of your choosing; with blocks/modules that have built in filters, that allow you to select the posts to be shown based upon the categories, authors, etc. that you choose.
However I would like to show custom taxonomies in there as well, so that I can choose for instance album reviews, which have the custom taxonomy of the letter A attached to it.
For my client I would need to do that since he requested a glossary (alphabetical index).
So far I have created a custom taxonomy called "alphabetical_letter", which houses all 26 characters with the linked posts to it.
The code which I need to alter is this one, preferrably I'd have a drop down list. However I keep failing in getting it right. Could anyone point me in the right direction please ?
/**
* the filter array (used by blocks and by the loop filters)
* #return array
*/
static function get_map_filter_array ($group = 'Filter') {
return array(
array(
"param_name" => "separator",
"type" => "text_separator",
'heading' => 'Filters',
"value" => "",
"class" => "",
'group' => $group
),
array(
"param_name" => "post_ids",
"type" => "textfield",
"value" => '',
"heading" => 'Post ID filter:',
"description" => "Filter multiple posts by ID. Enter here the post IDs separated by commas (ex: 10,27,233). To exclude posts from this block add them with '-' (ex: -7, -16)",
"holder" => "div",
"class" => "tdc-textfield-big",
'group' => $group
),
array(
"param_name" => "category_id",
"type" => "dropdown",
"value" => td_util::get_category2id_array(),
"heading" => 'Category filter:',
"description" => "A single category filter. If you want to filter multiple categories, use the 'Multiple categories filter' and leave this to default",
"holder" => "div",
"class" => "tdc-dropdown-big",
'group' => $group
),
array(
"param_name" => "category_ids",
"type" => "textfield",
"value" => '',
"heading" => 'Multiple categories filter:',
"description" => "Filter multiple categories by ID. Enter here the category IDs separated by commas (ex: 13,23,18). To exclude categories from this block add them with '-' (ex: -9, -10)",
"holder" => "div",
"class" => "tdc-textfield-big",
'group' => $group
),
array(
"param_name" => "alphabetical_letter_id",
"type" => "dropdown",
"value" => td_util::get_alphabetical_letter_id_array(),
"heading" => 'Custom taxonomy:',
"description" => "alphabetical letter custom taxonomy",
"holder" => "div",
"class" => "tdc-dropdown-big",
'group' => $group
),
array(
"param_name" => "tag_slug",
"type" => "textfield",
"value" => '',
"heading" => 'Filter by tag slug:',
"description" => "To filter multiple tag slugs, enter here the tag slugs separated by commas (ex: tag1,tag2,tag3)",
"holder" => "div",
"class" => "tdc-textfield-big",
'group' => $group
),`enter code here`
Edit:
in the meantime I have tried to figure out the td_util I keep seeing.
There is a file called td_util.php one folder up from where this file is, and it mentions the category2id_array so I am currently trying to find out if the problem lies here.
for completeness, this is the bit of text that refers to the category2id array function above (or the other way around more likely).
/**
* generates a category tree, only on /wp_admin/, uses a buffer
* #param bool $add_all_category = if true ads - All categories - at the begining of the list (used for dropdowns)
* #return array
*/
private static $td_category2id_array_walker_buffer = array();
static function get_category2id_array($add_all_category = true) {
if (is_admin() === false) {
return array();
}
if (empty(self::$td_category2id_array_walker_buffer)) {
$categories = get_categories(array(
'hide_empty' => 0,
'number' => 1500
));
$td_category2id_array_walker = new td_category2id_array_walker;
$td_category2id_array_walker->walk($categories, 4);
self::$td_category2id_array_walker_buffer = $td_category2id_array_walker->td_array_buffer;
}
if ($add_all_category === true) {
$categories_buffer['- All categories -'] = '';
return array_merge(
$categories_buffer,
self::$td_category2id_array_walker_buffer
);
} else {
return self::$td_category2id_array_walker_buffer;
}
}
And a bit further down the file it pops up one last time
class td_category2id_array_walker extends Walker {
var $tree_type = 'category';
var $db_fields = array ('parent' => 'parent', 'id' => 'term_id');
var $td_array_buffer = array();
function start_lvl( &$output, $depth = 0, $args = array() ) {
}
function end_lvl( &$output, $depth = 0, $args = array() ) {
}
function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
$this->td_array_buffer[str_repeat(' - ', $depth) . $category->name . ' - [ id: ' . $category->term_id . ' ]' ] = $category->term_id;
}
function end_el( &$output, $page, $depth = 0, $args = array() ) {
}
}

Select specific custom post type from selected taxonomy on wordpress

hello i have post_type "product" and taxonomy "price" can someone help me to query that custom post type with the selected taxonomy?
my current code is like this
<?php $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
$args = array(
'post_type' => 'product',
'posts_per_page' => 5,
'tax_query' => array(
array(
'taxonomy' => 'productcategories',
'terms' => $term->name
)
)
);
query_posts($args);
print_r($args);?>
but nothing on result, can someone help me? thank you
i'm found what wrong already.
nothing wrong with the code, i'm already solved it. that's because i'm not set the content into selected custom category yet, that why it display null.
my bad

Wordpress custom post type archive page wp_query pagination not working

I have created an archive page for my 'Event' custom post ape called archive-event.php.
I used the content from the standard archive.php template and it listed my 4 events in the order they were posted.
The next step was to change the order by the custom field event_date. I did this no problems. Then I wanted to not show any events that event_date had passed. The below code does this perfectly.
The issue I now have is my pagination is all messed up. I have the default reading settings set to 2 posts per page and I have a 'Load more' button to bring up the next two.
When I click 'Load more' it duplicates the two events already showing. Any ideas where I've gone wrong?
<?php
$today = date("Ymd");
$args = array (
'post_type' => 'event',
'meta_key' => 'event_date',
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'event_date',
'value' => $today,
'type' => 'numeric',
'compare' => '>=',
)
),
);
$wp_query = new WP_Query( $args );
while( $wp_query->have_posts() )
{
$wp_query->the_post();
?>
<div>Content goes here</div>
<?php } wp_reset_postdata(); ?>
Depending on how the plugin builds the UI it may or may not be respecting the pagination functionality built into WordPress.
Try forcing the paged setting into your query like so:
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array (
'post_type' => 'event',
'paged' => $paged, // this will be set to what WordPress thinks is the proper page to start
'meta_key' => 'event_date',
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'event_date',
'value' => $today,
'type' => 'numeric',
'compare' => '>=',
)
),
);
Next, if this still doesn't work, you can test the assumption that the paged parameter isn't working for some reason by changing the default paged value like so (again, just to test):
$paged = 2; // just force it to start on the second page to see if that works
If the above test works, I would say that get_query_var() believes you're on the first page.

How to query by custom post type values in WordPress?

I have a Custom Post Type using the Custom Post Type UI plugin called Case Studies. I'm also using the Custom Fields to add a capability field to the Case Studies.
How can I query Case Studies where the capability is equal to some ID?
$query = array('post_type' => 'case-studies','posts_per_page' => 3);
is my query so far
It could be
$query = array(
'post_type' => 'case-studies',
'meta_key' => 'capability',
'meta_value' => 10, // some ID
'posts_per_page' => 3
);
$the_query = new WP_Query( $query );
while ( $the_query->have_posts() ) : $the_query->the_post();
// echo here
endwhile;
wp_reset_postdata();
You need to set your key to capability, and then query value by your post ID.
'meta_query' => array(
array(
'key' => 'capability',
'value' => $post->ID,
'compare' => 'example'
)
)

CakePHP Search Plugin, search for a value equal or higher than the given in the search

I'm using the CakePHP Search Plugin, and there's something I can't get to work. I would like to have a search field (let's call it age) where a user can input a value (like 24, for example) and get as a result all the elements with a value in the age field of the table who have age 24 or higher. How can I do that?
So far I can perform normal searches, like by name or by an exact value (if you want age 24 exactly then it works fine).
Here's the code related with the Search Plugin that I have so far:
- model:
class Person extends AppModel{
var $name = 'Person';
public $actsAs = array('Searchable');
public $filterArgs = array(
array('name' => 'name', 'type' => 'like'),
array('name' => 'age', 'type' => 'value'),
);
}
- controller:
class PersonsController extends AppController {
var $name = 'Persons';
var $components = array('Search.Prg');
public $presetVars = array(
array('field' => 'name', 'type' => 'value'),
array('field' => 'age', 'type' => 'value'),
);
function index() {
$this->set('persons', $this->Person->find('all'));
}
/* ---------------- SEARCH PLUGIN --------------*/
public function find() {
$this->Prg->commonProcess();
$this->paginate['conditions'] = this->Game->parseCriteria($this->passedArgs);
$this->set('persons', $this->paginate());
}
}
- find.ctp:
//apart from the code below, I have all the code to show the results
echo $form->create('Game', array(
'url' => array_merge(array('action' => 'find'), $this->params['pass'])
));
echo $form->input('name', array('div' => false));
echo $form->input('age', array('div' => false));
echo $form->submit(__('Search', true), array('div' => false));
echo $form->end();
To sum up: with the code above, I can perfomr a search of an exact value for the age field. How do I change that to perform a search of 'age >= value entered'?
THank you so much in advance!
So this is how I solved it (or at least it seems to work with all the test I've done so far):
Changed the 'age' line by the following line in the filterArgs array in the model:
array('name' => 'age', 'type' => 'query', 'method' => 'findByAge', 'field' => 'Person.age'),
Added the following method in the same model:
public function findByAge($data = array()) {
$query = array(
'Person.age >=' => $data['age'],
);
return $query;
}
That's it! With the 'query' type, any complex query can be added to the main query using a method. Thanks to satyrwilder for pointing in the right direction!
From your presetVars -
array('field' => 'age', 'type' => 'value'),
-- filters down to your find() method from your commonProcess() method, which I presume constructs a generalized find like conditions=>array($key=>$val)?
Cake sees array key=>val pair assignments as an indication to generate a "WHERE $key=$val" condition.
To do a fuzzier pull, wherever you construct that generic find() - add a method or something just to roll those two into
'conditions'=>array("name LIKE '%{$name}%'", "{$age}>={$val}")
or whatever you've got going on. String the arguments together for the desired effect on your query and I'm sure you can extrapolate further ways to abstract that query, if needed.
If you need a more complex solution, Cake provides elegant built-in, extremely powerful subquery generation. It seems like you're working awfully hard to achieve a lot of built-in functionality, but then again I don't know how complicated your situation is.
http://book.cakephp.org/view/1030/Complex-Find-Conditions
HTH
I know this has been answered but there is another method that may be more suitable to this situation.
From the documentation
'expression' type: useful if you want to add condition that will generate by some method, and condition field contain several parameter like in previos sample used for 'range'. Field here contains 'Article.views BETWEEN ? AND ?' and Article::makeRangeCondition returns array of two values.
Full Article Here
I had to accomplish the same thing you did but with 5 different fields. I did not want to have to write a query for each one. Here is how I accomplished the same thing with the expression type. This is in the filterArgs array.
array(
'name'=>'bathrooms',
'type'=>'expression',
'method'=>'returnNumber',
'field'=>'House.bathrooms >= ?'
)
Then I created this function in the model that simply returns the number the user submitted. When called, returnNumber will be passed two arrays.
Looks something like this.
Array
(
[0] => Array
(
[bathrooms] => 6
[bedrooms] => 5
[acres] => 12
[city] => Greenville
[year] => 2009
)
[1] => Array
(
[name] => bathrooms
[type] => expression
[method] => returnNumber
[field] => House.bathrooms >= ?
)
)
Now for the actual function. You can use the debug statement to see what you are actually passing the function.
function returnNumber($arg, $name){
// debug(func_get_args());
// exit;
return $arg[$name['name']];
}

Resources