categories - Alphabetical Index Page

admin2025-06-02  1

I can't quite seem to wrap my head around the logic needed to create an Alphabetical Index page. I can get a rudimentary version working but what I'm trying to do is create something like this /.

So far I have my code outputting the first letter of a set of taxonomy terms and then every time it finds a new letter it adds the letter to the index.

What I cannot figure out is A) How to equally divide the posts into columns (Bootstrap markup being wrapped in <div class="col-sm-2"> and B) If I can get that working then how to group 3 letters together at a time ie) A-C, D-F, etc.

Here is my code so far:

<?php
$args = array(
    'taxonomy' => 'brands',
    'hide_empty' => 0,
    'orderby' => 'name',
    'order' => 'ASC',
);
$category_list = get_categories($args);
$curr_letter = '';

foreach ( $category_list as $category ) {
    $this_letter = strtoupper(substr($category->name,0,1));

    if ($this_letter != $curr_letter) {
        echo !empty( $curr_letter ) ? '</div>' : null;
        echo '<div class="row">';
        echo '<h3 class="col-sm-2">' . $this_letter . '</h3>';
        $curr_letter = $this_letter;
    }
    echo '<div class="col-sm-2">' . $category->name . '</div>';
}
?>

I thought of trying to store every nth iteration of the loop into a new array for each of the columns and then emptying the arrays when it hits a new letter but I'm not entirely sure how to do that. Perhaps someone can point me in the right direction.

I can't quite seem to wrap my head around the logic needed to create an Alphabetical Index page. I can get a rudimentary version working but what I'm trying to do is create something like this https://www.carryology/brands/.

So far I have my code outputting the first letter of a set of taxonomy terms and then every time it finds a new letter it adds the letter to the index.

What I cannot figure out is A) How to equally divide the posts into columns (Bootstrap markup being wrapped in <div class="col-sm-2"> and B) If I can get that working then how to group 3 letters together at a time ie) A-C, D-F, etc.

Here is my code so far:

<?php
$args = array(
    'taxonomy' => 'brands',
    'hide_empty' => 0,
    'orderby' => 'name',
    'order' => 'ASC',
);
$category_list = get_categories($args);
$curr_letter = '';

foreach ( $category_list as $category ) {
    $this_letter = strtoupper(substr($category->name,0,1));

    if ($this_letter != $curr_letter) {
        echo !empty( $curr_letter ) ? '</div>' : null;
        echo '<div class="row">';
        echo '<h3 class="col-sm-2">' . $this_letter . '</h3>';
        $curr_letter = $this_letter;
    }
    echo '<div class="col-sm-2">' . $category->name . '</div>';
}
?>

I thought of trying to store every nth iteration of the loop into a new array for each of the columns and then emptying the arrays when it hits a new letter but I'm not entirely sure how to do that. Perhaps someone can point me in the right direction.

Share Improve this question asked Mar 5, 2019 at 3:38 tylorreimertylorreimer 651 silver badge8 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 5

You can do it like so:

// Group the categories by their FIRST LETTER.
$groups = [];
foreach ( $category_list as &$term ) {
    $letter = strtoupper( substr( $term->name, 0, 1 ) );
    if ( ! isset( $groups[ $letter ] ) ) {
        $groups[ $letter ] = [];
    }

    $groups[ $letter ][] = $term;
}

// Now display them, three groups in each row.
echo '<div class="row">';
$i = 0;
$letters = array_keys( $groups );
foreach ( $groups as $letter => $terms ) {
    $new_row = ( $i % 3 === 0 );
    if ( $i && $new_row ) {
        echo '</div><div class="row">';
    }

    // Show either "A - C", "A & B", or just a letter.
    if ( ! $i || $new_row ) {
        $range = array_slice( $letters, $i, 3 );
        if ( $end = $range[ count( $range ) - 1 ] ) {
            $sign = ( count( $range ) > 2 ) ? ' - ' : ' & ';
            $range = $letter . $sign . $end;
            echo '<h2 class="col-12">' . $range . '</h2>';
        } else {
            echo '<h2 class="col-12">' . $letter . '</h2>';
        }
    }

    echo '<div class="col-sm">';
    if ( ! empty( $terms ) ) {
        echo '<ul>';
        foreach ( $terms as $term ) {
            echo '<li>' . $term->name . '</li>';
        }
        echo '</ul>';
    }
    echo '</div>';

    $i++;
}
echo '</div>';

The output would look like so:


UPDATE

So this is the proper version, based on the layout on Carryology/brands/ (as of writing).

I have commented the code (although not all parts) and it shouldn't be hard for you to make modifications to the code:

// Group the categories by their FIRST LETTER.
$letters = range( 'A', 'Z' );
$groups = [];
foreach ( $category_list as &$term ) {
    $letter = strtoupper( substr( $term->name, 0, 1 ) );
    if ( ! isset( $groups[ $letter ] ) ) {
        $groups[ $letter ] = [];
    }

    $groups[ $letter ][] = $term;
}

$cols = 3; // number of letters in a range
for ( $i = 0; $i < count( $letters ); $i++ ) {
    if ( $i % $cols === 0 ) {
        $list = array_slice( $letters, $i, $cols );
        // Start the row.
        echo '<div class="row">';

        // Show the heading. (letter range)
        $end = $list[ count( $list ) - 1 ];
        $sign = ( count( $list ) > 2 ) ? ' - ' : ' & ';
        $range = $end ? $sign . $end : '';
        // Show either "A - C", "A & B", or just a letter.
        echo '<h3 class="col-sm-2">' . $list[0] . $range . '</h3>';

        // Put all the letter terms in a single group.
        $groups2 = [];
        for ( $j = 0; $j < count( $list ); $j++ ) {
            if ( isset( $groups[ $list[ $j ] ] ) ) {
                $groups2 = array_merge( $groups2, $groups[ $list[ $j ] ] );
            }
        }

        $cols2 = 5; // number of columns in a row, excluding the heading.
        $n = count( $groups2 );
        $rows = floor( $n / $cols2 );
        $diff = $n - $rows * $cols2;
        for ( $k = 0, $l = 0; $k < $cols2; $k++ ) {
            $x = $diff ? 1 : 0;
            // Start a column.
            echo '<ul class="col-xs-4 col-sm-2">';

            // Show the group terms.
            foreach ( array_slice( $groups2, $l, $rows + $x ) as $term ) {
                echo '<li>' . $term->name . '</li>';
                $l++;
            }

            $diff = $diff ? $diff - 1 : 0;
            // Column end.
            echo '</ul>';
        }

        // Row end.
        echo '</div>';
    }
}

The output would look like so:

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1748828825a314064.html

最新回复(0)