I'm trying to combine several loops into one and sort the final results by relevance.
For the former part, I did this:
// set the variables
$author_id = get_the_author_meta('ID');
$tags_id = wp_get_post_tags($post->ID);
$first_tag = $tags_id[0]->term_id;
$categories_id = wp_get_post_categories($post->ID);
// loop for same author
$by_author = new WP_Query (array(
'author' => $author_id,
'posts_per_page' => '5'
));
// add ids to array
if ($by_author->have_posts()) {
while ($by_author->have_posts()) {
$by_author->the_post();
$add[] = get_the_id();
}
}
// loop for same tag
$by_tag = new WP_Query(array(
'tag__in' => $first_tag,
'posts_per_page' => '5'
));
// add ids to array
if ($by_tag->have_posts()) {
while ($by_tag->have_posts()) {
$by_tag->the_post();
$add[] = get_the_id();
}
}
// loop for same category
$by_category = new WP_Query(array(
'category__in' => $categories_id,
'posts_per_page' => '5'
));
// add ids to array
if ($by_category->have_posts()) {
while ($by_category->have_posts()) {
$by_category->the_post();
$add[] = get_the_id();
}
}
// loop array of combined results
$related = new WP_Query(array(
'post__in' => $add,
'post__not_in' => array($post->ID),
'posts_per_page' => '10',
'orderby' => $weight[$post->ID],
'order' => 'DESC'
));
// show them
if ($related->have_posts()) {
while ($related->have_posts()) {
$related->the_post();
// [template]
}
}
This is working nicely combining the loops into one. For the latter part, what I'm trying to do next is to add an incremental "weight" value to each post as they come up so as to later sort them with something like 'orderby' => $weight,.
For example, if a post comes up in "same author" it gets 3 points, if another one comes up in same tag it gets 2 points and so on. If it comes up in more than one loop, it should get the combined points i.e. 3+2+1=6 hence be boosted to the top of the final query.
I have tried to add a counter to each preliminary loop, like $weight = +3 etc, but this only adds everything up for every post, not individually.
I also tried inserting something like this at the end of each preliminary loop...
$weight = 0;
if ($by_author){
foreach ($by_author as $post){
setup_postdata($post);
$weight = +10;
add_post_meta($post->ID, 'incr_number', $weight, true);
update_post_meta($post->ID, 'incr_number', $weight);
}
}
... and this to the final one
echo get_post_meta($post->ID,'incr_number',true);
But it still doesnt do it right. It assigns a global value, while I want them to be different depending on the actual main posts one is reading.
So is there a way to do this?
If I understand your question right, I think your last solution was close. Instead of a global $weight parameter, however, I think you need to build an array of $weights that's unique to each post:
$weights[$post.id] += 10;
Then, you could sort that array and get your most heavily weighted post IDs from there.
Related
In my WordPress v5.8.1, I have the below query in taxonomy.php to get the list of posts.
$args = array(
'post_type' => array('song', 'dance'),
'post_status' => 'publish',
'posts_per_page' => 10,
);
query_posts($args);
The query return posts from both post_type's.
I would like to create a menu in the same page, where I want to check if the query results has found posts from a specific post_type. The menu looks something like this.
This taxonomy has posts from Song, Dance (if found posts from both post_type's), or
This taxonomy has posts from Song (if found posts from Song post_type only)
Have tried the below within the loop:
$song_count = wp_posts_count('song')->found_posts;
$dance_count = wp_posts_count('dance')->found_posts;
if ($song_count=>0 {
/** code goes here **/
}
Above is returning the count from entire WordPress, not just from current taxonomy.
You can stock result in variable, but did I understand the question correctly?
$args = array(
'post_type' => array('song', 'dance'),
// or 'post_type' => get_post_type($post->ID),
// conditions are no longer necessary
'post_status' => 'publish',
'posts_per_page' => 10,
);
$results = query_posts($args);
if($results) {
$count = 0;
$current_post_type = get_post_type($post->ID);
$current_post_type_name = get_post_type_object(get_post_type())->labels->singular_name); // ajust with 2 variables for multiple results
foreach($results as $result) {
// if request is in a single custom post
if($result->post_type == $current_post_type) {
$count++;
}
}
if($count > 0) {
echo $count . $current_post_type_name;
}
}
else {
// no results
}
Ok, so right now I have a working code, that basically echo the total amount of posts for meta_key _heart_this for a specific user:
<?php $query = new WP_Query( array( 'meta_key' => '_heart_this', 'author' => 1, ) );
echo $query->found_posts; ?>
However, some posts have meta_value of 2, 3 etc..
So I want to sum the total amount of meta_value and echo, because right now the number I get is inaccurate obviously.
I'm almost there, need a bit of guidance.
Thanks in advance.
It should be taken in loop. Use below code
$query = new WP_Query( array( 'meta_key' => '_heart_this', 'author' => 1) );
//Take all values in array
$sum = [];
if( $query->have_posts()){
while( $query->have_posts()): $query->the_post();
{
//Get all posts values one by one
$value = get_post_meta( get_the_ID(), '_heart_this', true );
//Push values in array
array_push($sum, $value);
}
endwhile;
}
//Sum all values of array to get total amount of meta value
$sum_final = array_sum ($sum);
echo $sum_final;
Tested & works
Im new to WP Query and ACF custom fields. I want to write a code that will show first 3 results from the calculation of the total_score custom field. I have managed to short by the total score but I want to show the title and permanlink of the first 3 posts so the visitor will click and go to the post. Any help will be much appreciated. My code so far :
$args = array(
'posts_per_page' => -1,
'post_title' => true,);
$all_posts = array();
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ):
while ( $the_query->have_posts() ): $the_query->the_post();
// Get all fields
$fields = get_fields();
// Push each $fields array into the $all_posts array
array_push($all_posts, $fields);
endwhile;
// Restore original Post Data
wp_reset_postdata();
// Print the result here and do what you choose
print_r($all_posts);
endif;
if(isset($_POST['place']))
{ // start the loop
$q1=$_POST["place"];
//CORECT CODE !!!!
foreach($all_posts as &$value) {
if ($value['question1']==$q1){
$value['total_score']=$q1;
}
} } //end question 1
// question 2
if(isset($_POST['home']))
{ // start the loop
$q2=$_POST["home"];
foreach($all_posts as &$value) {
if ($value['question2']==$q2){
$value['total_score']=$value['total_score']+$q2;
}
//echo $value['total_score']."<br>"; }
//echo "Q2"."<br>";
//print_r($all_posts);
} //end question 2
// question 3
if(isset($_POST['hours']))
{ // start the loop
$q3=$_POST["hours"];
//CORECT CODE !!!!
foreach($all_posts as &$value) {
if ($value['question2']==$q3){
$value['total_score']=$value['total_score']+$q3;
}
}
//echo "Q2"."<br>";
} //end question 3
// shorting by total_score
function sortByOrder($a, $b) {
return $b['total_score'] - $a['total_score'];
}
usort($all_posts, 'sortByOrder');
//print_r($all_posts);
foreach($all_posts as &$value) {
echo $value['total_score']."<br>";
}
Please replace your code with only this code. It's give you only 3 post and your total_score ASC or DESC
and Replace data in as per comment
Let me know if any Query
<?php
$args = array(
'post_type' => 'portfolio', // your post type name
'orderby' => 'meta_value_num', // if total_score is string then use it - meta_value
'meta_key' => 'total_score', // your meta key name ( total_score custom field )
'posts_per_page' => 3,
'order' => 'ASC' // ASC or DESC
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) :
while ( $loop->have_posts() ) : $loop->the_post();
echo ''.get_the_title().'';
endwhile;
endif;
wp_reset_postdata();
You could look at using your $args variable to both limit and filter the results of WP_Query. Setting your 'posts_per_page' => 3. This means only 3 posts will be returned in the query.
However, as you are fetching all of the posts and using usort to sort them, you can swap this out to use this resource to help you query using a custom field. This will reduce the amount of work is needed to compile the posts you require.
You can then use the final result to loop over the 3 posts and output your title & permalink.
I'm trying to iterate over some API data and turn it into custom WordPress posts.
My function works, but I can't stop it from creating duplicate posts.
I am checking a unique unitproperty_id field on each iteration to avoid creating duplicates, but it only works in a sporadic way.
Sometimes there will be no duplicate posts, sometimes there will be two, and sometimes three.
It also only happens on the first pass, after the posts have been created (duplicates and non-duplicates) it won't keep creating them each time. The duplicates only appear on the first load.
When this function is working correctly I'll be calling it on a regular basis using wp_cron job, but until then I am calling it using the shutdown action hook that runs at the very end of WordPress loading.
Can you see why I this is generating duplicate posts?
add_action( 'shutdown', 'build_units_from_api', 10 );
function build_units_from_api() {
//Get all the unit IDs currently inside wordpress
$current_property_ids = array();
$wp_units = get_all_wp_posts('unit');
foreach ($wp_units as $wp_unit) {
$current_property_ids[] = (int)get_post_meta( $wp_unit->ID, 'unitproperty_id', true );
}
//Get all the api data
$property_units = get_all_property_units();
$num_of_property_pages = $property_units['pages'];
//Loop through the pages of the API data
for ( $i=0; $i <= $num_of_property_pages; ++$i ) {
$page_of_units = get_property_units_by_page($i);
$num_of_units_on_page = count($page_of_units['results']);
//Loop through the results of each page
for ( $x=0; $x <= $num_of_units_on_page; ++$x ) {
$property_profile = $page_of_units['results'][$x];
//Check if we already have that unit property ID
if ( in_array($property_profile['id'], $current_property_ids, true) || $property_profile['id'] == null ) {
//Do nothing and exit the current iteration
continue;
} else {
//Get the individual profile info from unit property API
$api = new unitpropertyAPI();
$api->getunit($property_profile['id']);
$property_profile_data = json_decode($api->result, true);
$post_arr = array(
'post_type' => 'unit',
'post_title' => $property_profile_data['name'],
'post_content' => '',
'post_status' => 'publish',
'comment_status' => 'closed',
'ping_status' => 'closed',
'meta_input' => array(
'unitproperty_id' => $property_profile_data['id'],
'unit_name' => $property_profile_data['name'],
'unitproperty_rating' => $property_profile_data['rating'],
),
);
//Put those fields into a new 'unit' custom post
$new_id = wp_insert_post( $post_arr );
//Stop from adding this property again
$current_property_ids[] = $property_profile_data['id'];
}
}
}
}
It was the action hook!
I found a solution thanks to this answer: https://wordpress.stackexchange.com/questions/287599/wp-insert-post-creates-duplicates-with-post-status-publish
Changing the action hook to admin_notices fixes the problem because it won't re-fire during the wp_insert_post call.
I want to display 3 specifics posts.
Problem : My posts IDs are from a previous array.
Result : It displays only the first one.
Function :
foreach($fav_author_list as $i => $item) {
$insert = get_user_favorites($item);
if (!is_array($insert[0])) {
$result = array_merge($result, $insert);
}
}
$algoid = implode(",", $result);
Result from $algoid (Post ID) = 865, 866, 877
I want to display the three posts.
$myarray = array($algoid);
$args = array(
'post__in' => $myarray,
);
// The Query
$the_query = new WP_Query( $args );
You don't have to implode your $algoid for the post__in. Since you're using implode, you're actually passing an array with a string for your query:
array('865, 866, 877'); // Items: 1
However, WP_Query is expecting an array with the ids, not as a string:
array(865, 866, 877); // Items: 3
Here's how it should be:
// Use your function to generate the array with the IDs
$algoid = array(865, 866, 877);
$args = array(
'post__in' => $algoid
);
For more information about WP_Query: https://codex.wordpress.org/Class_Reference/WP_Query
post__in (array) - use post ids. Specify posts to retrieve. ATTENTION If you use sticky posts, they will be included (prepended!) in the posts you retrieve whether you want it or not. To suppress this behaviour use ignore_sticky_posts.