My php-wordpress if while loop only runs the first time - php

My code had a typo!
But im not allowed to delete this so here you have some info on ways you could have done a better job then me ;)
The problem is as follows, My query is skipping a part of my loop.
i have a query that makes a anchor with the title and thumbnail of the post.
it runs the query fine for the first post except for the second post it does not load in the thumbnail, but it does show the title, and the title is only mentioned after the thumbnail, There is no small image that resembles it cant be found either. My first question posted on here so apolagies for misplacing items in the wrong sections.
<?php
// WP_Query arguments
$args = array (
'post_type' => array( 'klantcase' ),
'post_status' => array( 'publish' ),
'nopaging' => true,
'order' => 'ASC',
'orderby' => 'menu_order',
);
// The Query
$klantcases = new WP_Query( $args );
// The Loop
if ( $klantcases->have_posts() ) {
while ( $klantcases->have_posts() ) {
$klantcases->the_post();
echo "<a href=".get_the_permalink().">";
echo get_the_post_thumbnail( null, $size = 'post-thumbnail');?><br><?php
echo the_title();?><br><?php
echo "</a>";
}
} else {
echo "no posts found";
}
// Restore original Post Data
wp_reset_postdata();
Now there is probably many ways to improve this loop but as mentioned im very new to all of this. That said i'd love to hear how you guys would resolve this issue.

Define empty variable on top of while loop.
And in loop concatenate your html with that empty variable.
For Example.
$output = '';
if ( $klantcases->have_posts() ) {
while ( $klantcases->have_posts() ) {
$klantcases->the_post();
$output .= '<a href="'.the_permalink().'">';
$output .= the_post_thumbnail() .'<br>';
$output .= the_title();
$output .= '</a>';
}
} else {
echo "no posts found";
}
echo $output;

You don't need to echo the_title() - it already echoes out, so I'm guessing that's where part of the problem is coming in. You can also make your loop a little more simple.
You don't need the 'post_status' argument, as publish is default.
In your loop, let's use WP's built in echo functions: the_permalink(), the_title() and the_post_thumbnail(). You don't have to pass any arguments to the the_post_thumbnail() because you are just calling the default in your code.
<?php
// WP_Query arguments
$args = [
'post_type' => ['klantcase'],
'nopaging' => TRUE,
'order' => 'ASC',
'orderby' => 'menu_order',
];
// The Query
$klantcases = new WP_Query( $args );
// The Loop
if ( $klantcases->have_posts() ) {
while ( $klantcases->have_posts() ) {
$klantcases->the_post(); ?>
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail(); ?><br>
<?php the_title(); ?>
</a>
<?php
}
} else {
echo 'no posts found';
}
// Restore original Post Data
wp_reset_postdata();

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!

List each custom post type separately in a wp_query without repeating the loop

