GAJDAW


MOJE KSIĄŻKI

Książka pt. Git. Recipes
Książka pt. Git. Rozproszony system kontroli wersji
Książka pt. PhpStorm Starter
Książka pt. Symfony w przykładach
Książka pt. GIMP. Praktyczne projekty. Wydanie II
Książka pt. PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych
Książka pt. PHP. Praktyczne projekty

PROGRAMY

Sortowanie danych względem dowolnych kolumn

Włodzimierz Gajda

W artykule opiszę szczegóły implementacji sortowania wielokolumnowych tabel danych. Najwygodniejszym rozwiązaniem jest modyfikacja nagłówków tabel, tak, by każda kolumna nagłówkowa służyła do sortowania w porządku rosnącym oraz malejącym. Opisane rozwiązanie jest uniwersalne i może być wykorzystane do sortowania tabel o dowolnej liczbie kolumn i występujących na dowolnej podstronie serwisu.

1. Przykładowa witryna

Sortowanie danych omówię na przykładzie aplikacji, która jest bibliograficzną bazą danych artykułów, jakie zostały opublikowane na łamach Magazynu INTERNET. Baza danych zawiera wszystkie artykuły z lat 2003 oraz 2004. Strona główna aplikacji jest przedstawiona na rysunku 1.

Rysunek 1. Strona główna aplikacji Magazyn INTERNET

Po wybraniu opcji AUTORZY, na witrynie pojawia się lista wszystkich osób, które pisały do MI. Lista ta jest domyślnie posortowana alfabetycznie wg nazwisk. Ilustruje to rysunek 2.

Rysunek 2. Lista wszystkich autorów posortowana alfabetycznie wg nazwisk

Do zmiany porządku sortowania służą nagłówki kolumn tabeli, przedstawione na rysunku 3. Po kliknięciu hiperłącza Imię i nazwisko dane zostaną posortowane rosnąco wg nazwiska i imienia. Ponowna aktywacja tego samego hiperłącza spowoduje odwrócenie porządku sortowania: dane zostaną posortowane malejąco. Ilustruje to rysunek 4, na którym Jakub Żelichowski znajduje się na pozycji pierwszej.

Rysunek 3. Nagłówki umożliwiają sortowanie rosnące i malejące wg dowolnej kolumny

Rysunek 4. Lista autorów posortowana malejąco wg nazwisk

Podobnie rzecz się ma w przypadku pozostałych kolumn. Kolumna Artykuły umożliwia przesortowanie listy autorów rosnąco oraz malejąco wg liczby opublikowanych artykułów. Rysunek 5 przedstawia listę autorów posortowaną malejąco wg liczby opublikowanych tekstów.

Rysunek 5. Lista autorów posortowana malejąco wg liczby opublikowanych artykułów

Natomiast rysunek 6 przedstawia listę autorów posortowaną rosnąco wg liczby stron. Sortowanie takie jest możliwe dzięki nagłówkowi kolumny przedstawiającej liczbę stron. W przypadku równej liczby zajętych stron autorzy są posortowani w porządku rosnącym, alfabetycznie wg nazwisk.

Rysunek 6. Lista autorów posortowana rosnąco wg liczby stron

Na tej samej zasadzie sortujemy dane przedstawiane na pozostałych stronach serwisu. Na stronie przedstawiającej wszystkie rubryki dane możemy sortować:

Rysunek 7 przedstawia listę rubryk posortowaną rosnąco wg liczby stron.

Rysunek 7. Zestawienie wszystkich rubryk czasopisma posortowane rosnąco wg liczby stron

Podrubryki czasopisma możemy sortować:

Rysunek 8 przedstawia listę podrubryk posortowaną malejąco wg liczby artykułów.

Rysunek 8. Zestawienie wszystkich podrubryk czasopisma posortowane malejąco wg liczby artykułów

Poznawszy cel, przejdźmy do jego realizacji.

2. Zapytania SQL

Oczywiście sortowanie danych wykonujemy wykorzystując klauzulę ORDER BY języka SQL.

Listę wszystkich autorów posortowaną rosnąco wg nazwiska i imienia ustala zapytanie:

SELECT
    tosoba_id,
    imie,
    nazwisko,
    liczbaartykulow,
    liczbastron
FROM
    tosoba
ORDER BY
    nazwisko, imie

Jeżeli chcemy osiągnąć odwrotny porządek sortowania, to w klauzuli ORDER BY dodajemy słowo kluczowe DESC:

SELECT
    tosoba_id,
    imie,
    nazwisko,
    liczbaartykulow,
    liczbastron
FROM
    tosoba
