Order wp_query by variable set inside the loop - php

I have a custom loop that pulls all the child pages of the current page, and displays them. However, I need to order this query by the $first_row_image variable that is pulled inside the loop.
This is done by grabbing the title row at the end() of an array (The array being a repeater field in Advanced Custom Fields).
I know my below code isn't right, but I can't work out how to do it.
<?php function flo_add_child_pages() {
global $post;
$args = array(
'post_type' => 'page',
'post_parent' => $post->ID,
'cat' => '3368',
'posts_per_page' => -1,
'meta_key' => $first_row_image,
'orderby' => 'meta_value',
'order' => 'ASC'
);
$the_query = new WP_Query( $args );
?>
<?php if ( $the_query->have_posts() ) : ?>
<div class="child-flex">
<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<?php
$rows = get_field('breadcrumbs' ); // get all the rows
$first_row = end($rows); // get the first row
$first_row_image = $first_row['title' ]; // get the sub field value
?>
<?php if($first_row_image) : ?>
<a href="<?php the_permalink(); ?>" rel="post-<?php the_ID(); ?>" class="one-half">
<?php echo $first_row_image; ?><i class="fa fa-angle-right rotate-icon" style="float: right; margin-top: 5px;"></i>
</a>
<?php endif;?>
<?php endwhile; ?>
</div><?php wp_reset_postdata(); ?>
<?php endif;
}

In my experience, it's usually better to do complex sorting after the query instead of as part of the query.
For one thing, you defined 'meta_key' => $first_row_image, but $first_row_image is undefined at that point, so the query can't execute on it. For another thing, given the way that ACF stores repeater values, it'd be almost impossible to query on them.
I'd do it this way:
Run the query
Check to see if you have posts
Use usort to write a custom sorting function on the $query->posts array.
<?php
function reorder_by_last_title($page1, $page2) {
$page1_rows = get_field('breadcrumbs', $page1['ID']); // get all the rows
$page1_first_row = end($page1_rows); // get the first row
$page1_first_row_image = $page1_first_row['title']; // get the sub field value
$page2_rows = get_field('breadcrumbs', $page2['ID']);
$page2_first_row = end($page2_rows);
$page2_first_row_image = $page2_first_row['title'];
return $page1_first_row_image > $page2_first_row_image;
}
function flo_add_child_pages() {
global $post;
$args = array(
'post_type' => 'page',
'post_parent' => $post->ID,
'cat' => '3368', // Not sure why this is needed-- did you enable categories for pages?
'posts_per_page' => 500, // Use a big number instead of -1
);
$child_pages_query = new WP_Query($args);
if ($child_pages_query->have_posts()) :
// Reorder child pages by last breadcrumbs title.
usort($child_pages_query->posts, 'reorder_by_last_title' );
?>
<div class="child-flex">
<?php while ($child_pages_query->have_posts()) : $child_pages_query->the_post(); ?>
<?php
$rows = get_field('breadcrumbs'); // get all the rows
$first_row = end($rows); // get the first row
$first_row_image = $first_row['title']; // get the sub field value
?>
<?php if ($first_row_image) : ?>
<a href="<?php the_permalink(); ?>" rel="post-<?php the_ID(); ?>" class="one-half">
<?php echo $first_row_image; ?><i class="fa fa-angle-right rotate-icon"
style="float: right; margin-top: 5px;"></i>
</a>
<?php endif; ?>
<?php endwhile; ?>
</div><?php wp_reset_postdata(); ?>
<?php endif;
}

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!

PHP showing certain content top of page, rest afterwards

Wordpress team members have a select in admin that lets you pick a number to display the team in a certain order on Archive page. The Select returns a value of the number, which i retrieve.
However, I want to display all the members that have the value of 1 first, and any members after that show up below. At the moment, the IF statements only shows the content if they exist (obviously), i would like to however make it work somehow so it shows Members with value 1 first, then members with value 2. Thank you!
$images = get_field('image');
$titles = get_the_title();
$positions = get_field('position');
$link = get_permalink($post->ID);
if ($positions[0] == 1) {
echo "<div class='employee'>";
echo "<img src='$images'>";
echo "<h2>$titles</h2>";
echo "</div>";
}
if ($positions[0] == 2) {
echo "<div class='employee'>";
echo "<img src='$images'>";
echo "<h2>$titles</h2>";
echo "</div>";
}
If you want to sort the $positions array you could use
sort($positions);
You you can easily sort by a meta value with get_posts()...
<?php
$args = array(
'post_type' => 'team_members',
'posts_per_page' => -1,
'meta_key' => 'position',
'orderby' => 'meta_value',
'order' => 'ASC'
);
$posts = get_posts( $args );
?>
<?php if( $posts ): ?>
<ul>
<?php foreach( $posts as $post ): setup_postdata( $post ) ?>
<li class='employee'>
<img src='$images'>
<h2>$titles</h2>
</li>
<?php endforeach; ?>
</ul>
<?php wp_reset_postdata(); ?>
<?php endif; ?>

