Getting related articles in WordPress not working - php

I am trying to display all the posts with the same category in WordPress however its not displaying correctly and instead is just showing everything.
Here is the php code:
<?php
$related = get_posts( array(
'category_in' => wp_get_post_categories($post->ID),
'numberposts' => 3,
'post_not_in' => array($post->ID) ) );
if( $related ) foreach( $related as $post ) {
setup_postdata($post); ?>
<div class="post">
<a href="<?php the_permalink(); ?>">
<?php if ( has_post_thumbnail() ) {
the_post_thumbnail();
}
?>
<h3><?php the_title();?></h3>
</a>
</div>
<?php }
wp_reset_postdata();
?>
Its taken from here: https://wordpress.stackexchange.com/questions/41272/how-to-show-related-posts-by-category
And if it helps here is the link to the website in question where the code isnt working:http://u1f8aki.nixweb23.dandomain.dk/cat-4-post-test/
The code in question is further down the page under the red text. You can see the category at the top in the breadcrumbs.

There are quite errors in your code, and I'm sure atleast one of them are the culprit in giving you the wrong result.
I've refactored your code with some comments explaining what and why has been changed:
<?php
// For readability, save our categories in a variable for later use.
// $post->ID has been replaced with get_the_ID(), $post might not be accessible depending if you're exposing $post as a global or not.
$categories = wp_get_post_categories(get_the_ID());
/*
Instead of using get_posts(), use the recommended Wordpress loop in the form of WP_Query().
We start by defining our arguments for the loop
*/
$args = array(
'category_in' => $categories, // here we use variable for readability
'posts_per_page' => 3, //numberposts and posts_per_page has the same function, but posts_per_page is the more common of the two (IMO)
'post__not_in' => array(get_the_ID()) // you were missing a '_', ie post_not_in instead of post__not_in
);
// Start the loop
$query = new WP_Query($args);
if($query->have_posts()): while($query->have_posts()): $query->the_post();
// No need to setup or reset postdata when using this method, it does it for you!
?>
<div class="post">
<a href="<?php the_permalink(); ?>">
<?php
if( has_post_thumbnail() ) {
the_post_thumbnail();
}
?>
<?php
// the_title() actually takes opening tag and closing tags as arguments in its function. So add the <h3> code like this.
the_title('<h3>', '</h3>');
?>
</a>
</div>
<?php endwhile; endif; ?>
Long story short, your code prolly isn't working because of the miss-named arguments. If you don't feel like replacing your code with my example, just change your arguments from numberposts to posts_per_page, and post_not_in to post__not_in.
If it still isn't working, check what wp_get_post_categories(get_the_ID()) is returning for each post, and make sure all posts aren't sharing some category you missed.
Edit: numberposts is actually a valid argument, changed my answer to reflect this.

Related

Only showing the first sentence of a WordPress post on the front page as a "highlighted post" section

I'm currently working on my first WordPress theme and I want to create a "Highlighted Post" section on my index.php. There are a lot of scripts for this but all seem to apply a permanent filter over the entire index.php. That is problematic since i want to show the whole posts on my index.php below. Is there a way to apply this special filter only for this section and not for the whole index.php?
If you could give us more info what determines this "Highlighted" posts we might be able to be more specific in solving this.
But in the mean time I'll guess it's two latest posts which means you could have two queries in the index.php
First one would be for "Highlighted" ones:
<?php
$args = array( 'numberposts' => 2 );
$lastposts = get_posts( $args );
foreach($lastposts as $post) : setup_postdata($post);
?>
<h2 class="news"><?php the_title(); ?></h2>
<?php the_excerpt(); ?>
<?php endforeach; ?>
This will give you excerpt of your post in this query.
What you could do then is limit excerpt to whatever length you'd like and add read more link if you want :)
function newExcerpt($more) {
global $post;
return '... Read more';
}
add_filter('excerpt_more', 'newExcerptReadMore');
function customExcerptLength( $length ) {
return 20;
}
add_filter( 'excerpt_length', 'customExcerptLength', 999 );
And for other posts you could do another query but not using first two posts like this:
$count = 0;
$lastposts = get_posts();
foreach($lastposts as $post) : setup_postdata($post);
if($count > 1)
?>
<h2 class="news"><?php the_title(); ?></h2>
<?php the_excerpt(); ?>
$counter++;
<?php endforeach; ?>
This will just loop through the posts and skip first two posts.
If you have some other term or category or something else that determine Highlighted posts then you can use that in and pass it as an argument to get_posts($args).

Put php into a function to shortcut

