Wordpress Advanced Search - php

I had created a custom search page containing the code
<?php
function filter_where( $where = '' ) {
$where .= " AND post_date >= '{$_GET['frmdate']}' AND post_date < '{$_GET['todate']}'";
return $where;
}
add_filter( 'posts_where', 'filter_where');
$query = new WP_Query( array( 'post_type' => 'post' ) );
while( $query->have_posts() ) : $query->the_post(); ?>
<p><?php the_title(); the_date() ?></p>
<?php endwhile; ?>
<?php remove_filter( 'posts_where', 'filter_where' ); wp_reset_query(); ?>
My Aim is Search posts with 'keywords' between 'Two Dates'
my search variables passing through url like this
www.something.com?page_id=372&s12=lorem&s13=ipsum&frmdate=2012-03-01&todate=2012-06-12
with my Current code to filter the result between two date is Working perfectly when my url is looks like this www.something.com?page_id=372&frmdate=2012-03-01&todate=2012-06-12
when iam adding &s=lorem isn't work both keyword and date filtering. even I add it (&s=lorem) alone

Rather than use a custom page, you may want to just alter the search template that's available in the WP template hierarchy. Please see this post for more information.

Updated My code with the below one its working fine with my all requirements, Not sure if there is an another smarter way
<?php
function filter_where( $where = '' ) {
if(isset($_GET['frmdate']) && isset($_GET['todate'])){
$where .= " AND post_date >= '{$_GET['frmdate']}' AND post_date < '{$_GET['todate']}'";
}
if(isset($_GET['s12'])){
$where .= " AND post_content LIKE '%{$_GET['s12']}%' " ;
}
if(isset($_GET['s13'])){
$where .= " AND post_title LIKE '%{$_GET['s13']}%' " ;
}
//echo $where;exit;
return $where;
}
add_filter( 'posts_where', 'filter_where');
$query = new WP_Query( array( 'post_type' => 'post' ) );
while( $query->have_posts() ) : $query->the_post(); ?>
<li>
<h4><?php the_title(); ?></h4>
<div class="monthDate"> <span class="date"><?php the_time('M d,Y H.i'); ?></span> <span class="month"><?php comments_number();?></span> </div>
<p><?php content('100'); ?></p>
</li>
<?php endwhile; ?>
<?php remove_filter( 'posts_where', 'filter_where' ); wp_reset_query(); ?>

Related

Wordpress loop: custom number of posts and sort by date