I'm using an AJAX search to pull 3 custom post types from wordpress (post, guides, advice). As you can see in my if while loop, the results show which results are which but I'm trying to section them out individually so it will show something like this:
section 1
blog posts
section 2
guides
The problem seems to be that I need to edit the if while loop because adding anything inside that loop will just cause it to be in that loop. Does anyone know the best way to modify the if while loop to achieve this?
function data_fetch(){
$the_query = new WP_Query(
array(
'posts_per_page' => 6,
's' => esc_attr( $_POST['keyword'] ),
'post_type' => array('post' , 'guides', 'advice'),
'post_status' => 'publish'
)
);
global $post;
if( $the_query->have_posts()) :
while( $the_query->have_posts() ): $the_query->the_post(); ?>
<?php $type = get_post_type();
$term = $_POST['keyword'];
$i++;
$total = $the_query->found_posts;
?>
<span class="search-title">
<?php if ($type == 'post'):?>
<?php echo 'Article: ';?>
<?php elseif($type == 'guide' ):?>
<?php echo 'Guide: ';?>
<?php elseif($type == 'advice' ):?>
<?php echo 'advice: ';?>
<?php endif;?>
<?php the_title();?><br>
</span>
<?php endwhile; ?>
<?php
wp_reset_postdata();
else:
echo '<h3>No Results Found</h3>';
endif;
die();
}
If I were you, I'd probably just do three separate queries. They seem simple enough that it shouldn't cause any issues at all. Otherwise you have to either sort through or reorder the WP_Query results somehow.
If you're set on the single query, however - since these are such short HTML strings, I'd probably just control the output with the Output Buffer.
Basically you can create an associative array, and add the HTML strings to the appropriate keys. You could get a bit more elaborate and have them be nested arrays, but since your output is so light, you can probably get by just by having HTML strings as the values for the keys.
I took the liberty of cleaning up your code a little bit and removing some unused variables, etc.
function data_fetch(){
// Build the Query Arguments
$the_query = new WP_Query( array(
's' => esc_attr($_POST['keyword']),
'posts_per_page' => 6,
'post_type' => array('post' , 'guides', 'advice'),
'post_status' => 'publish'
) );
// Do we have posts?
if( $the_query->have_posts()){
// We do. Start an array that will fill with HTML from the output buffer
$output = array(
'post' => '',
'guides' => '',
'advice' => '',
);
// Loop through the posts
while( $the_query->have_posts() ){
$the_query->the_post();
ob_start(); // Turn on the output buffer
$type = get_post_type(); ?>
<span class="search-title">
<?php echo ($type == 'post') ? 'Article: ' : ucwords($type).': '; // Output "Articles: " for posts, or just capitalize the other post type names ?>
<?php the_title();?><br>
</span>
<?php $output[$type] .= ob_get_clean(); // Add the HTML output from the buffer to our array
}
wp_reset_postdata();
// Here we have an array with 3 HTML strings that we can output wherever
echo $output['post'];
echo $output['guides'];
echo $output['advice'];
} else {
echo '<h3>No Results Found</h3>';
}
}
if I understood your concern, I propose to divide your code by creating a generic class.
and you make calls to the different Post Type :
class Custom_Query {
public $post_type;
public $key_word;
public function __construct($post_type, $keyword) {
$this->post_type = $post_type;
$this->key_word = $keyword;
}
public function getResult() {
echo '<h1>Article : ' . $this->post_type . '</h1>';
$the_query = new WP_Query(
array(
'posts_per_page' => 6,
's' => esc_attr($this->key_word),
'post_type' => array($this->post_type),
'post_status' => 'publish'
)
);
if ($the_query->have_posts()):
while ($the_query->have_posts()): $the_query->the_post();
echo '<span class="search-title">';
echo '' . the_title() . '<br>';
echo '</span>';
endwhile;
else:
echo '<h3>No Results Found</h3>';
endif;
wp_reset_postdata();
}
}
global $post;
$type = get_post_type();
$term = $_POST['keyword'];
$article = new Custom_Query($type, $term);
$article->getResult();
You were on the right track initially. You can just use the standard post objects to check for post type. You can adjust to fit your needs, but try something like this:
<?php
query = new WP_Query( array(
's' => esc_attr($_POST['keyword']),
'posts_per_page' => 6,
'post_type' => array('post' , 'guides', 'advice'),
'post_status' => 'publish'
) );
if ($query->have_posts()) {
while ($query->have_posts()):
$query->the_post();
?>
<div class="posts">
<?php
if ($query->post->post_type === 'post') {
// add your content
} else if ($query->post->post_type === 'guides' {
// add your content
} else {
// add your content
}
?>
</div>
<?php endwhile;
} else {
// no posts found
}

wordpress shortcode render content in dashboard also

I am using a simple wordpress shortcode
function my_recent_post()
{
echo 'hello';
}
add_shortcode( 'recent', 'my_recent_post' );
with the shortcode [recent] and its working fine and visible in front page,
but the problem is, its printing the hello in the dashboard also.
below is the screenshot, can anyone please help.
Update:
I was actually trying to show posts, so can you help me with this, because it renders the lists of posts in the dashboard itself like the "hello". I tried:
function lorem_function() {
global $post;
$args = array( 'posts_per_page' => 10, 'order'=> 'ASC', 'orderby' => 'title' );
$postslist = get_posts( $args );
foreach ( $postslist as $post ) :
setup_postdata( $post ); ?>
<div>
<?php the_date(); ?> <br /> <?php the_title(); ?> <?php the_excerpt(); ?>
</div>
<?php endforeach;
wp_reset_postdata();
return;
}
add_shortcode('lorem', 'lorem_function');
Based on your comments to me & Nikita Dudarev, what you need to do is create a variable to hold all the post information and then return it. Using the function you posted as an example:
function lorem_function() {
global $post;
$args = array( 'posts_per_page' => 10, 'order'=> 'ASC', 'orderby' => 'title' );
$postslist = get_posts( $args );
// create a variable to hold the post information
$html ="";
foreach ( $postslist as $post ) :
setup_postdata( $post );
$backgroundstyle = "";
// get the featured image and set it as the background
if ( has_post_thumbnail() ) { // make sure the post has a featured image
$imageurl = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), 'medium' ); // you can change "medium" to "thumbnail or full depending on the size you need
// add the css for the background image. You can include background-size etc ad required
$backgroundstyle = "background-image: url('".$imageurl[0]."');";
}
// add the information to the variable
$html .= '<div style="'.$backgroundstyle.'">';
$html .= get_the_date();
$html .= "<br />";
$html .= get_the_title();
$html .= get_the_excerpt();
$html .= "</div>";
endforeach;
wp_reset_postdata();
return $html;
}
add_shortcode('lorem', 'lorem_function');
Note that the_date(), the_title() and the_excerpt() all display the information (just like echo).
Instead you must use get_the_date(), get_the_title() and get_the_excerpt() - these get the same information, but instead of displaying it directly, they return it as a variable which you can then store in your html string to be returned.
Update:
As you don't want to use the variable name on each line for whatever reason, you can do it like this:
$html .= "<div>".get_the_date()."<br />".get_the_title().get_the_excerpt()."</div>";
I'm not sure why you specifically want to change it to do that - it makes absolutely no difference to how it works, it just makes it harder to read and identify any errors :-)
Your function must return a value, not output
function my_recent_post()
{
return 'hello';
}
add_shortcode( 'recent', 'my_recent_post' );

