Display each taxonomy term post under a Year and Month heading - php

I have a CPT - 'newsletters' and Taxonomy 'newsletter-groups'
I'm trying to display each post under it's respective term heading with all that terms posts displayed under it showing the Month and Year they were posted (by Postdate).
I thought I had something working , but noticed during testing that if a post had the same 'Month' it would wipe out the year and month for other posts in the same term and also for the terms below it , I have some images to show what I mean and the code I'm using so far.
In the images shown I've appended the post date to the filename for clarity , it would normally be just the filename.
Not Working if post date month is the same
Working if post date month is different
How can I solve this ? do I need to get all the post dates with a separate query and save that ?
Any examples appreciated
/*
* Custom Template: Archive Newsletters
*/
// Remove stuff
remove_action( 'genesis_loop', 'genesis_do_loop' );
// Add our custom loop
add_action( 'genesis_loop', 'newsletter_archive_loop' );
function newsletter_archive_loop() {
//fetch the terms for the newsletter-groups taxonomy
$terms = get_terms( 'newsletter-groups', array (
'hide_empty' => 'true',
'exclude' => 67, //excluding parent term ID 'school-newsletters' - only want to show term children of 'school-newsletters'
));
// run a query for each term
foreach( $terms as $term ) {
// Define the query
$args = array(
'post_type' => 'newsletters',
'newsletter-groups' => $term->slug ,
'posts_per_page' => -1,
);
// run the query
$query = new WP_Query( $args );
if( $query->have_posts() ) {
echo '<div class="letters">';
// output the term name in a heading tag
echo'<h4 class="term-heading">' . $term->name . '</h4>';
while ( $query->have_posts() ) { $query->the_post();
// get current month
$current_month = get_the_date('F');
// get attachements from custom field
$attachment_id = get_field('newsletter_upload');
$url = wp_get_attachment_url( $attachment_id );
$title = get_the_title( $attachment_id );
// get the filesize
$filesize = filesize( get_attached_file( $attachment_id ) );
$filesize = size_format($filesize, 2);
if( $query->current_post === 0 ) {
echo '<h4 class="date">';
the_date( 'F Y' );
echo '</h4>';
} else {
$f = $query->current_post - 1;
$old_date = mysql2date( 'F', $query->posts[$f]->post_date );
if($current_month != $old_date) {
echo '<h4 class="date">';
the_date( 'F Y' );;
echo '</h4>';
}
} ?>
<li class="letters-file">
<?php the_title(); ?><span class="letters-file-sz"> (<?php echo $filesize; ?>)</span>
</li>
<?php } // endwhile have posts
echo '</div>'; // close letters div
// use reset postdata to restore orginal query
wp_reset_postdata();
} // end if query have posts
} // end for each
} // end function
genesis(); // call genesis framework
Remove if and else both conditions and try to print only echo ''; the_date( 'F Y' ); echo ''
it will only show the individual post dates - But not grouped
EXPECTED OUTPUT

You can push each month in an array and check if the month is already in the array then do not display repeat month.
/*
* Custom Template: Archive Newsletters
*/
// Remove stuff
remove_action( 'genesis_loop', 'genesis_do_loop' );
// Add our custom loop
add_action( 'genesis_loop', 'newsletter_archive_loop' );
function newsletter_archive_loop() {
//fetch the terms for the newsletter-groups taxonomy
$terms = get_terms( 'newsletter-groups', array (
'hide_empty' => 'true',
'exclude' => 67, //excluding parent term ID 'school-newsletters' - only want to show term children of 'school-newsletters'
));
// run a query for each term
foreach( $terms as $term ) {
$dates = array();
// Define the query
$args = array(
'post_type' => 'newsletters',
'newsletter-groups' => $term->slug ,
'posts_per_page' => -1,
);
// run the query
$query = new WP_Query( $args );
if( $query->have_posts() ) {
echo '<div class="letters">';
// output the term name in a heading tag
echo'<h4 class="term-heading">' . $term->name . '</h4>';
while ( $query->have_posts() ) { $query->the_post();
// get current month
$current_month = get_the_date('F');
// get attachements from custom field
$attachment_id = get_field('newsletter_upload');
$url = wp_get_attachment_url( $attachment_id );
$title = get_the_title( $attachment_id );
// get the filesize
$filesize = filesize( get_attached_file( $attachment_id ) );
$filesize = size_format($filesize, 2);
if( !in_array(get_the_date( 'F Y' ), $dates ) ){
$dates[] = get_the_date( 'F Y' );
echo '<h4 class="date">';
echo get_the_date( 'F Y' );
echo '</h4>';
}
?>
<li class="letters-file">
<?php the_title(); ?><span class="letters-file-sz"> (<?php echo $filesize; ?>)</span>
</li>
<?php } // endwhile have posts
echo '</div>'; // close letters div
// use reset postdata to restore orginal query
wp_reset_postdata();
} // end if query have posts
} // end for each
} // end function
genesis(); // call genesis framework