New to php, but I've learned how it works (I mean, I can write php and do the things in the YouTube tutorials). I'm having difficulty applying it to actual use though:
I want to shorten the amount of php I need to put on frontpage.php (WordPress, but I hear this question is not a WordPress question; just a php one).
I'm going to call the same php many times to display 1 post each time, just changing the category to display in the php - so, now I have:
lots of php cat=33 lots of php
I want to make a function so that on my frontpage.php, I just need to write:
whatever cat=33 whatever
or just
whatever 33
If it helps to have my code, it is (this has tag, but I use both tag and cat here and there):
<?php
$args=array(
'tag' => 'feature-left',
'showposts'=>1,
'caller_get_posts'=>1
);
$my_query = new WP_Query($args);
$offset = 3;
if( $my_query->have_posts() ) {
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>" itemscope="itemscope" itemtype="http://schema.org/BlogPosting" itemprop="blogPost">
<h4><?php the_excerpt(); ?> </h4>
</a>
<a href="<?php the_permalink() ?>" >
<div class="front-first-article-title" itemprop="headline"><h2 style="color:#00589C; margin-bottom:5px;"><b><?php the_title(); ?></b></h2>
</div>
<?php
endwhile;
} //if ($my_query)
wp_reset_query(); // Restore global post data stomped by the_post().
?>
In your theme folder, find your functions.php file.
In that file, place this code (from your question) into a function, like so:
function my_custom_loop($category) {
$args=array(
'tag' => 'feature-left',
// showposts has been replaced, use 'posts_per_page' instead
// 'showposts' =>1,
'posts_per_page' => 1,
// this has been replaced, use 'ignore_sticky_posts'
// 'caller_get_posts' => 1,
'ignore_sticky_posts' => true,
'cat' => $category
);
$my_query = new WP_Query($args);
$offset = 3;
if( $my_query->have_posts() ) {
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>" itemscope="itemscope" itemtype="http://schema.org/BlogPosting" itemprop="blogPost">
<h4><?php the_excerpt(); ?> </h4>
</a>
<a href="<?php the_permalink() ?>" >
<div class="front-first-article-title" itemprop="headline"><h2 style="color:#00589C; margin-bottom:5px;"><b><?php the_title(); ?></b></h2>
</div>
<?php
endwhile;
} //if ($my_query)
wp_reset_query(); // Restore global post data stomped by the_post().
}
Now, in your home page file, you can drop in my_custom_loop(33) to have it output your custom post loop.
NOTE
There's a few issues with your HTML inside your loop. You shouldn't put <div> or <h2> or <h4> elements inside of an <a> tag. Also, your <a> tag is not getting closed properly. Lastly, I'd suggest using classes / CSS rather than inline styles on your <h2>, as it's going to be output to the screen many times, and it's sorta silly to output the exact same inline CSS a bunch of times.
EDIT
Per your recent comments, yes, you could make the function also handle tags, and have the "number" be dynamic. Note that there are a variety of approaches to this sort of issue, but the most direct (given your existing function) would be something like so:
/* Note the "default values" for $tag and $offset.
* You can call this function in many ways:
* my_custom_loop(33); just get the categories, with an offset of 3
* my_custom_loop(33, NULL, 5); get the categories, offset of 5
* my_custom_loop(NULL, 'feature-left'); get the tags, offset of 3
* my_custom_loop(NULL, 'feature-left', 5); get the tags, offset of 5
*/
function my_custom_loop($category, $tag = NULL, $offset = 3) {
$args=array(
// showposts has been replaced, use 'posts_per_page' instead
// 'showposts' =>1,
'posts_per_page' => 1,
// this has been replaced, use 'ignore_sticky_posts'
// 'caller_get_posts' => 1,
'ignore_sticky_posts' => true,
);
if ($category) {
$args['cat'] = $category;
}
if ($tag) {
$args['tag'] = 'feature-left';
}
$my_query = new WP_Query($args);
// ... rest of function to output loop
}
if you dont want your functions to be crowded you can create folder lets call it templates/parts/
for each part you want to reuse put inside one .PHP file .
then any where you need this block you call it
<?php include(locate_template( 'templates/parts/slider-box.php' ));?>
this is better from design prospective . for example the main page for one website I am building looks like this
<?php $catNum = 23; ?>
<?php include(locate_template( 'templates/parts/slider-box.php' ));?>
<?php include(locate_template( 'templates/parts/ads3.php' ));?>
<?php $catNum = 2; ?>
<?php include(locate_template( 'templates/parts/catBlox-main.php' ));?>
<?php $catNum = 4; ?>
<?php include(locate_template( 'templates/parts/catBlox-main.php' ));?>
<?php $catNum = 3; ?>
<?php include(locate_template( 'templates/parts/catBlox-main.php' ));?>
and I have all the files for each parts in one folder I can move them to other project or when there is problem it easer to go to file other than go to function in 1 big function.php

How to display most viewed posts in custom post type