Wordpress loop media by "uploaded By"

I have a webpage that I want to display images that are uploaded by a certain author.
In the backend if I look at media, each image has an 'Uploaded By' attribute, and then it says the authors name.
(source: discoveryourwonder.com)
I've tried using this loop:
<?php
// The Query
$args = array(
'author' => $author_name_variable, // Replace with author id
'post_status' => 'any',
'post_type' => 'attachment'
);
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
echo '<ul>';
while ( $the_query->have_posts() ) {
$the_query->the_post();
echo '<li>' . the_content() . '</li>';
}
echo '</ul>';
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
?>
It is very buggy. Some authors it will show every media file, others none; the rest are just inaccurate. It's a real blind shot :/
The goal is to loop through all the media files, and then post the_content() of all files with the corresponding Uploaded By name.
I would be grateful if someone could comment as to why an ID is more reliable than a slug in the 'author' argument.
I figured out a solution. Apparently the 'author' argument does not like usernames, so I converted it to ID and it works now. I used get_user_by( 'slug', $username ); to get all the information of the particular username, and then assigned that array to a variable. I then filtered the variable to only use the ID and passed that through the arguments.
Here's the working loop:
<?php
// The Query
$profileid = get_user_by( 'slug', $username );
$args = array(
'author' => $profileid->id, // Replace with author id
'post_status' => 'inheret',
'post_type' => 'attachment'
);
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
echo '<ul>';
while ( $the_query->have_posts() ) {
$the_query->the_post();
echo '<li>' . the_content() . '</li>';
}
echo '</ul>';
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
?>

Wordpress Custom fields display file URL

I have the following code and need to show THREE things from my custom post type called fact-sheet.
The Title
The summary (fact_sheet_summary)
A file upload URL (fact_sheet_pdf_link)
I can get the first two to work but no idea how to do the third.
Basically my output should be...
The Title
The Summary paragraph
Click here to download as PDF
Any ideas how I can query to list all of these post type results? Is there a better way to do this rather than what I have below? The main problem is, I can't get the URL of the uploaded file.
<?php
$posts = get_posts(array(
'numberposts' => -1,
'post_type' => 'fact-sheet',
'order' => 'ASC',
));
if($posts)
{
foreach($posts as $post)
{
echo '<span class="fact-sheet-title">' . get_the_title($post->ID) . '</span><br />';
echo '<p><span class="fact-sheet-summary">' . the_field('fact_sheet_summary') . '</span></p>';
}
}
?>
I think It's better to use query_posts() as you can use The Loop default structure.
As for the custom fields (Using ACF Plugin), you're using the_field(), which automatically echoes the retrieved field value. You can use, in other hand, the get_field() function, which just returns the value of the field.
You could do something like this:
// Query all posts from 'fact-sheet' post_type
query_posts(array(
'numberposts' => -1,
'post_type' => 'fact-sheet',
'order' => 'ASC',
// Getting all posts, limitless
'posts_per_page' => -1,
));
// Loop throught them
while(have_posts()){
the_post();
echo '<span class="fact-sheet-title">' . get_the_title() . '</span><br />';
echo '<p><span class="fact-sheet-summary">' . get_field('fact_sheet_summary') . '</span></p>';
// Echos the link to PDF Download
echo '<p>Click here to download as PDF</p>';
}
// Once you're done, you reset the Default WP Query
wp_reset_query();
In case you might need further explanation about wp_reset_query(), check this out.
Can you try this? It's slightly modified from the manual of the WP Codex (not much)
<ul>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post();
$args = array(
'post_type' => 'attachment',
'post_mime_type' => array('application/pdf'),
'numberposts' => -1,
'post_status' => null,
'post_parent' => $post->ID
);
$attachments = get_posts( $args );
if ( $attachments ) {
foreach ( $attachments as $attachment ) {
echo '<li>';
the_attachment_link( $attachment->ID, true );
echo '<p>';
echo apply_filters( 'the_title', $attachment->post_title );
echo '</p></li>';
}
}
endwhile; endif; ?>
</ul>
If it works, maybe it's better to modify a working sample to your needs - by adding your custom fields. Just my thoughts :-)

Categories