Related

WooCommerce display product thumbnail and add to cart button

I have created a live search field that fetches the title of the product using AJAX.
It works correctly, however, I would like to fetch the product thumbnail and the ‘Add to the cart’ button.
**Edit: I have added the output for the thumbnail and add to cart button. It works, but it only displays in singular rows. How can I update my output in rows of 4 as below?
Front End Code
<input type="text" name="keyword" id="keyword" onkeyup="fetch()">
<div id="datafetch">Your numbers will show here</div>
<script>
function fetch(){
$.post('<?php echo admin_url('admin-ajax.php'); ?>',{'action':'my_action'},
function(response){
$('#datafetch').append(response);
console.log(result);
});
}
</script>
Code in Functions.php
<?php
}// LOTTERY start the ajax function
add_action('wp_ajax_data_fetch' , 'data_fetch');
add_action('wp_ajax_nopriv_data_fetch','data_fetch');
function data_fetch(){
$the_query = new WP_Query( array( 'posts_per_page' => -1, 's' => esc_attr( $_POST['keyword'] ), 'post_type' => 'product' ) );
if( $the_query->have_posts() ) :
while( $the_query->have_posts() ): $the_query->the_post();
global $product;
$product = get_product( get_the_ID() ); //set the global product object
$myquery = esc_attr( $_POST['keyword'] );
$a = $myquery;
$search = get_the_title();
if( stripos("/{$search}/", $a) !== false) {?>
<h4><?php the_title();?></h4>
<h4><?php the_post_thumbnail();?></h4>
<p><?php echo $product->get_price_html(); ?></p>
<?php woocommerce_template_loop_add_to_cart(); //ouptput the woocommerce loop add to cart button ?>
<?php
}
endwhile;
wp_reset_postdata();
endif;
die();
}
You can use this get_the_post_thumbnail_url(get_the_ID()) to get thumbnail URL and add image.
You can use this https://yourdomain.com/?add-to-cart=<product_id> to add product add to cart URL.
https://developer.wordpress.org/reference/functions/get_the_post_thumbnail_url/
Try this approach
//Ajax
add_action('wp_ajax_data_fetch' , 'data_fetch');
add_action('wp_ajax_nopriv_data_fetch','data_fetch');
function data_fetch(){
$the_query = new WP_Query( array( 'posts_per_page' => -1, 's' => esc_attr( $_POST['keyword'] ), 'post_type' => 'product' ) );
if( $the_query->have_posts() ) :
while( $the_query->have_posts() ): $the_query->the_post();
$myquery = esc_attr( $_POST['keyword'] );
$a = $myquery;
$search = get_the_title();
if( stripos("/{$search}/", $a) !== false) {
//get image and add-to-cart buttom here
$query->the_post();
global $product;
wc_get_template_part('content', 'product');
//End get image and add-to-cart buttom here
}
endwhile;
wp_reset_postdata();
endif;
die();
}

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!

WordPress display loop in 2 columns

