Wordpress, random product only on home search page - php

I have a custom wordpress search page with page navigation numbers, my client asks me to random products on page 1 but not for others, but all products displayed randomly on home page should not displayed on others pages.
For the query i have this code :
$args = array(
'post_type' => 'products',
'paged' => ( get_query_var('paged') ? get_query_var('paged') : 1 )
)
and for the random :
if( $args['paged'] == 1) {
$args['orderby'] = 'rand';
} else {
$args['order'] = 'DESC':
}
the results are there when i do a search, and first page random well, but some products that are already displayed on home page because of the random are also displayed on others pages (ex : page 2 ).
The aim is not display products that are already displayed on home page.
I already do something similar :
if( $page == 1 ) shuffle($r->posts);
But it shuffle only first the 10 products on page 1, and others products on others pages never display on page 1.
After some thoughts i think store first 10 random products to cookie or session and do a NOT IN for others pages ? like this ?
if( $args['paged'] == 1 ){
$args['orderby'] = 'rand';
$r = new Wp_Query($args);
$randomFirstPage = wp_list_pluck( $r->posts, 'ID' );
print_r($randomFirstPage);
setcookie( 'firstPageResults', $randomFirstPage, time()+3600, '/', 'mydomain.com/dev' );
}else{
$not_in = $_COOKIE['firstPageResults'];
$args['NOT IN'] = $not_in;
$r = new Wp_Query($args);
}
Sorry for bad english, and may you help me please ?
Thanks

Try this aproach:
<?php
$products1_ids = array();
$products2_ids = array();
$allproducts = get_posts(array('post_type' => 'products'));
$p=1; foreach($allproducts as $products) {
if(is_page(1) && $p<11) {
$products1_ids[] = $products->ID;
}
if(!is_page(1) && $p>10) {
$products1_ids[] = $products->ID;
}
$p++; }
shuffle($products1_ids);
shuffle($products2_ids);
$post_in = is_page(1) ? $products1_ids : $products2_ids;
$products = new WP_Query(array(
'post_type' => 'products',
'posts_per_page' => 10,
'post__in' => $post_in,
));
if($products->have_posts()) {
while($products->have_posts()) { $products->the_post();
echo '<div class="post">'
the_title();
echo '</div>';
}
}
Hope it helps

Your posted code above uses $args['NOT IN'] = $not_in;, but according to the WP_Query docs the argument to exclude posts by id is post__not_in:
$query = new WP_Query(
array('post_type' => 'post', 'post__not_in' => array(2, 5, 12, 14, 20))
);
So try:
$args['post__not_in'] = $not_in;

Related

Wordpress CPT pagination error 1st and 2nd page are fine but not the ones after