I have tried to find a solution to something I need on the website (example here: https://www.baiweb.nl/). I have been looking for a way to show a custom number of posts per category AND sort them by date. I have managed to get a single post per category, but I can't seem to fix the rest. It sorts the posts itself by date now, but not all of them.
So, my questions are:
Is it possible to sort this loop, with all different categories, by date?
Is it possible to control the number of posts shown per category? This one is extra for me, not essential, but it would be nice.
Hope someone can help! Thanks a lot in advance for your time!
Here is my code used in the loop now:
<?php
$categories = get_categories();
$cats = array();
foreach($categories as $category) {
$cats[] = $category->name . ", ";
}
$exclude_posts = array();
foreach( $cats as $cat ) {
// build query argument
$query_args = array(
'category_name' => $cat,
'showposts' => 1,
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC'
);
// exclude post that already have been fetched
// this would be useful if multiple category is assigned for same post
if( !empty($exclude_posts) )
$query_args['post__not_in'] = $exclude_posts;
// do query
$query = new WP_Query( $query_args );
// check if query have any post
if ( $query->have_posts() ) {
// start loop
while ( $query->have_posts() ) {
// set post global
$query->the_post();
// add current post id to exclusion array
$exclude_posts[] = get_the_ID();
?>
<article id="post-<?php the_ID(); ?>" <?php post_class('loop');?>>
<div class="corner"><span><?php foreach((get_the_category()) as $category){ echo $category->name.'<br> '; } ?></span></div>
<!-- thumbnail -->
<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>" class="image">
<?php
$thumb_id = get_post_thumbnail_id();
$thumb_url = wp_get_attachment_image_src($thumb_id,'medium', true);
if ( in_category('2') || in_category('32') ) {
echo '<div class="newstitle">' . the_title() . '</div>';
}
else {
if ( has_post_thumbnail()) {
echo "<div class='ctr-image test2' style='background-image: url(" . $thumb_url[0] . ")'></div>";
}
else {
echo '<div class="newstitle">' . the_title() . '</div>';
}
}
?>
</a>
<div class="content">
<span class="date"><?php the_time('j/m/Y'); ?></span>
<h3>
<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
<?php if ( in_category('2') || in_category('32') ) {}
else { echo the_title();} ?>
</a>
</h3>
<div class="text">
<?php html5wp_excerpt('html5wp_index'); // Build your custom callback length in functions.php ?>
</div>
</div>
</article>
<?php
// do something
}
} else {
// no posts found
}
// Restore original Post Data
wp_reset_postdata();
} ?>
You were close. Your categories foreach loop has to englobe everything. Then we do a simple loop but we specify what arguments to use depending on each categories.
Here is our final result.
<?php
$categories = get_categories(); // ... get all our categories
foreach( $categories as $category ) { // ... start foreach categories
if ( $category->name == 'Mercury' ) { // ... if our category name is 'Mercury'
$posts_per_page = 1; // ... 1 post per page if our category is named 'Mercury'
} else { // ... else, for all other categories
$posts_per_page = 3; // ... 3 posts per page
};
$args = array( // ... all our arguments
'posts_per_page' => $posts_per_page, // ... 1 or 3 posts per page depending on our categories
'post_type' => 'post',
'category_name' => $category->name,
'post_status' => 'publish',
'orderby' => 'date', // ... order by date
'order' => 'ASC', // ... most recent first
);
$query = new WP_Query( $args ); // .. start a new loop
if( $query->have_posts() ):
echo '<section>';
echo '<h1>' . $category->name . '</h1>'; // ... only display our section IF a post exist in the category
while( $query->have_posts() ): $query->the_post();
echo '<article>'; // ... our post template
the_title( '<h4>', '</h4>' );
echo '</article>';
endwhile;
echo '</section>';
endif;
wp_reset_postdata(); // ... After looping through a separate query, this function restores the $post global to the current post in the main query.
}; // ... end foreach categories
?>
Thank you so much for your quick and comprehensive answer! The part of the number of categories is working very well, however, the outcome is slightly different than I want. It may be that my question was not clear, apologies for that.
What you have already made beautiful is all the categories with posts that belong to it. What I want to achieve is that all messages are mixed up, sorted by date and, what was already done here, I can indicate how many posts are in per category. Is that even possible?
Some screenshotsof the outcome of your code:
This is what I am trying, except now I need to sort this by date:
This is the code slightly adjusted:
<?php
$categories = get_categories(); // ... get all our categories
foreach( $categories as $category ) { // ... start foreach categories
if ( $category->name == 'Mercury' ) { // ... if our category name is 'Mercury'
$posts_per_page = 1; // ... 1 post per page if our category is named 'Mercury'
} else { // ... else, for all other categories
$posts_per_page = 2; // ... 3 posts per page
};
$args = array( // ... all our arguments
'posts_per_page' => $posts_per_page, // ... 1 or 3 posts per page depending on our categories
'post_type' => 'post',
'category_name' => $category->name,
'post_status' => 'publish',
'orderby' => 'date', // ... order by date
'order' => 'ASC', // ... most recent first
);
$query = new WP_Query( $args ); // .. start a new loop
if( $query->have_posts() ):
// echo '<section>';
// echo '<h1>' . $category->name . '</h1>'; // ... only display our section IF a post exist in the category
while( $query->have_posts() ): $query->the_post();
echo '<article>'; // ... our post template
echo '<h1>' . $category->name . '</h1>';
the_time('j/m/Y');
the_title( '<h4>', '</h4>' );
echo '</article>';
endwhile;
// echo '</section>';
endif;
wp_reset_postdata(); // ... After looping through a separate query, this function restores the $post global to the current post in the main query.
}; // ... end foreach categories ?>
Hope this is clear, thanks again!

How to list posts and wrap them alphabetically?

I have a list of posts on my website, what I'm trying to do is to wrap them alphabetically from A-Z by title to get a glossary like this:
A.
Apple
B.
Banana
C.
Carotts
D.
E.
F.
G.
Grenada
and so on untill letter z.
I want the letter to be displayed even if there's no post.
and i want to wrap results inside this structure :
<div class="group_letter">
<div class="letter">A</div>
<div class="post">Apple</div>
</div>
<div class="group_letter">
<div class="letter">B</div>
<div class="post">Banana</div>
</div>
here is what I've got so far :
<?php
$letter=' ';
query_posts( array ( 'post_type' => 'auteurs', 'orderby' => 'title', 'order' => 'ASC' ) );
if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php
$title=get_the_title();
$initial=strtoupper(substr($title,0,1));
if($initial!=$letter) {
echo "<div>$initial</div>";
$letter=$initial;
}
echo "<div class='post'>" . $title. "</div>";
?>
<?php endwhile; endif; wp_reset_query(); ?>
here is the result :
<div class='letter'>A</div>
<div class='post'>Apple</div>
<div class='letter'>B</div>
<div class='post'>Banana</div>
<div class='letter'>C</div>
<div class='post'>carotts</div>
<div class='letter'>G</div>
<div class='post'>Grenanda</div>
I have 2 problems :
Empty letters are not displayed.
I can't find a way to wrap my groups inside group_letter div.
I would solve this with a filter on WP_Query. One that detects an extra query variable.
Add this into your functions.php
add_filter( 'posts_where', 'title_filter', 10, 2 );
function title_filter( $where, &$wp_query )
{
global $wpdb;
if ( $search_term = $wp_query->get( 'search_prod_title' ) ) {
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql( $wpdb->esc_like( $search_term ) ) . '%\'';
}
return $where;
}
Once you have filter in place you can use wp_query and array range of alphabet
foreach (range('A', 'Z') as $char) {
echo '<div class="group_letter">';
echo '<div class="letter">'.$char.'</div>';
$args = array(
'post_type' => 'auteurs',
'posts_per_page' => -1,
'search_prod_title' => $char,
'post_status' => 'publish',
'orderby' => 'title',
'order' => 'ASC'
);
$the_query = new WP_Query($args);
if ( $the_query->have_posts() ) :
while ( $the_query->have_posts() ) : $the_query->the_post();
$title=get_the_title();
$initial=strtoupper(substr($title,0,1));
if($initial==$char) {
echo "<div class='post'>" . $title. "</div>";
}
endwhile;
wp_reset_postdata();
endif;
echo '</div>';
}
remove_filter( 'posts_where', 'title_filter', 10, 2 );
I have not tested this code, I hope it should work.
You can get more information about Wp_query https://codex.wordpress.org/Class_Reference/WP_Query
Sorry, postin TV from phone, so may be not displaying properly
Firstly, you have to create an array of all alphabets.
$alph = array('A', 'B', 'C',.... 'Z');
<
?php
$title=get_the_title();
foreach($alph as $key) {
// add while loop here
initial=strtoupper(substr($title,0,1));
if($initial!=$key) {
echo '<div class="group_letter">';
echo "<div>$key</div>";
}else{
echo "<div class='post'>" . $title. "</div>";
}
echo "</div>";
// end while loop here
}
?>

How to display post category inside page.php if else statement?

I have set up a few categories and want to display specific ones based on is_page().
Inside page.php, I've created an if..else statement that checks the page name and prints out the specific category. My problem at the moment is that instead of just the_title being printed out the whole post is being printed.
Where am I going wrong with this?
<?php while ( have_posts() ) : the_post(); ?>
<?php get_template_part( 'content', 'page' ); ?>
<?php if ( is_page( 'Greywater Recycling' ) ) { ?>
<div class="col">
<?php query_posts( 'category_name=Greywater Recycling&posts_per_page=5'); if (have_posts()) : while (have_posts()) : the_post(); ?>
<h2><?php the_title(); ?></h2>
<?php endwhile; endif; ?>
</div>
<?php } else if ( is_page( 'Stormwater Management' ) ) { ?>
<div class="col">
<?php query_posts( 'category_name=Stormwater Management&posts_per_page=5'); if (have_posts()) : while (have_posts()) : the_post(); ?>
<h2><?php the_title(); ?></h2>
<?php endwhile; endif; ?>
</div>
<?php } else if ( is_page( 'Rainwater Harvesting' ) ) { ?>
<div class="col">
<?php query_posts( 'category_name=Rainwater Harvesting&posts_per_page=5'); if (have_posts()) : while (have_posts()) : the_post(); ?>
<h2><?php the_title(); ?></h2>
<?php endwhile; endif; ?>
</div>
<?php } ?>
<?php endwhile; // end of the loop. ?>
Many problems with your code. For one, is_page does not work inside the loop.
Second, don't mess with query_posts: When should you use WP_Query vs query_posts() vs get_posts()?. Really, forget about it for secondary loops.
Your code can be simplified to the following. In functions.php, we drop one function to get the Category ID by its Name. And another to do a secondary loop using the ID. And then, in page.php a simple call to those functions.
Documentation: Class_Reference/WP_Query.
page.php
Notice that you don't need to open PHP tags at each line, that makes the code dreadly difficult to read.
Use it only to swap between PHP and HTML
<?php
get_template_part( 'content', 'page' );
// This page title
$the_title = get_the_title();
// Search for category with the same name of the page
$category = brsfl_get_category_id( $the_title );
// Category found, go to the secondary loop
if( $category ) {
brsfl_check_print_categories( $category );
}
functions.php
Always prefix your function names with something distinctive to avoid conflicts that may take the site down.
/**
* Get the category ID based on its name
*/
function brsfl_get_category_id( $cat_name )
{
$term = get_term_by( 'name', $cat_name, 'category' );
// term found, return its ID
if( $term ) {
return $term->term_id;
}
// not found
return false;
}
/**
* Print a loop based on a category ID
*/
function brsfl_check_print_categories( $cat_id )
{
$args = array(
'post_type' => 'post',
'cat' => $cat_id,
'posts_per_page' => 5
);
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() )
{
while ( $the_query->have_posts() ) :
$the_query->the_post();
echo '<h2>' . get_the_title() . '</h2>';
endwhile;
}
else
{
echo 'No posts found...';
}
}
Although I've answered within the proposed scope, I think there are better solutions to this, like:
a shortcode, just adapt the functions.
using Advanced Custom Fields to show a meta box where you can select a very specific category (don't relying in page and category names) and use only the WP_Query function to print it out in the template.
i think it's better to get the category by the slug name.
i've tried your solution, it works fine but in the case of one of my category has a name with special html characters like apostrophes or quotes it doesn't.
here is the piece of code edited from your solution :
in your functions.php
function brsfl_get_category_id($cat_name){
$term = get_term_by( 'slug', $cat_name, 'category' );
if( $term ) {
return $term->term_id;
}
return false;
}
in your page.php
$the_slug = get_post(get_the_ID())->post_name;
$category = brsfl_get_category_id( $the_slug );
if( $category ) {
brsfl_check_print_categories( $category );
}

Wordpress order posts by post type

I am trying to create a system which fetches post from 2 post types and i want to display the posts order by their post type. I am trying to first show the posts from one post type and then another post type but the query i used mixes it all. Can any one suggest a good solution for this. Here is my code.
$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$args = array(
'post_type' => array('review','directory'),
'orderby' => 'name',
'order' => 'ASC',
'posts_per_page' => '4',
'paged' => $paged ,
'tax_query' => array( array(
'taxonomy' => 'Reviews',
'field' => 'id',
'terms' => $cat_id
), ),
);
query_posts($args);
if (have_posts()) :
while (have_posts()) : the_post();
$product_terms = wp_get_post_terms(get_the_ID(), 'Reviews', array("fields" => "all", "order" => "DESC"));
$postype=get_post_type( get_the_ID() );
if($postype=='review')
{
?>
<div class="review-post">
<h3><?php the_title(); ?></h3>
<div class="review-cat-new">
<?php echo get_the_term_list( $post->ID, 'Reviews', 'Category: ', ', ', '' ); ?>
</div>
<?php
if(get_field('see_it'))
$seeit_text= get_field('see_it');
if(get_field('skip_it'))
$skipit_text= get_field('skip_it');
?>
<div class="see-skip">
<p class="see-it"><span>See it:</span>
<?php echo $seeit_text; ?>
</p>
<p class="skip-it"><span>Skip it:</span>
<?php echo $skipit_text; ?>
</p>
</div>
<?php echo custom_field_excerpt(); ?>
</div>
<?php }
else
{
?>
<div class="review-post">
<h3><?php the_title(); ?></h3>
<div class="review-cat-new">
<?php echo get_the_term_list( get_the_ID(), 'Reviews', 'Category: ', ', ', '' ); ?>
</div>
<?php echo the_field('enter_content_direc'); ?>
<?php
if(get_field('enter_textdirec'))
$text= get_field('enter_textdirec');
if(get_field('enter_linkdirec'))
$textlink= get_field('enter_linkdirec');
?>
<div class="see-skip">
<p class="see-it direc"><span><a target="_blank" style="color:#5D6D71; text-transform: lowercase;" href="<?php echo $textlink;?>"><?php echo $textlink;?> </a></span>
</p>
</div>
</div>
<?php }
endwhile;
echo '<div class="paging">';
wp_pagenavi();
echo '</div>';
endif;
So is there a way so that i can first show the posts form reviews and then directory?
Since Wordpress 4.0 you can just pass the option type (post_type) to the orderby parameter in the WP_Query object.
orderby (string | array) - Sort retrieved posts by parameter. To order by post type just pass:
'type' - Order by post type (available since Version 4.0). ('post_type' is also accepted.)
As seen in the docs https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters , you can use the regular wp query by passing an array to 'orderby' :
$wp_query = new WP_Query(
array(
's' => $search,
'orderby'=> array('type'=>'DESC', 'title'=>'ASC'),
'paged'=>$paged
)
);
if ( $wp_query->have_posts() ) {
while ( $wp_query->have_posts() ) {
$wp_query->the_post();
// do your loop stufff here
}
}
Finally i got the solution and it can be done using a filter.
The solution looks like this.
add_filter( 'posts_request' , 'modify_request' );
function modify_request( $query) {
global $wpdb;
if(strstr($query,"post_type IN ('review', 'directory')")){
$where = str_replace("ORDER BY {$wpdb->posts}.post_date","ORDER BY {$wpdb->posts}.post_type",$query);
}
return $where;
}
Order per post types with custom post type order:
add_filter('pre_get_posts', function ($query) {
if ($query->is_search && !is_admin()) :
$query->set('post_type', [ 'cpt-1', 'cpt-2', 'post', 'cpt-3']);
endif;
return $query;
});
add_filter('posts_orderby', function ( $order ) {
if ( ! is_admin() ) :
if ( is_search() && is_main_query() ) :
global $wpdb;
$order = "FIELD( post_type, 'cpt-1', 'cpt-2', 'post' ), {$wpdb->posts}.post_modified DESC";
endif;
// Disable this filter for future queries!
remove_filter( current_filter(), __FUNCTION__);
endif;
return $order;
});
First solution which comes to my mind is to get posts only for first category. Reset query (wp_reset_query()) and get them again for second category. You need to double up your code of course, but I don't see any other solution - it's WordPress - you're very limited.
Second solution is to query database directly like this:
$result = mysql_query('SELECT *
FROM `wp_posts`
WHERE post_type = "page"
OR post_type = "post"
ORDER BY post_type ASC , post_date DESC ');
$posts = array();
if($result) {
while ($row = mysql_fetch_assoc($result)) {
$posts[] = $row;
}
}
mysql_free_result($result);
echo('<pre>');
var_dump($posts);
echo('</pre>');
die();
Notice that I've used post and page types as these are default, and exist in my WP installation. But you can use different. You can play with this query as much as you want.

Don't show older post in wordpress programmatically

I'm using "The Future Is Now!" plugin and want to display all post that are schedule for the future. The only problem is, how do i make a query like (WHERE date >= $currentdate) before i enter the loop?
<?php if (is_category('My awesome category')) {
$currentdate = date("Y-m-d",mktime(0,0,0,date("m"),date("d"),date("Y")));
/* Some sort of query with the statement date >= $currentdate? */
}
?>
/* The Loop */
<?php if (have_posts()) : while (have_posts()) : the_post();
?>
query_posts(array('post_status' => 'future'));
Edit: Above is the easy answer that fits with your loop, but as a default solution it's better that u use a new $WP_Query object:
$my_query = new $WP_Query;
$my_query->query_posts(array('post_status' => 'future'));
while ($my_query->have_posts()) :
$my_query->the_post();
the_title();
endwhile;
wp_reset_postdata(); // now the main wordpress query and post data is intact
2nd Edit: Similar query but with a filter:
function filter_where( $where = '' ) {
// posts in the future
$now = date("Y-m-d H:i:s");
$where .= " AND post_date >= '$now'";
return $where;
}
add_filter( 'posts_where', 'filter_where' );
$q = new WP_Query(array('post_type' => 'post'));
while ($q->have_posts()) :
$q->the_post();
the_title();
endwhile;
remove_filter( 'posts_where', 'filter_where' );

Categories