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 Commented 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

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