I know this question has been asked before. I checked through multiple answers on this site,
for example:
Wordpress loop with different bootstrap columns
https://wordpress.stackexchange.com/questions/222278/how-to-separate-posts-loop-in-to-two-columns/222281
... but I cannot work out how to integrate answers with my code (assuming that is possible).
I want to display a list of Categories and their related posts on a page.
The code I'm using works fine BUT displays the results in a single column down the page:
I want to split the display into 2 columns, like in the image below, if possible:
The code I'm using (currently placed in a new page template) is as follows:
<?php
/*
* Template Name: Alphabetical List
*/
get_header();
// Grab all the categories from the database that have posts.
$categories = get_terms( 'category', 'orderby=name&order=ASC');
// Loop through categories
foreach ( $categories as $category ) {
// Display category name
echo '<h2 class="post-title">' . $category->name . '</h2>';
echo '<div class="post-list">';
// WP_Query arguments
$args = array(
'cat' => $category->term_id,
'order' => 'ASC',
'orderby' => 'title',
);
// The Query
$query = new WP_Query( $args );
// The Loop
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
?>
<p><?php the_title(); ?></p>
<?php
} // End while
} // End if
echo '</div>';
// Restore original Post Data
wp_reset_postdata();
} // End foreach
get_footer();
?>
Wondering if anyone can help me to get this code to display loop results in 2 columns.
Many thanks.
UPDATE TO QUESTION
Karl, thanks for your answer. Your script works, but with a small problem:
The Categories/Related Posts display in 2 columns but a 'gap/space' appears in the middle of the display of data (see image below):
I added to your code slightly so I could display a custom field I inserted into each post. I'm not sure if this has caused the problem.
Altered code (changes are immediately after $query->the_post();):
<?php
/*
* Template Name: Alphabetical List
*/
get_header();
?>
<div style="height:100px"></div>
<?php
// Grab all the categories from the database that have posts.
$categories = get_terms( 'category', 'orderby=name&order=ASC');
// Loop through categories
echo "<div class='new-column'>";
$counter = 0;
foreach ( $categories as $category ) {
if($counter % 4 == 0 && $counter !=0){
echo "<div class='new-column'>";
}
// Display category name
echo '<h2 class="post-title">' . $category->name . '</h2>';
echo '<div class="post-list">';
// WP_Query arguments
$args = array(
'cat' => $category->term_id,
'order' => 'ASC',
'orderby' => 'title',
);
// The Query
$query = new WP_Query( $args );
// The Loop
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
$customfieldvalue = get_post_meta($post->ID, "PDF", true);
?>
<p><a href="<?php echo $customfieldvalue; ?>" target="_blank"><?php
the_title(); ?></a></p>
<?php
} // End while
} // End if
echo '</div>';
// Restore original Post Data
wp_reset_postdata();
$counter++;
if($counter % 4 == 0){
echo "</div>";
}
} // End foreach
if($counter % 4 != 0){
echo "</div>";
}
get_footer();
?>
I've used bootstrap classes (row, col-6). Checked the size of categories array and used 2 variables - one as a counter and the other one to check if the column is first or second.
<?php
/*
* Template Name: Alphabetical List
*/
get_header();
// Grab all the categories from the database that have posts.
$categories = get_terms( 'category', 'orderby=name&order=ASC');
//get size of category
$catSize = sizeof($categories);
$j = 1;
$n = 1;
// Loop through categories
foreach ( $categories as $category ) {
if($n == 1){
echo '<div class="row">';
}
echo'<div class="col-6">';
// Display category name
echo '<h2 class="post-title">' . $category->name . '</h2>';
echo '<div class="post-list">';
// WP_Query arguments
$args = array(
'cat' => $category->term_id,
'order' => 'ASC',
'orderby' => 'title',
);
// The Query
$query = new WP_Query( $args );
// The Loop
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
?>
<p><?php the_title(); ?></p>
<?php
} // End while
} // End if
echo '</div></div>';
if($n == 1){
if($j == $catSize){
echo '<div class="col-6"></div>
</div>';
}
else{
$n = 2;
}
}
else{
echo '</div>';
$n =1;
}
$j++;
}
// Restore original Post Data
wp_reset_postdata();
} // End foreach
get_footer();
?>
Try this, I used a modulos operator "%" to group loops into 4, it will create new column every 4 loops. MAKE SURE YOU ADD CSS TO class new-column to arrange it like columns.
<?php
/*
* Template Name: Alphabetical List
*/
get_header();
// Grab all the categories from the database that have posts.
$categories = get_terms( 'category', 'orderby=name&order=ASC');
// Loop through categories
echo "<div class='new-column'">;
$counter = 0;
foreach ( $categories as $category ) {
if($counter % 4 == 0 && $counter !=0){
echo "<div class='new-column'">;
}
// Display category name
echo '<h2 class="post-title">' . $category->name . '</h2>';
echo '<div class="post-list">';
// WP_Query arguments
$args = array(
'cat' => $category->term_id,
'order' => 'ASC',
'orderby' => 'title',
);
// The Query
$query = new WP_Query( $args );
// The Loop
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
?>
<p><?php the_title(); ?></p>
<?php
} // End while
} // End if
echo '</div>';
// Restore original Post Data
wp_reset_postdata();
$counter++;
if($counter % 4 == 0){
echo "</div>";
}
} // End foreach
if($counter % 4 != 0){
echo "</div>";`enter code here`
}
get_footer();
?>

Advanced Custom Fields Wordpress Repeater Field Order By Date

