1

I need to create a 9 column list that outputs posts sorted vertical and alphabetically. I'm getting closer, but still not there. I have two separate loops I'm working with.

The first loop I have the way I want it, sorted by letter, and alphabetically in tables. Problem here is that I just cant get the styling correct.

The second one I've used wp_query_columns function from here. With this I get a loop that are correctly sorted, and with a float:left I have it aligned properly. What's missing here is that I need to set a pre-determed set of numbers per row, where I need it to be dynamically, and also I need it to be sorted after letter like the first example.

I tried numerous ways to do this over the past few days, and I'm confused. Both of them seems to be on the right track, not sure which one I should pursue working with. You can see both outputs here (Scroll down for the second one)

Loop 1

<?php

$last_char = '';
$args=array(
'post_type' => 'portfolio',
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page'=>-1,
'portfolio-category' => 'indie',
'ignore_sticky_posts'=>1
);

$my_query = new WP_Query($args);

$columnCount = 0;

?>

<?php if( $my_query->have_posts() ) : ?>
<?php  echo 'Alphabetic index of all ' . count($my_query->posts) . ' posts'; ?>

<table>
               <?php while ($my_query->have_posts()) : ?>
            <?php if ($columnCount == 8): ?>


            <?php endif; ?>


            <?php $my_query->the_post(); ?>
            <?php $this_char = strtoupper(substr($post->post_title,0,1));  

           if ($this_char != $last_char) : ?>
 </table></td><td>
 <?php   $last_char = $this_char; ?>
 <h2> <?= $last_char; ?></h2>
 <table>
 <?php else: ?>
     <tr><td><p><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to    <?php the_title_attribute(); ?>"><?php the_title(); ?></a></p></td></tr>

 <?php endif; ?>
                      <?php endwhile; ?>  
        <?php if ($columnCount != 8): ?>
            </tr><!-- Make sure the last row gets closed. -->

        <?php endif; ?>
</table>
<?php endif; ?>

<?php wp_reset_query();  // Restore global post data stomped by the_post(). ?>

Loop 2

<?php

 $args=array(
'post_type' => 'portfolio',
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page'=>-1,
'portfolio-category' => 'indie',
'gnore_sticky_posts'=>1
);



$the_query = new WP_Query($args);
foreach(new WP_Query_Columns($the_query, 15) as $column_count) : ?>

<ul>
    <?php while ($column_count--) : $the_query->the_post(); ?>
    <li><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></li>
    <?php endwhile; ?>
 </ul>
<?php endforeach; ?>
1
  • Where you ever able to solve this problem? haven't heard anything back from you regarding my solution or your answer Sep 17, 2014 at 15:28

1 Answer 1

2

EDIT

From the comments from the OP

There's a few concerns though and suggestions on improvement. First of all, not sure if i missed something, but the list are not links? Second is that with this list it outputs a letter even though it doesn't have a post assigned to the letter.....

and

Posts that starts with an number won't be listed, would it be possible to extend the range for this?

I have totally rewritten the entire code. Still, both blocks of codes in your question had major issues, so again, I've dropped both. As well as @birgire indicated, the code in my original answer had the drawback of the amount of db queries due the fact that I was including empty letters as well (thought this is what you wanted)

I have made the links clickable, as well as made provision to include numbers as the first character to sort by. What I did not go into detail in is styling.

So here are the revised code

<?php 
$args=array(
    'post_type' => 'portfolio',
    'portfolio-category' => 'indie',
    'orderby' => 'title',
    'order' => 'ASC',
    'posts_per_page'=>-1,
    'ignore_sticky_posts'=>1
);

$my_query = new WP_Query($args);
$q = array();
if( $my_query->have_posts() ) {
    while ($my_query->have_posts()) {
        $my_query->the_post(); 

            $t = '<a href="'. get_permalink() .'" rel="bookmark" title="Permanent Link to '. get_the_title() .'">' . get_the_title() .'</a>';
            $c = strtoupper(substr(get_the_title(),0,1)); 
            $q[$c][] = $t;
    }
} 
wp_reset_postdata();  // Restore global post data stomped by the_post(). 

$count = 0;

foreach ($q as $key=>$values) {
    $count++; ?>

    <div class="column<?php echo $count; ?>" style="width:9%; margin-right:2%; float:left; margin-bottom:25px">

        <?php echo $key;

        foreach ($values as $value) { ?>    
            <div style="width:95%; padding-right:5%">
                <p>
                    <?php echo $value; ?>
                </p>
            </div>
        <?php } ?>

    </div>

    <?php if( 0 == $count%9 ){ ?>

        <div class="clear" style="clear:left"></div>

    <?php } 
}

