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
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
and here is the HTML structure