I am using advanced custom fields pro to store and display information on estate sale dates. These are held in a repeater field, each row in the field has a start time, end time and a date. I need to display the information ordered by the date in the repeater field row. Currently it is ordered by date modified. I have tried several solutions but none seem to work for what I need to do.
This is what I have currently:
<?php
$latestes = new WP_Query(
array(
'post_type' => 'estate-sales',
'post_status' => 'publish',
'posts_per_page' => 10,
'orderby' => 'modified',
'order' => 'DESC'
)
);
while ( $latestes->have_posts() ) : $latestes->the_post();
echo '<li class="frontpage-esale"><a href="';
the_permalink();
echo '">';
the_title();
echo ' ';
$rowses = get_field('estate_sale_dates');
$first_row = $rowses[0];
$first_row_date = $first_row['es-date'];
$first_row_start = $first_row['es-start-time'];
$first_row_end = $first_row['es-end-time'];
echo ' - ';
if ($first_row_date) {
echo date('F j, Y',strtotime($first_row_date));
}
else {
echo 'Sale Dates TBA';
}
endwhile;
wp_reset_query();
?>
The most common answer when searching for a solution is to do something like this:
$latestes = new WP_Query(
array(
'post_type' => 'estate-sales',
'post_status' => 'publish',
'posts_per_page' => 10,
'orderby' => 'modified',
'order' => 'DESC'
)
);
while ( $latestes->have_posts() ) : $latestes->the_post();
$repeater = get_field('estate_sale_dates');
foreach( $repeater as $key => $row )
{
$column_id[ $key ] = $row['es-date'];
}
array_multisort( $column_id, SORT_ASC, $repeater );
foreach( $repeater as $row ) {
echo '<li class="frontpage-esale"><a href="';
the_permalink();
echo '">';
the_title();
echo ' ';
$rowses = get_field('estate_sale_dates');
$first_row = $rowses[0];
$first_row_date = $first_row['es-date'];
$first_row_start = $first_row['es-start-time'];
$first_row_end = $first_row['es-end-time'];
echo ' - ';
if ($first_row_date) {
echo date('F j, Y',strtotime($first_row_date));
}
else {
echo 'Sale Dates TBA';
}
}
endwhile;
wp_reset_query();
?>
However, when I try that, it lists each sale 3 times, does not order by the date at all, and if no date is entered (which needs to just default to Sale Dates TBA) it throws an error.
Any help greatly appreciated.
Note, that your integration isn't complete, signaled by having two get_field('estate_sale_dates');, and the name $first_row being out of place when iterating all of them. Without the sort, you're basically doing
$repeater = get_field( 'estate_sale_dates' );
...
foreach ( $repeater => $row_that_isnt_used )
{
$rowses = get_field( 'estate_sale_dates' );
$first_row = $rowses[0];
}
I think something like this is what you're after:
<?php
while ( $latestes->have_posts() ) {
$latestes->the_post();
echo '<li class="frontpage-esale"><a href="';
the_permalink();
echo '">';
the_title();
echo '</a> ';
if ( ! count( $sale_dates = get_field('estate_sale_dates') ) )
echo '<span>Sale Dates TBA</span>';
else
{
// $order = array_column( $sale_dates, 'es-date' ): (php 5.5+)
foreach( $sale_dates as $ignore => $row )
$order[] = $row['es-date'];
array_multisort( $order, SORT_ASC, $sale_dates );
echo "<ul>";
foreach( $sale_dates as $row ) {
$date = $row['es-date'];
$start = $row['es-start-time'];
$end = $row['es-end-time'];
echo "<li>" . date('F j, Y',strtotime($row_date)) . " $start-$end</li>";
}
echo "</ul>";
}
echo "</li>";
}
I have the same problem with a calendar. There is no solution to do this in the right way with a repater field. The best way to do this, is to use an custom field in an hidden post type and a relation field.
Because any PHP solution is inperformant.
Make a Custom Post Type "Sales Dates" an in this a custom field "date" and a second "Post Relation".
Then select from Post Type "Sales Dates" all Posts order by meta key "dates" with the relation field you get the data from the not hidden post type.

Woocommerce alphabetic list of products

I would like to have an alphabet listing the products by ABC... list
Something like
A | B | C | D .... Z
And that all link to the products-list sorted by their first letter.
I would like it placed above the list where the sorting dropdown menu is (top of the woocommerce ).
Is it possible somehow with coding, or is there some plug-in for it?
I put this at the end of orderby.php:
<div id="alphabet">
<?php
$args = array(
'post_type' => 'product',
'posts_per_page' => -1
);
$query = new WP_Query($args);
$by_letter = array();
while( $query->have_posts() ) { $query->the_post();
global $post;
$letter = substr($post->post_name, 0, 1);
if ( ! isset($by_letter[$letter]) ) $by_letter[$letter] = array();
$by_letter[$letter][] = $post;
}
wp_reset_postdata();
?>
<?php
if ( ! empty( $by_letter ) ) {
ksort($by_letter); // order the array
// fill the array with letters have no posts
$by_letter = fill_by_letter_array( $by_letter );
display_letters_anchors( array_keys( $by_letter ) );
foreach( $by_letter as $letter => $posts ) {
?>
<div id="Productlist_<?php echo strtoupper($letter); ?>" class="Productlist_<?php echo strtoupper($letter); ?>_object productlists">
<?php
if ( ! empty($posts) ) {
foreach ( $posts as $post ) {
setup_postdata($post);
// just an example of post output
echo '<p>' . get_the_title() . '</p>';
}
} else {
echo '<p>' . __('No products.') . '</p>';
}
?>
</div>
<?php
}
wp_reset_postdata();
}
?>
</div>
A bit of css, and it Works great!

Categories