How am I supposed to implement this custom query into index.php?

The following is my index.php file
<?php get_header(); ?>
<?php
if(get_option('zens_home') == "blog") { ?>
<?php include (TEMPLATEPATH . '/lib/blog-home.php'); ?>
<?php } else { ?>
<div id="home-content" class="clearfix">
<ul id="shelf">
<?php
?>
<?php while (have_posts()) : the_post(); ?>
/*Start of mark*/
<li class="box" id="post-<?php the_ID(); ?>">
<?php $disc = get_post_meta($post->ID, 'fabthemes_discount', true); ?>
<?php if ( $disc ) { ?>
<span class="salebadge"></span>
<?php }?>
<img class="productshot" width="172" height="243" src="<?php get_image_url(); ?>" alt="<?php the_title(); ?>"/>
<div class="pricetab clearfix">
<?php if ( $disc ) { ?>
<span class="oldprice"><del> <?php echo get_post_meta($post->ID, 'fabthemes_disc-price', true) ?> </del></span>
<?php }?>
<span class="prodetail"><?php $price=get_post_meta($post->ID, 'fabthemes_price', true); echo $price; ?></span>
</div>
</li>
/*End of mark*/
<?php endwhile; ?>
<div class="clear"></div>
<?php getpagenavi(); ?>
</ul>
</div>
On top of the loop it is already using, I also want to place the following custom query
$args = [
'posts_per_page' => -1,
'post_type' => 'products',
'orderby' => 'rand', // Order these posts randomly
'tax_query' => [
[
'taxonomy' => 'product-category',
'terms' => 27
]
]
];
$vip_posts = new WP_Query( $args );
// Run the loop
if ( $vip_posts->have_posts() ) {
while ( $vip_posts->have_posts() ) {
$vip_posts->the_post();
// Display what you want in your loop like
echo '</br>';
}
wp_reset_postdata();
}
However, I failed to do it properly without having it as either plaintext on my mainpage or finding myself in some sort of syntax error.
The problem is that I can't get the elements that I marked in the code of index.php and start after the loop in the to work with the custom query
A cleaner approach here would be to add your custom query via the loop_start action. The advantage of doing this is that you do not need to alter template files at all. You can simply drop your code in functions.php or a plugin if you wish (which I always prefer)
Another advantage is that the loops are apart from each other, something that you needed according to another question, so this approach would fit perfectly
The following code is untested, but should give you an idea of how to use the action
add_action( 'loop_start', function ( \WP_Query $q )
{
// Make sure we only target the main query, if not, bail
if ( !$q->is_main_query() )
return;
// Set a static counter to make sure this runs only once to avoid infinitive loops
static $count = 0;
// Make sure our counter is 0, if not, bail
if ( 0 != $count )
return;
// Update our counter
$count++;
// This is the main query, lets target specific pages only
if ( $q->is_home()
|| $q->is_post_type_archive( 'products' )
|| $q->is_tax( 'product-category' )
) {
// Bail on vip pages
if ( $q->is_tax( 'product-category', 'vip' ) ) // Make sure about vip slug
return;
// Bail if this is not the first page
if ( $q->is_paged() )
return;
// Lets add our custom loop
global $wp_query;
$args = [
'posts_per_page' => -1,
'post_type' => 'products',
'orderby' => 'rand', // Order these posts randomly
'tax_query' => [
[
'taxonomy' => 'product-category',
'terms' => 27
]
]
];
$vip_posts = new WP_Query( $args );
// Run the loop
if ( $vip_posts->have_posts() ) {
while ( $vip_posts->have_posts() ) {
$vip_posts->the_post();
// Display what you want in your loop like
the_title();
echo '</br>';
}
wp_reset_postdata();
}
// Lets make sure our main loop counter starts at -1
$wp_query->rewind_posts();
}
});

Randomise X most recent wordpress posts

I've got the following code which will display 4 random posts from the defined category. However, that's a little too random, I need it to display the 4 most recent, and then randomise them in particular each time the page is refreshed.
Otherwise I just end up getting articles which could date back over 2 years ago appear on the homepage.
<div class="article-block-v1">
<?php
//get terms (category ids 11,2,33,34), then display one post in each term
$taxonomy = 'category';// e.g. post_tag, category
$param_type = 'category__in'; // e.g. tag__in, category__in
$term_args=array(
'include' => '1459',
);
$terms = get_terms($taxonomy,$term_args);
if ($terms) {
foreach( $terms as $term ) {
$args=array(
"$param_type" => array($term->term_id),
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 4,
'orderby' => 'rand',
);
$my_query = null;
$my_query = new WP_Query($args);
$i = 1;
if( $my_query->have_posts() ) {
echo '<ul>';
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<?php if ($i == 1): ?>
<div class="article-block-v1">
<div class="category-label-large category-news-analysis">
<p><?php echo $term->name; ?></p>
</div>
<div class="view2 third-effect">
<?php the_post_thumbnail(); ?>
<div class="mask">
</i>
</div>
</div>
<ul class="homepagewhitebg">
<li><h5><?php the_title(); ?></h5></li>
</ul>
</div>
<?php else: ?>
<li><p><?php the_title(); ?></p></li>
<?php endif; ?>
<?php
$i++;
endwhile;
echo '</ul>';
}
}
}
wp_reset_query(); // Restore global post data stomped by the_post().
?>
Demo 1 (4 Most Recent) - Regular without random orderby
Article #1001
Article #1002
Article #1003
Article #1004
Demo 2 (4 Most Recent - But with order by random on those 4)
Article #1003
Article #1001
Article #1004
Article #1002
UPDATE
I'm also trying this now, however it's not taking into account the category I've defined, nor is it randomising across the 4 displayed:
<div class="article-block-v1">
<?php
$number = "4";
$posts = "SELECT * from $wpdb->posts WHERE post_type='post' ORDER BY post_date DESC LIMIT $number";
$postX = array();
$postresult = mysql_query($posts) or die(mysql_error());
while ($row = mysql_fetch_array($postresult)) {
$postX[] = $row[0];
}
$ids = shuffle($postX);
$ids = implode(',', $postX);
echo $ids;
?>
<?php
$args = array(
'posts_per_page'=> $number,
'post__in' => explode(',', $ids),
'include' => '1451',
'orderby' => 'rand'
);
query_posts($args);
?>
<?php while (have_posts()) : the_post(); ?>
<li><?php the_title(); ?></li>
<?php endwhile; ?>
You can use shuffle(). You're going to want to get the 4 most recent posts (in order) before shuffling them. Quite simply, you could do something like the following:
// Get the 4 most recent posts
$args = array( 'numberposts' => 4 );
$recent_posts = wp_get_recent_posts( $args );
// Shuffle them
shuffle($recent_posts)
foreach( $recent_posts as $recent ){
// Do something with the $recent post
}
You may need to pass additional $args to the function, for your specific constraints.

Custom Post Query WordPress and a better way to display posts

This seems a little noob, but I didn't found a better option. I created a custom loop to display only the title of custom post type I created.
Example:
Custom Post Type: Atuação
Contratos (Cível e Societário)
Direito Penal Empresarial
The problem is: I can't "validate" at the menu if the post is active or only a link. Example: My visitor is visiting the Direito Penal Empresarial page. But the menu don't display any class so I can customize it. It just shows the <a href> link.
See the code of the custom loop below.
<ul class="menu-advogados">
<?php
// WP_Query arguments
$args = array (
'post_type' => 'atuacao_posts',
'pagination' => false,
'order' => 'ASC',
'orderby' => 'title',
);
// The Query
$exibir_atuacao_posts = new WP_Query( $args );
// The Loop
if ( $exibir_atuacao_posts->have_posts() ) {
while ( $exibir_atuacao_posts->have_posts() ) {
$exibir_atuacao_posts->the_post();
?>
<li><?php the_title(); ?></li>
<?php
}
} else {
echo "Nenhum post encontrado";
}
// Restore original Post Data
wp_reset_postdata();
?>
</ul>
There is any better solution for this? Or if not, how can I add the "active" class to the href?
UPDATE: You can check out the website live.
You need to store current post ID in a variable then you need to compare current Post ID with list item Post ID if both are same then apply active class. So your code will be something like this-
<ul class="menu-advogados">
<?php
global $post;
$post_id = $post->ID; // Store current page ID in a variable.
// WP_Query arguments
$args = array (
'post_type' => 'atuacao_posts',
'pagination' => false,
'order' => 'ASC',
'orderby' => 'title',
);
// The Query
$exibir_atuacao_posts = new WP_Query( $args );
// The Loop
if ( $exibir_atuacao_posts->have_posts() ) {
while ( $exibir_atuacao_posts->have_posts() ) {
$exibir_atuacao_posts->the_post();
?>
<li><a href="<?php the_permalink(); ?>" <?php echo ($post_id==$post->ID)?'class="active"':''; ?> ><?php the_title(); ?></a></li>
<?php
}
} else {
echo "Nenhum post encontrado";
}
// Restore original Post Data
wp_reset_postdata();
?>
</ul>
use this
// WP_Query arguments
$args = array (
'post_type' => 'atuacao_posts',
'post_status' => 'publish',
'pagination' => false,
'order' => 'ASC',
'orderby' => 'title',
);
// The Query
$query = new WP_Query( $args );
<?php if ( $query ->have_posts() ) : ?>
<!-- the loop -->
<?php while ( $query ->have_posts() ) : $query ->the_post(); ?>
<h2><?php the_title(); ?></h2>
<?php endwhile; ?>
<!-- end of the loop -->
<?php wp_reset_postdata(); ?>
<?php else : ?>
<p><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p>
<?php endif; ?>
for WP_Query consider this link it's great article...

Categories