I'm using keremiya theme for wordpress. I was trying to display my most viewed post in my custom post type if "most_viewed" option is on. The name of my custom post type is watch. How can i do this with my current code? I am also using a plugin called wp-post views to display the views in my sidebar. Here is my query.
<?php if(get_option('most_viewed') == 'On'): ?>
<div class="sidebar-right">
<h2><?php echo get_option('my_title'); ?></h2>
<div class="fimanaortala">
<?php $tavsayi = get_option('keremiya_tavsiyesayi'); $tavkat = get_option('keremiya_tavsiyekat');?>
<?php query_posts('showposts='.$tavsayi.'&v_orderby=desc&cat='.$tavkat.'') ?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div class="filmana">
<div class="filmsol">
<?php keremiya_resim('80px', '70px', 'izlenen-resim'); ?>
</div>
<div class="filmsag">
<div class="filmsagbaslik">
<?php the_title(); ?>
</div>
<div class="filmsagicerik">
<?php if(function_exists('the_views')) { the_views(); echo " "; } ?>
<p><?php nezaman_yazildi(); ?></p>
</div>
<div class="filmizleme">
<img src="<?php bloginfo('template_directory'); ?>/images/filmizle.png" alt="film izle" height="21" width="61" />
</div>
</div>
</div>
<?php endwhile; else: ?>
<?php endif; ?>
<?php wp_reset_query(); ?>
</div>
</div>
Your solution (or attempt, at least), is based on a plugin called WP-PostViews, which I have no knowledge of. So, I can't really help you there. I can, however, help you solve it without this or any other plugin. So here we go:
Wordpress has a little something called metadata. From this very own link:
The Metadata API is a simple and standarized way for retrieving and manipulating metadata of various WordPress object types. Metadata for an object is a represented by a simple key-value pair. Objects may contain multiple metadata entries that share the same key and differ only in their value.
That means you can create metadata for your custom post type that contains how many times it has been seen. To do so, we create a function:
<?php
function set_views($post_ID) {
$key = 'views';
$count = get_post_meta($post_ID, $key, true); //retrieves the count
if($count == ''){ //check if the post has ever been seen
//set count to 0
$count = 0;
//just in case
delete_post_meta($post_ID, $key);
//set number of views to zero
add_post_meta($post_ID, $key, '0');
} else{ //increment number of views
$count++;
update_post_meta($post_ID, $key, $count);
}
}
//keeps the count accurate by removing prefetching
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0);
?>
This will, given the post ID, increment a counter every time a post is viewed. Of course, we have to call this function somewhere in our code so it actually runs. You can do this in two ways: You can either call this function on your single template (which I believe is called single-watch.php), or you can add a simple tracker. I favor the second option, as it keeps your single post loop cleaner. You can achieve such tracking this way:
<?php
function track_custom_post_watch ($post_ID) {
//you can use is_single here, to track all your posts. Here, we're traking custom post 'watch'
if ( !is_singular( 'watch') ) return;
if ( empty ( $post_ID) ) {
//gets the global post
global $post;
//extracts the ID
$post_ID = $post->ID;
}
//calls our previously defined methos
set_views($post_ID);
}
//adds the tracker to wp_head.
add_action( 'wp_head', 'track_custom_post_watch');
?>
There you go. Now, WordPress checks if the user is visiting a page corresponding to a watch single post. If they are, it increments the counter.
The only thing left now is to query for the post with the highest number of views. This is easily achievable using WP_Query. When you create your loop, do something like this:
<?php
$query = new WP_Query( array(
'post_type' => 'watch', //your post type
'posts_per_page' => 1,
'meta_key' => 'views', //the metakey previously defined
'orderby' => 'meta_value_num',
'order' => 'DESC'
)
);
while ($query->have_posts()) {
$query->the_post();
//whatever code you want
}
?>
I kept my answer to PHP, so you can adapt to your mark-up needs. I also assumed your post-type is indeed called watch. I hope all of this helps you. If you want to query your posts in a slightly different way, I suggest you read the WP_Query docs. Cheers.

wordpress query_posts alternative

