Artikel alphabetisch sortieren

Quell-ID: GitHub Discussion #22

Use Case

Im Frontend sollen Artikel einer Kategorie nicht nach der Backend-Priorität, sondern alphabetisch nach Namen sortiert werden.

Verwendete AddOns

  • REDAXO Core

Problemstellung

Die Standard-Methode getArticles() liefert Artikel nach der im Backend festgelegten Priorität:

$articles = rex_category::get("REX_CATEGORY_ID")->getArticles(true);

Lösung

Mit PHP’s usort() können die Artikel nach einem beliebigen Kriterium sortiert werden:

<?php
$articles = rex_category::get("REX_CATEGORY_ID")->getArticles(true);

usort($articles, function ($a, $b) {
    return strcmp($a->getValue('name'), $b->getValue('name'));
});

// Ausgabe
foreach ($articles as $article) {
    echo '<a href="' . $article->getUrl() . '">' . $article->getName() . '</a>';
}

Weitere Sortier-Beispiele

Sortierung nach Datum (absteigend)

<?php
usort($articles, function ($a, $b) {
    return strtotime($b->getValue('createdate')) - strtotime($a->getValue('createdate'));
});

Sortierung nach Meta-Feld

<?php
usort($articles, function ($a, $b) {
    return strcmp($a->getValue('art_custom_field'), $b->getValue('art_custom_field'));
});

Numerische Sortierung

<?php
usort($articles, function ($a, $b) {
    return $a->getValue('art_order') <=> $b->getValue('art_order');
});

Besserer Ansatz

Als wiederverwendbare Funktion

<?php
class ArticleHelper
{
    /**
     * Sortiert Artikel nach einem beliebigen Feld
     * 
     * @param rex_article[] $articles
     * @param string $field
     * @param string $direction 'asc' oder 'desc'
     * @return rex_article[]
     */
    public static function sortBy(array $articles, string $field = 'name', string $direction = 'asc'): array
    {
        usort($articles, function ($a, $b) use ($field, $direction) {
            $valA = $a->getValue($field);
            $valB = $b->getValue($field);
            
            // Numerische Werte
            if (is_numeric($valA) && is_numeric($valB)) {
                $result = $valA <=> $valB;
            } else {
                // Textvergleich (case-insensitive für deutsche Umlaute)
                $result = strcasecmp($valA, $valB);
            }
            
            return $direction === 'desc' ? -$result : $result;
        });
        
        return $articles;
    }
}

// Verwendung
$articles = rex_category::get($categoryId)->getArticles(true);
$articles = ArticleHelper::sortBy($articles, 'name', 'asc');

Mit Collator für korrekte deutsche Sortierung

<?php
class ArticleHelper
{
    public static function sortByName(array $articles, string $direction = 'asc'): array
    {
        $collator = new Collator('de_DE');
        
        usort($articles, function ($a, $b) use ($collator, $direction) {
            $result = $collator->compare($a->getName(), $b->getName());
            return $direction === 'desc' ? -$result : $result;
        });
        
        return $articles;
    }
}

Direkt per SQL (performanter bei vielen Artikeln)

<?php
$categoryId = rex_category::getCurrentId();
$sql = rex_sql::factory();

$articles = $sql->getArray('
    SELECT id, name, createdate
    FROM ' . rex::getTable('article') . '
    WHERE parent_id = :category_id
    AND status = 1
    ORDER BY name ASC
', ['category_id' => $categoryId]);

foreach ($articles as $article) {
    $articleObj = rex_article::get($article['id']);
    echo '<a href="' . $articleObj->getUrl() . '">' . $article['name'] . '</a>';
}

Diese SQL-Variante ist bei großen Kategorien effizienter, da die Sortierung in der Datenbank erfolgt.