Support

Account

Home Forums General Issues Upload PDF Manuals on all product pages and display all the uploaded value

Solved

Upload PDF Manuals on all product pages and display all the uploaded value

  • Hi,

    We have 300 products and every products contains a user manual. I created a field called pdf_upload where I’ve uploaded a pdf file on each individual product. The file can then be previewed on every single page.

    Here is my code:

    
    <?php $pdf_upload = get_field('pdf_upload');
        if( $pdf_upload ): ?>
           <a href="<?php echo $pdf_upload['url']; ?>">Manuel PDF</a>
        <?php endif; ?>
    

    Now, I want to create a page and display an ordered list of all uploaded PDF by date uploaded. So far, looking at acf documentation I’ve only been able to get the result of a field on a single product page but not all the results uploaded.

    How can I display a list of all the PDF’s that has been uploaded?

  • This is correct. There isn’t any way to get all of the values for all of the posts using any function in ACF or WP. To do what you want to do you would have to query the _postmeta table in the DB directly.

    https://developer.wordpress.org/reference/classes/wpdb/

    edit: in addition to this, this field in the DB only contains the ID value of the media file (upload) and you would need to get the link to this file yourself. https://developer.wordpress.org/reference/functions/wp_get_attachment_url/

  • HI @bigrat95

    Could you not just add a loop to your page template, loop through all pages/posts and output the ACF field?

    
    <?php
    $args = array(
    	'posts_per_page'	=> -1,
    	'post_type'			=> 'post',
     	'orderby' 			=> 'date',
        'order'   			=> 'DESC',	
    	'paged'				=> $paged,
    	'fields'			=> 'ids'			
    );
    $wp_query = new WP_Query($args);
    if ($wp_query->have_posts()) :
    	while ($wp_query->have_posts()) : $wp_query->the_post();
    
    	$pdf_upload = get_field('pdf_upload');
    	if( $pdf_upload ): ?>
           <a href="<?php echo $pdf_upload['url']; ?>">Manuel PDF</a>
        <?php endif; 
    
    	endwhile;
    endif;
    
  • @jarvis yes, this could be done. The only issue with it is that with 300 products it will be very slow. But it is a solution.

  • A possible alternative would be to use AJAX and create a load more function as the user scrolls down.

    Would be more work but would ease the page load!

    A good tutorial can be seen here.

  • @bigrat95

    You may need to change the post_type and you will also need to amend the ACF field to the name of the one you set up.

  • @jarvis It work well, here is the modified code below…

    <?php
    $args = array(
      'posts_per_page'  => -1,
      'post_type'     => 'product',
      'orderby'       => 'date',
      'order'         => 'DESC',  
      'paged'       => $paged,
      'fields'      => 'ids'      
    );
    $wp_query = new WP_Query($args);
    if ($wp_query->have_posts()) :
      while ($wp_query->have_posts()) : $wp_query->the_post();
    
      $pdf_upload = get_field('pdf_upload');
      if( $pdf_upload ): ?>
           <li> <a href="<?php echo $pdf_upload['url']; ?>"><? echo $product->post->post_title; ?></a></li>
           <?php echo '<span class="date_published">Published on: ' . get_the_date('Y', $product->get_id()) . '</span>'; ?>
    
        <?php endif; 
    
      endwhile;
    endif;
    
    ?>


    @hube2
    The page is indeed pretty slow, I will work on the Ajax now, I will keep this thread updated with the code.

    Thanks

  • Something like the below:

    <div id="ajax-posts">
    <?php
    $postsPerPage = 10;	
    $args = array(
      'posts_per_page' 	=> $postsPerPage,
      'post_type'		=> 'product',
      'orderby'			=> 'date',
      'order'			=> 'DESC',  
      'paged'			=> $paged,
      'fields'			=> 'ids'      
    );
    $wp_query = new WP_Query($args);
    if ($wp_query->have_posts()) :
    	while ($wp_query->have_posts()) : $wp_query->the_post();
    
    		$pdf_upload = get_field('pdf_upload');
    		if( $pdf_upload ): ?>
    			<li> <a href="<?php echo $pdf_upload['url']; ?>"><? echo $product->post->post_title; ?></a></li>
    			<?php echo '<span class="date_published">Published on: ' . get_the_date('Y', $product->get_id()) . '</span>'; ?>
    		<?php endif; 
    
    	endwhile;
    endif; ?>
    </div><!-- /ajax-posts -->
    <div id="more_posts">Load More</div>

    In your functions file:

    <?php
    wp_localize_script( 'twentytwentyone-script', 'ajax_posts', array(
        'ajaxurl' => admin_url( 'admin-ajax.php' ),
        'noposts' => __('No older posts found', 'twentytwentyone'),
    ));
    
    function more_post_ajax(){
    
        $ppp = (isset($_POST["ppp"])) ? $_POST["ppp"] : 10;
        $page = (isset($_POST['pageNumber'])) ? $_POST['pageNumber'] : 0;
    
        $args = array(
            'post_type'			=> 'product',
            'posts_per_page'	=> $ppp,
            'paged'				=> $page,
        );
    
    	$wp_query = new WP_Query($args);
    	if ($wp_query->have_posts()) :
    		$out = '';
    		while ($wp_query->have_posts()) : $wp_query->the_post();
    
    			$pdf_upload = get_field('pdf_upload');
    			if( $pdf_upload ): 
    				$out .= '<li><a href="'.$pdf_upload['url'].'">'.$product->post->post_title.'</a></li>';
    				$out .= '<span class="date_published">Published on: ' . get_the_date('Y', $product->get_id()) . '</span>';
    			endif; 
    
    		endwhile;
    	endif;
    	
        wp_reset_postdata();
        die($out);
    }
    
    add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
    add_action('wp_ajax_more_post_ajax', 'more_post_ajax');
    ?>

    Ajax call (perhaps in the footer for testing):

    <script>
    var ppp = 10; // Post per page
    var pageNumber = 1;
    
    function load_posts(){
        pageNumber++;
        var str = '&pageNumber=' + pageNumber + '&ppp=' + ppp + '&action=more_post_ajax';
        $.ajax({
            type: "product",
            dataType: "html",
            url: ajax_posts.ajaxurl,
            data: str,
            success: function(data){
                var $data = $(data);
                if($data.length){
                    $("#ajax-posts").append($data);
                    $("#more_posts").attr("disabled",false);
                } else{
                    $("#more_posts").attr("disabled",true);
                }
            },
            error : function(jqXHR, textStatus, errorThrown) {
                $loader.html(jqXHR + " :: " + textStatus + " :: " + errorThrown);
            }
    
        });
        return false;
    }
    	
    $("#more_posts").on("click",function(){ // When btn is pressed.
        $("#more_posts").attr("disabled",true); // Disable the button, temp.
        load_posts();
    });
    	
    // Or for 'infinite load' instead on click event on the button (just make it invisible, with visibility: hidden;) 
    
    $(window).on('scroll', function(){
    	if($('body').scrollTop()+$(window).height() > $('footer').offset().top){
    		if(!($loader.hasClass('post_loading_loader') || $loader.hasClass('post_no_more_posts'))){
    			load_posts();
            }
    	}
    });
    </script>

    Was based on this stack overflow post may help as a reference point

  • @jarvis I had to replace $ with jQuery, to solve this error: ‘Uncaught TypeError: $ is not a function ‘

    Now, I am getting this error: Uncaught ReferenceError: ajax_posts is not defined

    It makes me think that I haven’t proprely enqued the script maybe?

    Also do I need to keep the theme twentytwentyone installed ?

  • Ok, got this working.

    In your template:

    <?php
    $args = array(
      'posts_per_page' 	=> 3, #must match the value in settings > reading > Blog pages show at most
      'post_type'		=> 'product',
      'orderby'			=> 'date',
      'order'			=> 'DESC',  
      'paged'			=> $paged,
      'fields'			=> 'ids'      
    );
    $wp_query = new WP_Query($args);
    if ($wp_query->have_posts()) :
    	while ($wp_query->have_posts()) : $wp_query->the_post();
    the_title();
    $pdf_upload = get_field('pdf_upload');
    		if( $pdf_upload ): ?>
    			<li> <a href="<?php echo $pdf_upload['url']; ?>"><?php the_title; ?></a></li>
    		<?php endif; 
    
    	endwhile;
    endif; wp_reset_query(); ?>
    
    <?php
    #global $wp_query; // you can remove this line if everything works for you
     
    // don't display the button if there are not enough posts
    if (  $wp_query->max_num_pages > 1 )
    	echo '<div class="misha_loadmore">More posts</div>'; // you can use <a> as well
    ?>

    Create a javascript file called myloadmore.js and add the following:

    jQuery(function($){ // use jQuery code inside this to avoid "$ is not defined" error
    	$('.misha_loadmore').click(function(){
     
    		var button = $(this),
    		    data = {
    			'action': 'loadmore',
    			'query': misha_loadmore_params.posts, // that's how we get params from wp_localize_script() function
    			'page' : misha_loadmore_params.current_page
    		};
     
    		$.ajax({ // you can also use $.post here
    			url : misha_loadmore_params.ajaxurl, // AJAX handler
    			data : data,
    			type : 'POST',
    			beforeSend : function ( xhr ) {
    				button.text('Loading...'); // change the button text, you can also add a preloader image
    			},
    			success : function( data ){
    				if( data ) { 
    					button.text( 'More posts' ).prev().before(data); // insert new posts
    					misha_loadmore_params.current_page++;
     
    					if ( misha_loadmore_params.current_page == misha_loadmore_params.max_page ) 
    						button.remove(); // if last page, remove the button
     
    					// you can also fire the "post-load" event here if you use a plugin that requires it
    					// $( document.body ).trigger( 'post-load' );
    				} else {
    					button.remove(); // if no data, remove the button as well
    				}
    			}
    		});
    	});
    });

    In your functions file, add the following:

    function misha_my_load_more_scripts() {
     
    	global $wp_query; 
     
    	// In most cases it is already included on the page and this line can be removed
    	wp_enqueue_script('jquery');
     
    	// register our main script but do not enqueue it yet
    	wp_register_script( 'my_loadmore', get_stylesheet_directory_uri() . '/js/myloadmore.js', array('jquery') );
     
    	// now the most interesting part
    	// we have to pass parameters to myloadmore.js script but we can get the parameters values only in PHP
    	// you can define variables directly in your HTML but I decided that the most proper way is wp_localize_script()
    	wp_localize_script( 'my_loadmore', 'misha_loadmore_params', array(
    		'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX
    		'posts' => json_encode( $wp_query->query_vars ), // everything about your loop is here
    		'current_page' => get_query_var( 'paged' ) ? get_query_var('paged') : 1,
    		'max_page' => $wp_query->max_num_pages
    	) );
     
     	wp_enqueue_script( 'my_loadmore' );
    }
     
    add_action( 'wp_enqueue_scripts', 'misha_my_load_more_scripts' );

    Also in your functions file, add the following:

    
    function misha_loadmore_ajax_handler(){
     
    	// prepare our arguments for the query
    	$args = json_decode( stripslashes( $_POST['query'] ), true );
    	$args['paged'] = $_POST['page'] + 1; // we need next page to be loaded
    	$args['post_status'] = 'publish';
     
    	// it is always better to use WP_Query but not here
    	query_posts( $args );
     
    	if( have_posts() ) :
     
    		// run the loop
    		while( have_posts() ): the_post();
    	
    		$pdf_upload = get_field('pdf_upload');
    		if( $pdf_upload ): ?>
    			<li> <a href="<?php echo $pdf_upload['url']; ?>"><?php the_title(); ?></a></li>
    		<?php endif; 
    	
    		endwhile;
     
    	endif;
    	die; // here we exit the script and even no wp_reset_query() required!
    }
     
     
     
    add_action('wp_ajax_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_{action}
    add_action('wp_ajax_nopriv_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_nopriv_{action}

    Tried and tested!

  • It dosen’t seems to be working. It now show 3 links in <li>

    There is also a list of products name listed at the bottom of the page

    Just to let you know I did match the value in settings – reading- blog which is 12 for me 🙂

  • @hube2 @jarvis Forget about my last message. I was able to solve my issue without using ajax.

    Since I have around 1200 products on my site, I just added ‘meta_key’ => ‘pdf_upload’, in the array to filter. It reduced the loading time, now the page load fast!

    Thanks for your help

    Revised code:

    
    <section class="post-content">
                    <ul>
    
                    <?php
                    $args = array(
                      'posts_per_page' => -1,
                      'post_type' => 'product',
                      'orderby' => 'date',
                      'order' => 'DESC',
                      'paged' => $paged,
                      
                      'meta_key'    => 'pdf_upload',  
                    );
                    $wp_query = new WP_Query($args);
                    if ($wp_query->have_posts()) :
                      while ($wp_query->have_posts()) : $wp_query->the_post();
    
                        $pdf_upload = get_field('pdf_upload');
                        if( $pdf_upload ): ?>
                          <li><a href="<?php echo $pdf_upload['url']; ?>"><?php echo $product->post->post_title; ?> </a></li>
                          <?php echo '<span class="date_published">Published on: ' .get_the_date('Y', $product->get_id()) . '</span>'; ?>
    
                        <?php endif;
    
                      endwhile;
                    endif;
                    ?>
    
                    </ul>
                  </section>
Viewing 12 posts - 1 through 12 (of 12 total)

You must be logged in to reply to this topic.