ORDER BY
    nazwisko DESC, imie DESC

Zmianę porządku sortowania osiągniemy podając inne kolumny w klauzuli ORDER BY. Sortowanie rosnące liczbą artykułów osiągniemy zapytaniem:

SELECT
    tosoba_id,
    imie,
    nazwisko,
    liczbaartykulow,
    liczbastron
FROM
    tosoba
ORDER BY
    liczbaartykulow,
    nazwisko, imie

Dzięki podaniu trzech kolumn w klauzuli ORDER BY powyższego zapytania, w przypadku równej liczby artykułów autorzy zostaną posortowaniu alfabetycznie wg nazwiska i imienia.

Natomiast zapytanie:

SELECT
    tosoba_id,
    imie,
    nazwisko,
    liczbaartykulow,
    liczbastron
FROM
    tosoba
ORDER BY
    liczbaartykulow DESC,
    nazwisko, imie

ustali listę autorów posortowaną malejąco wg liczby opublikowanych tekstów (w przypadku równej liczby autorzy będą posortowani alfabetycznie wg nazwisk).

W ten sam sposób należy przygotować jeszcze dwa zapytania. Jedno z nich ma zwracać listę autorów posortowaną rosnąco wg liczby stron. Wynikiem drugiego zapytania powinna być lista autorów posortowana malejąco wg liczby stron. W przypadku równej liczby stron, rekordy sortujemy tak jak poprzednio: rosnąco alfabetycznie wg nazwiska i imienia. Zapytania te są przedstawione na listingach 1 oraz 2.

SELECT
    tosoba_id,
    imie,
    nazwisko,
    liczbaartykulow,
    liczbastron
FROM
    tosoba
ORDER BY
    liczbastron,
    nazwisko, imie

Listing 1. Lista autorów posortowana rosnąco wg liczby stron

SELECT
    tosoba_id,
    imie,
    nazwisko,
    liczbaartykulow,
    liczbastron
FROM
    tosoba
ORDER BY
    liczbastron DESC,
    nazwisko, imie

Listing 2. Lista autorów posortowana malejąco wg liczby stron

Przygotowaliśmy zatem sześć zapytań SQL odpowiadających za ustalenie listy autorów posortowanej w porządku:

3. Funkcja ustalająca listę autorów

Na podstawie sześciu zapytań opisanych w poprzednim punkcie należy teraz przygotować jedną funkcję o nazwie DBA_podaj_wszystkie_osoby(). Jest to metoda klasy DBA odpowiedzialna za ustalenie listy autorów posortowanej w odpowiednim porządku.

Porządek sortowania jest parametrem funkcji. Mamy w sumie sześć porządków sortowania. Są to właściwie trzy porządki odwrócone rosnąco i malejąco. Parametrami funkcji będą liczby 1, -1, 2, -3, 3, -3. Liczby dodatnie oznaczają porządek rosnący, a ujemne — malejący. Oto, jaki porządek ustala każda z liczb:

W funkcji DBA_podaj_wszystkie_osoby() występuje na początku instrukcja switch, która posiada sześć przypadków. Na każdy porządek sortowania wypada jeden przypadek. Wewnątrz instrukcji switch ustalane jest zapytanie SQL. Gdy zapytanie SQL jest gotowe, funkcja realizuje transakcję SQL wykorzystując metody klasy PEAR::DB. Listing 3 przedstawia zarys funkcji DBA_podaj_wszystkie_osoby() ograniczony do pierwszych dwóch przypadków instrukcji switch.

public function DBA_podaj_wszystkie_osoby($ASort = 1)
{
    switch ($ASort) {

    case 1:
        $q = '
            SELECT
                tosoba_id,
                imie,
                nazwisko,
                liczbaartykulow,
                liczbastron
            FROM
                tosoba
            ORDER BY
                nazwisko, imie
        ';
        break;

    case -1:
        $q = '
            SELECT
                tosoba_id,
                imie,
                nazwisko,
                liczbaartykulow,
                liczbastron
            FROM
                tosoba
            ORDER BY
                nazwisko DESC, imie DESC
        ';
        break;

    ...

    }

    $w = $this->Fdb->getAll($q);

    if (DB::isError($w)) {
        die(__LINE__ . ' ' . $w->getMessage());
    } else {
        return $w;
    }
}

Listing 3. Zarys metody DBA_podaj_wszystkie_osoby()

4. Zmienne URL

Kolejnym etapem wzbogacenia aplikacji o sortowanie danych jest ustalenie adresów URL. Strona przedstawiająca listę wszystkich autorów w domyślnym porządku sortowania ma adres:

index.php?id=3