I've been trying this for days at this point and I can not get it to work..
I am trying to have a posts page in wordpress with all my posts AND my CPTs. I am doing this by making a post loop with a custom query in index.php which prints fine. Then I try to make it paginate through the paginate_links() function, But I get a 404 error when clicking on it. Which is a common issue. The kicker is that it doesn't do it on the first nor the second page, it only does it on page three and up. An even stranger thing with this code is that it reacts differently on my work computer than on my home computer (they are different local servers with different amount of posts in each post type. I'm guessing that's why they work differently) Anyways on my work computer the second page also gives me an error.
I have already changed my reading settings to 1 post at most per page. I don't know what else I can be doing wrong.
Here is my code:
<?php
$paged = ( get_query_var( 'paged') ) ? get_query_var( 'paged') : 1;
// custom post loop
$arg_custom_post_loop = array(
'post_type' => array('post', 'ljm_utstallningar', 'ljm_event', 'ljm_arkiv', 'ljm_bildarkiv', 'ljm_film', 'ljm_pag'),
'post_status' => 'publish',
'paged' => $paged,
'posts_per_page' => 5,
);
$ljm_custom_post_loop = new WP_Query($arg_custom_post_loop);
$temp_query = $wp_query;
$wp_query = null;
$wp_query = $ljm_custom_post_loop;
if ($ljm_custom_post_loop->have_posts()) {
while ($ljm_custom_post_loop->have_posts()) {
$ljm_custom_post_loop->the_post();
get_template_part('template/default-content-thumbnail', get_post_type());
}
echo paginate_links();
}
$wp_query = null;
$wp_query = $temp_query;
?>
Thanks for the help
Okay I got it to work with this code:
<?php
// fixing pagination for custom loop
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
// code...
}else{
$url= $_SERVER['REQUEST_URI'];
$url = parse_url($url);
}
$current_page = explode('/', $url['query']);
$current_page = end($current_page);
if (!is_numeric($current_page)) {
$current_page = 1;
}
// custom post loop
$arg_custom_post_loop = array(
'post_type' => array('post', 'ljm_utstallningar', 'ljm_event', 'ljm_arkiv', 'ljm_bildarkiv', 'ljm_film', 'ljm_pag'),
'post_status' => 'publish',
'paged' => $current_page,
'posts_per_page' => 5,
);
$ljm_custom_post_loop = new WP_Query($arg_custom_post_loop);
$temp_query = $wp_query;
$wp_query = null;
$wp_query = $ljm_custom_post_loop;
if ($ljm_custom_post_loop->have_posts()) {
while ($ljm_custom_post_loop->have_posts()) {
$ljm_custom_post_loop->the_post();
get_template_part('template/default-content-thumbnail', get_post_type());
}
echo paginate_links(array(
'base' => get_pagenum_link(1) . '%_%',
'format' => '/page/%#%',
'current' => $current_page,
'total' => $ljm_custom_post_loop->max_num_pages,
));
wp_reset_postdata();
}
$wp_query = null;
$wp_query = $temp_query;
?>
Its not pretty but it works, I throw the hole paginate_links() default action out the window and just use it to print the page number in the url. Then I retrieve the number from the url and push it in the paged and current arguments.
Thanks #CBroe for the push to understand why my first code didn't work :)

Exclude specific category from Related Posts

Looking to exclude specific category (ID = 100) from "Related Posts" feed at bottom of Blog pages. Extra bonus if it can also exclude from the sidebar archive (not sure if they are connected??)
I'm using WP Theme "TheFox", have asked them - not part of their theme.
I "think" it has to do in the functions.php. I have found some similar questions, and code, but have not had any luck.
I'm a complete noob for .php, so be gentle :)
I've found some other attempts, no luck. Not registering or effecting the feed.
$categories_to_exclude [ 100 ];
$first_cat = false;
$categories = get_the_category( $post->ID );
while ( ! empty( $categories ) && false === $first_cat ) {
if ( in_array($categories[0]->cat_ID, $categories_to_exclude) ) {
array_shift($categories);
}
else {
$first_cat = $categories[0]->cat_ID;
}
}
What I could gather from your question is that You want to ignore one category (may be more) in the related post query?
use the following CODE (some explanation is given within the CODE in comments):
// set the category ID (or multiple category IDs)
// you want to ignore in the following array
$cats_to_ignore = array( 2 );
$categories = wp_get_post_categories( get_the_ID() );
$category_in = array_diff( $categories, $cats_to_ignore );
// ignore only if we have any category left after ignoring
if( count( $category_in ) == 0 ) {
$category_in = $categories;
}
$cat_args = array(
'category__in' => $category_in,
'posts_per_page' => 4,
'orderby' => 'date',
'post__not_in' => array( get_the_ID() )
);
$cat_query = new WP_Query( $cat_args );
while ( $cat_query->have_posts() ) : $cat_query->the_post();
/* just example markup for related posts */
echo '<h2>' . get_the_title() . '</h2>';
endwhile;
// reset $post after custom loop ends (if you need the main loop after this point)
wp_reset_postdata();
Use the below code, it must work
$categories_to_exclude [ 81, 11, 21 ];
$first_cat = false;
$categories = get_the_category( $post->ID );
while ( ! empty( $categories ) && false === $first_cat ) {
if ( in_array($categories[0]->cat_ID, $categories_to_exclude) ) {
array_shift($categories);
}
else {
$first_cat = $categories[0]->cat_ID;
}
}
You get the categories with get_the_category. Then in the while loop you skip the first category if it's 81, and look again. If it's not 81 (and you still have categories available), you asign it to $first_cat and carry on.