Here is the output from the code above

enter image description here

WHAT YOU NEED TO DO

  • Scrap everything from the original answer. I'm keeping the original answer for the sake of its completeness and that it might become useful to someone else in future.

  • Add your own styling and style according to your needs

  • Make any modification to suite your own personal needs

I have given you the backbone to accomplish your needs. I would expect that this would take to at least 99% in achieving your goal. Please let me know on your progress

ORIGINAL ANSWER

I've went a took a different route that what you took in your examples. Here is what I did and how it works:

STEP 1

@birgire did this post a while ago about extending the WP_Query class which enables you to retrieve a post by first letter. Is is done with the introduction of a new parameter, name__like. I've used this to create the custom query. Here is the new class

/**
 * Class WPSE_Query
 *
 * Add a support for the name__like parameter
 *
 * @link https://wordpress.stackexchange.com/a/136758/26350
 *
 */
class WPSE_Query extends WP_Query 
{       
    public function __construct( $args = array() )
    {
        add_filter( 'posts_where', array( $this, 'posts_where' ), 10, 2 );
        parent::__construct( $args );
    }
    public function posts_where( $where, $qry )
    {       
        remove_filter( current_filter(), array( $this, __FUNCTION__ ) );    
        $name__like = $qry->get( 'name__like' ); 
        if( ! empty( $name__like )  )
        {
            $where .= " AND ";
            $where .= $GLOBALS['wpdb']->posts;
            $where .= ".post_name LIKE '";
            $where .= esc_sql( like_escape( $name__like ) );
            $where .= "%' ";            
        }   
        return $where;
    }
}

This goes into your functions.php.

STEP 2

To dynamically retrieve a list of all letters of the alphabet, I've used the php function range() and assigned a variable to it.

$range = range('A','Z');

STEP 3

I've then passed my variable through a foreach loop to get all the individual letters, which is passed to my custom query

foreach ($range as $r){ }

STEP 4

Instead of using WP_Query, I've now used the new class that was created in STEP 1 called WPSE_Query. I also used the new parameter name__like and passed each letter of the alphabet to it to retrieve my posts accordingly

$args = array(
            'post_type'             => 'portfolio',
            'orderby'               => 'title',
            'order'                 => 'ASC',
            'posts_per_page'        => -1,
            'portfolio-category'    => 'indie',
            'ignore_sticky_posts'   => 1,
            'name__like'            => $r
        );

        // The Query
        $the_query = new WPSE_Query( $args ); 

The reason why I went through all this trouble is to give me more control over the HTML

STEP 5

I've introduced a counter to control when HTML elements are introduced and how they are advanced

STEP 6

To create and style the columns, I have used the following line. Note: I've used inline styles here just to showcase the output. You should add these styles to your stylesheet rather than keeping them as inline styles

<div class="column<?php echo $count; ?>" style="width:9%; margin-right:2%; float:left; margin-bottom:25px">

As you can see, I have used the counter here to advance my column class by one on each iteration

STEP 7

Finally, to stop any wacky output, you need to clear the float after every ninth post. With the use of the counter and the modulus division operator, a clear float is inserted after every ninth post

if( 0 == $count%9 ){ ?>

        <div class="clear" style="clear:left"></div>

    <?php }

ALL TOGETHER NOW!

This is the final code:

<?php
$count = 0;
$range = range('A','Z');

foreach ($range as $r){
   $count++;

?>

    <div class="column<?php echo $count; ?>" style="width:9%; margin-right:2%; float:left; margin-bottom:25px">

<?php

        echo '<p>' .$r . '</p>';

        // $args for the custom query
        $args = array(
            'post_type'             => 'portfolio',
            'orderby'               => 'title',
            'order'                 => 'ASC',
            'posts_per_page'        => -1,
            'portfolio-category'    => 'indie',
            'ignore_sticky_posts'   => 1,
            'name__like'            => $r
        );

        // The Query
        $the_query = new WPSE_Query( $args );  

        // The Loop
        if ( $the_query->have_posts() ) {
            while ( $the_query->have_posts() ) {
                $the_query->the_post();

                    ?>

                        <div style="width:95%; padding-right:5%">
                            <p>
                                <?php the_title(); ?>
                            </p>
                        </div>

                    <?php

            }
        } 

        wp_reset_postdata(); ?>

    </div>

<?php

    if( 0 == $count%9 ){ ?>

        <div class="clear" style="clear:left"></div>

    <?php }
}

?>

All you need to do is to tweak and add all relevant HTML mark-up

Here is the output from the code above

enter image description here

and here is the HTML structure

enter image description here

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.