Sortowanie wg dowolnej z trzech kolumn osiągniemy dodając zmienną URL o nazwie s. Zmienna ta będzie doklejona do podanego powyżej adresu i przyjmie wartości 1, -1, 2, -2, 3, -3:

index.php?id=3&s=1
index.php?id=3&s=-1
index.php?id=3&s=2
index.php?id=3&s=-2
index.php?id=3&s=3
index.php?id=3&s=-3

Podane powyżej adresy odpowiadają opisanym powyżej sześciu porządkom sortowania.

5. Walidacja danych

Ponieważ pojawia się dodatkowa zmienne, zatem należy rozszerzyć procedurę walidacji danych. W każdym z przypadków, w których pojawia się możliwość sortowania kolumn należy dodać sprawdzenie zmiennej s. Zmienna ta może przyjmować wartości całkowite z symetrycznego przedziału, z wyjątkiem 0. Do sprawdzenia poprawności zmiennej stosujemy funkcję ivsort(), która jest przedstawiona na listingu 4. W celu sprawdzenia, czy zmienna $a przyjmuje jedną z wartości 1, -2, 2, -2 należy funkcję ivsort() wywołać następująco:

if (ivsort($a, 2)) {
    //liczba $a jest poprawna
}
function ivsort($AZmienna, $AZakres)
{
    $tab = array();
    for ($i = 1; $i <= $AZakres; $i++) {
        array_push($tab, $i);
        array_push($tab, "-$i");
    }
    return in_array($AZmienna, $tab);
}

Listing 4. Funkcja ivsort()

Wykorzystując funkcję ivsort() walidacja aplikacji będzie przebiegała następująco. W każdym przypadku umożliwiającym sortowanie kolumn należy sprawdzić czy zmienna $_GET['s'] jest podana. Jeśli nie to przyjmujemy domyślny porządek sortowania, czyli do zmiennej $sortowanie wstawiamy 1. Jeżeli natomiast zmienna $_GET['s'] występuje, należy sprawdzić jej wartość funkcją ivsort(). Oto zarys walidacji przypadku 3: listy wszystkich autorów:

case 3:
    if (count($_GET) === 1) {
        $akcja = 3;
        $sortowanie = 1;
    } else if (
        (count($_GET) === 2) &&
        isset($_GET['s']) &&
        ivsort($_GET['s'], 3)
    ) {
        $akcja = 3;
        $sortowanie = $_GET['s'];
    }
    break;

6. Kod aplikacji

W kolejnym kroku przekazujemy ustalone sortowanie (tj. zmienną $sortowanie) do metody DBA_podaj_wszystkie_osoby() oraz do szablonu.

Pierwsze z tych zadań jest wykonane instrukcją:

case 3:
    $osoby = $db->DBA_podaj_wszystkie_osoby($sortowanie);
    $s->assign('osoby', $osoby);
    break;

zaś drugie:

$s->assign('sortowanie', $sortowanie);

7. Szablony kolumn

Ostatnią modyfikacją, jaką należy wprowadzić jest zmiana szablonu. Tabele HTML, umożliwiające sortowanie danych, muszą zawierać w komórkach nagłówkowych hiperłącza do adresów opisanych powyżej. Hiperłącza takie będą miały postać:

<a href="index.php?id=3&amp;s=1">Imię i nazwisko</a>

oraz

<a href="index.php?id=3&amp;s=-1">Imię i nazwisko</a>

Pierwsze z nich jest adresem listy autorów posortowanej rosnąco wg nazwisk, a drugie — malejąco wg nazwisk.

Liczbę 1 lub -1 wstawiamy warunkowo w zależności od aktualnego sortowania. Jeśli bieżące sortowanie jest rosnące, to należy wstawić -1. Na stronie posortowanej malejąco powinniśmy umieścić hiperłącze zawierające wartość s=1.

Należy zatem wykorzystać funkcję if szablonów. Przykładowy kod jest następujący:

<a href="index.php?id=3&amp;s={if $sortowanie == 1}-1{else}1{/if}">Imię i nazwisko</a>

W przypadku dalszych kolumn:

<a href="index.php?id=3&amp;s={if $sortowanie == 2}-2{else}2{/if}">Artykułów</a>
<a href="index.php?id=3&amp;s={if $sortowanie == 3}-3{else}3{/if}">Stron</a>

8. Podsumowanie

Opisana metoda jest uniwersalna i może być zastosowana do dowolnej podstrony serwisu. W omawianym przykładzie metoda ta jest wykorzystana na czterech podstronach:

Wykonanie sortowania wymaga:


Reklama

Szkolenia z Zend Framework 2.0