How to get the next $args when if:false?

I am new in programming... (The question absolutely about programming, but I use wordpress) I try to be very clear:
I have a subdomain based multisite network. If the users posts to their sites, I get a clone from the current post to my network home. This clone have a canonical url, what shows to the original post, and the post slug's also concur (the ID's dont.)
example: x user posted:
url: xusersite.network.com/4243345/this-is-slug-by-post-title
canonical: xusersite.network.com/4243345/this-is-slug-by-post-title
I get:
url: network.com/123677745/this-is-slug-by-post-title
canonical: xusersite.network.com/4243345/this-is-slug-by-post-title
Now I want get the clone post's ID, on the subsite, by the original post... so I have this code:
switch_to_blog( 1 );
$canonical = 'xusersite.network.com/4243345/this-is-slug-by-post-title';
$slug = 'this-is-slug-by-post-title'; // current slug
$args = array(
'name' => $slug,
'post_type' => 'post',
'post_status' => 'publish',
'numberposts' => 1
);
$my_posts = get_posts($args);
Thats ok, but the problem, if an another user posted with the same title for his blog, example: y user posted:
url: yusersite.network.com/72543/this-is-slug-by-post-title
canonical: yusersite.network.com/72543/this-is-slug-by-post-title
I get a post, with the same slug:
url: network.com/776536556733/this-is-slug-by-post-title
canonical: yusersite.network.com/72543/this-is-slug-by-post-title
So my php knowledge now here it is, I can do this:
if( $my_posts ) :
$cloneid = $my_posts[0]->ID;
$clonecanonical = wp_get_canonical_url( $cloneid );
if( $clonecanonical == $canonical ) :
$exit = 'true';
else :
$exit = 'false';
endif;
endif;
How can I get the next $my_posts, so $my_posts[1]->ID, if the $exit is false? How can I get the right $my_posts?
Not sure to have understood, but you should get the numeer of posts in my posts using count($my_posts) and then use a for or while to iterate through the full $my_posts.
something like this:
if( $my_posts ) :
$numPosts=count($my_posts)
//if $numPosts = 0 then $my_posts[0] does not exist
//but if you are here $numPosts must be > 0
if $numPosts > 0 {
for ( $i = 0; $i < $numPosts; $i++ ){
$cloneid = $my_posts[$i]->ID;
$clonecanonical = wp_get_canonical_url( $cloneid );
if( $clonecanonical == $canonical ) :
$exit = $my_posts[$i]->ID;
endif;
}
}
endif;

Wordpress get_posts() fetch next batch of posts