I am creating a website that integrates a portfolio which uses custom post types, this was done based off of this tutorial.
So far it is exactly what I am looking for and works great except for one small detail. In order to fetch the posts from the new custom post type the author of the tutorial used the query_posts() codex. So the top of my portfolio page looks like this:
<?php
/* Template Name: Portfolio */
get_header();
query_posts('post_type=portfolio&posts_per_page=10');
?>
What I gather is that this declares "get posts from "post type" portfolio and show 10 per page". My problem is that I can't go get content from my portfolio page. It seems that now my portfolio page only fetches the content from the custom post type, and I can't use:
<?php while ( have_posts() ) : the_post(); ?>
<?php the_content(); ?>
<?php endwhile; // end of the loop. ?>
to get content from the actual page.
This is what I am trying to do, I've replaced:
query_posts('post_type=portfolio&posts_per_page=10');
with:
add_action( 'pre_get_posts', 'add_my_post_types_to_query' );
function add_my_post_types_to_query( $query ) {
if ( is_page( 8 ) && $query->is_main_query() )
$query->set( 'post_type', array( 'portfolio' ) );
return $query;
}
This seems like the right track, but it stills doesn't work. I'm not getting the posts from my custom post type.
Any ideas how I could modify this? I am also still learning so being clear with explanations would be greatly appreciated.
Thank you!
Editing the pre_get_posts will replace the original query and you will not have the content for your page at all. I would only recommend going this approach if you only wanted to display the content of your portfolio post type and not the content of your portfolio page.
For general post queries it is recommended to use WP_Query or get_posts.
http://codex.wordpress.org/Class_Reference/WP_Query
http://codex.wordpress.org/Template_Tags/get_posts
If you use the WP_Query function the wp_reset_postdata() will restore the post data back to the original so you can get the content of your original page.
$args = array(
'posts_per_page' => 10,
'post_type' => 'portfolio',
);
// The Query
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
echo '<li>' . get_the_title() . '</li>';
}
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
Now you will be able to use the original loop to show the content of your page
<?php while ( have_posts() ) : the_post(); ?>
<?php the_content(); ?>
<?php endwhile; // end of the loop. ?>
Usually, I stick my query posts in a variable, like so:
$catid = get_cat_ID('My Category Name');
$args = array(
'posts_per_page' => 5,
'orderby' => 'post_date',
'order' => 'DESC',
'post_type' => 'post',
'post_status' => 'publish',
'category' => $catid
);
$posts_array = get_posts($args);
Then you can loop it like so:
<?php foreach ($posts_array as $post) : setup_postdata($post);?>
<h1><?php the_title(); ?></h1>
<p><?php the_content(); ?></p>
<?php endforeach; ?>
Finally, to access your page content you can use the variable $post, it's automatically set by wordpress. No need to add any more code than this to access your page content.
<?php foreach( $posts as $post ) : setup_postdata($post); ?>
<h1><?php the_title(); ?></h1>
<p><?php the_content(); ?></p>
<?php endforeach; ?>
The foreach loop for your page content is a little overkill, and there is a better way to do it (most likely at least), but I haven't been bothered to look into it further yet! It works though!

How do I get wordpress to override a previous posts query?

I've got a page that has a category list at the top, and should normally list posts below it. The category list is created using:
<?php $display_categories = array( 4, 7, 8, 9, 21, 1); $i = 1;
foreach ( $display_categories as $category ) { ?>
<div>
<?php single_cat_title(); ?> //etc
</div>
<?php }
?>
However, this seems to make the post loop order posts by category. I want it to ignore category ordering and order by date in descending order. I've created a new WP_Query since according to the docs you can't use query_posts() twice, so just in case.
<?php $q = new WP_Query( "cat=-1&showposts=15&orderby=date&order=DESC" );
if ( $q->have_posts() ) :
while ( $q->have_posts() ) : $q->the_post(); ?>
the_title(); // etc
endwhile;
endif;
?>
However, this still seems to be ordered by category (the same order as the list above) and then by date, as opposed to just by date.
I've had problems with this before as well.
Try this:
<?php
global $post;
$myposts = get_posts( 'numberposts=5' );
foreach( $myposts as $post ) : setup_postdata( $post ); ?>
<div <?php post_class(); ?>>
<div class="title">
<h2>
<?php the_title(); ?>
</h2>
<p class="small"><?php the_time( 'F j, Y' ); ?> by <?php the_author(); ?></p>
</div>
<?php the_excerpt(); ?>
</div>
<?php endforeach;
?>
The important line is global $post;.
That should reset your global query. The setup_postdata($post) method is necessary to give you access to functions like the_author() or the_content().
-Chris
I don't have any experience with wordpress, but a couple of possibilities:
You define the "order" parameter twice in the string you're calling query_posts() with, I don't know if that causes a problem or not.
As well, "show" is not a valid parameter, you may have been looking for "showposts".
Parameters and their effects are described here: http://codex.wordpress.org/Template_Tags/query_posts#Parameters
query_posts is finicky sometimes. Try something like this and see if it works:
query_posts(array('category__not_in'=>array(1),
'showposts'=>15,
'orderby'=>date,
'order'=>DESC));
Since that's not the issue, try adding update_post_caches($posts) to the second loop, like this:
<?php $q = new WP_Query("cat=-1&showposts=15&orderby=date&order=DESC");
if ( $q->have_posts() ) : while ( $q->have_posts() ) : $q->the_post(); update_post_caches($posts); ?>
the_title(); // etc
endwhile; endif; ?>
Supposedly this solves some plugin problems.

Categories