I'm using the get_posts() function to fetch a batch of posts from a custom post type, sorted by ID, modify those posts and then fetch the next batch.
I have the following code:
<?php
require_once('wp-load.php');
$temp_list_of_products_array = get_posts( array('post_type' => 'sale', 'numberposts' => 10 ) );
$temp_list_of_products_array_length = count( $temp_list_of_products_array );
for ($xt = 0; $xt < $temp_list_of_products_array_length; $xt++) {
$temp_product_id = $temp_list_of_products_array[$xt]->ID;
$temp_product_untranslated_field = get_post_meta($temp_product_id, 'wpcf-product-details', true);
$temp_product_translated_field = get_post_meta($temp_product_id, 'wpcf-translated-product-details', true);
$temp_product_description_language = 'en';
if ($temp_product_translated_field == null) {
$temp_product_translated_contents = google_translate_text($temp_product_untranslated_field, $temp_product_description_language);
update_post_meta($temp_product_id, 'wpcf-translated-product-details', $temp_product_translated_contents);
}
echo $temp_product_id;
}
?>
This works great but the problem is that it only loads the first 10 posts ordered by date.
My question is, how do I get the next batch of 10 posts without have a user activated pagination call?
Thanks
first get the current page
$paged=($query_vars['paged']!=0 ? $query_vars['paged'] : 1);
now calculate the offset value
$numberposts=10;
$ofdset=$numberposts* ($paged - 1) ;
add your code
$temp_list_of_products_array = get_posts( array('post_type' => 'sale', 'numberposts' => 10 ,'offset'=>$offset) );
$temp_list_of_products_array_length = count( $temp_list_of_products_array );
for ($xt = 0; $xt < $temp_list_of_products_array_length; $xt++) {
$temp_product_id = $temp_list_of_products_array[$xt]->ID;
$temp_product_untranslated_field = get_post_meta($temp_product_id, 'wpcf-product-details', true);
$temp_product_translated_field = get_post_meta($temp_product_id, 'wpcf-translated-product-details', true);
$temp_product_description_language = 'en';
if ($temp_product_translated_field == null) {
$temp_product_translated_contents = google_translate_text($temp_product_untranslated_field, $temp_product_description_language);
update_post_meta($temp_product_id, 'wpcf-translated-product-details', $temp_product_translated_contents);
}
echo $temp_product_id;
}
add pagination code at bottom of loop
check this for wordpress pagination with get_posts function
https://wordpress.stackexchange.com/questions/137100/using-pagination-with-get-posts-on-page-type
You can simply use the paged parameter:
$current_page = 1; // <-- Modify this to your needs!
$temp_list_of_products_array = get_posts(
array(
'paged' => $current_page,
'post_type' => 'sale',
'posts_per_page' => 10
)
);
for paging.

Insert a post type every x posts in custom loop

I was hoping someone could help me with this problem.
I'm trying to make a loop in wordpress with two different post types ('product' and 'outfits')
The code below is working fine, this outputs a list of the two post types ordered by newest to older.
$loop = new WP_Query( array(
'post_type' => array( 'product', 'outfits' ),
'posts_per_page' => 15
) );
$counter = 0;
?>
<?php if ( $loop->have_posts() ) { while ( $loop->have_posts() ) { $loop->the_post();
$counter++; ?>
<?php $loop->is_home = false; ?>
<?php
$large_image_url = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), 'large');
$titulo = get_the_title();
$content = apply_filters ('the_content', $post->post_content); ?>
<div class="caja-<?php echo $counter; ?>">
<?php if ( $post->post_type == "product" ) {
//some stuff
<?php } else {
//some stuff
} ?>
</div>
<?php } } wp_reset_postdata();
What I would like to do is to insert a product post type after X number of outfits.
I was trying to merge a similar solution I've found in other question with no luck. I'm not a php expert so any help is appreciated
<?php
$args = array('post_type'=>'post', 'posts_per_page'=>9, 'category_name'=>'news');
$posts = get_posts($args);
$args = array('post_type'=>'testimonials', 'posts_per_page'=>3);
$testimonials = get_posts($args);
// see how many of the regular posts you got back //
$post_count = count($posts);
// see how many testimonials you got back //
$testimonial_count = count($testimonials);
// add them up to get the total result count //
$total_count = $post_count + $testimonial_count;
// Loop through the total number of results //
for($i = 1; $i <= $total_count; $i++){
// assuming you want to show one testimonial every third post //
if($i % 3 == 0){
// this means you're on the a third post, show a testimonial //
setup_postdata($testimonials[$i]);
}
else{
/** show a regular post */
setup_postdata($posts[$i]);
}
/** and now handle the output */
?><h1><?php the_title();?></h1><?php
} ?>
$x = 3;
$products = get_posts(array(
'post_type' => 'product',
'posts_per_page' => -1
));
$outfits = get_posts(array(
'post_type' => 'outfit',
'posts_per_page' => -1
));
foreach ($outfits as $num => $outfit) {
if ( ($num+1) % $x == 0) {
if (isset($products[($num+1)/$x - 1])) {
array_splice( $outfits, $num, 0, array($products[($num+1)/$x - 1]) );
}
}
}
foreach ($outfits as $outfit) {
$posts_id[] = $outfit->ID;
}
$query = new wp_query(array(
'post_type' => array('outfit', 'product'),
'post__in' => $posts_id,
'posts_per_page' => 15,
'orderby' => 'post__in'
));

Categories