Sortowanie tablicy wielowymiarowej w php

Podziel się z innymi!

    Zdecydowałem się wreszcie opublikować mój artykuł na temat wzorca projektowego DTO (Data Transfer Object), który napisałem już jakiś czas temu. Przy okazji parę akapitów poprawiłem i dopisałem nowe przykłady zastosowania. Przygotowując przykład dotyczący Recordset-u odkopałem przydatną funkcję ułatwiającą [sortowanie tablicy wielowymiarowej](http://php.net/manual/pl/function.array-multisort.php#87268). Jest uniwersalna i moim zdaniem warto zwrócić na nią uwagę. Ponad to wbrew pozorom nie musi służyć jedynie do sortowania wyników zapytań SQL-owych.

    <?php
    /**
     * Sort DB result
     *
     * @param array $data Result of sql query as associative array
     *
     * Rest of parameters are optional
     * [, string $name  [, mixed $name or $order  [, mixed $name or $mode]]]
     * $name string - column name i database table
     * $order integer - sorting direction ascending (SORT_ASC) or descending (SORT_DESC)
     * $mode integer - sorting mode (SORT_REGULAR, SORT_STRING, SORT_NUMERIC)
     *
     * <code>
     * <?php
     * // You can sort data by several columns e.g.
     * $data = array();
     * for ($i = 1; $i <= 10; $i++) {
     *     $data[] = array( 'id' => $i,
     *                      'first_name' => sprintf('first_name_%s', rand(1, 9)),
     *                      'last_name' => sprintf('last_name_%s', rand(1, 9)),
     *                      'date' => date('Y-m-d', rand(0, time()))
     *                  );
     * }
     * $data = sortDbResult($data, 'date', SORT_DESC, SORT_NUMERIC, 'id');
     * print_r($data);
     * $data = sortDbResult($data, 'last_name', SORT_ASC, SORT_STRING, 'first_name', SORT_ASC, SORT_STRING);    
     * print_r($data);
     * ?>
     * </code>
     *
     * @return array $data - Sorted data
     */
    function sortDbResult(array $data /*$name, $order, $mode*/) {
        $_argList = func_get_args();
        $_data = array_shift($_argList);
        if (empty($_data)) {
            return $_data;
        }
        $_max = count($_argList);
        $_params = array();
        $_cols = array();
        $_rules = array();
        for ($_i = 0; $_i < $_max; $_i += 3)
        {
            $_name = (string) $_argList[$_i];
            if (!in_array($_name, array_keys(current($_data)))) {
                continue;
            }
            if (!isset($_argList[($_i + 1)]) || is_string($_argList[($_i + 1)])) {
                $_order = SORT_ASC;
                $_mode = SORT_REGULAR;
                $_i -= 2;
            } else if (3 > $_argList[($_i + 1)]) {
                $_order = SORT_ASC;
                $_mode = $_argList[($_i + 1)];
                $_i--;
            } else {
                $_order = $_argList[($_i + 1)] == SORT_ASC ? SORT_ASC : SORT_DESC;
                if (!isset($_argList[($_i + 2)]) || is_string($_argList[($_i + 2)])) {
                    $_mode = SORT_REGULAR;
                    $_i--;
                } else {
                    $_mode = $_argList[($_i + 2)];
                }
            }
            $_mode = $_mode != SORT_NUMERIC
                        ? $_argList[($_i + 2)] != SORT_STRING ? SORT_REGULAR : SORT_STRING
                        : SORT_NUMERIC;
            $_rules[] = array('name' => $_name, 'order' => $_order, 'mode' => $_mode);
        }
        foreach ($_data as $_k => $_row) {
            foreach ($_rules as $_rule) {
                if (!isset($_cols[$_rule['name']])) {
                    $_cols[$_rule['name']] = array();
                    $_params[] = &$_cols[$_rule['name']];
                    $_params[] = $_rule['order'];
                    $_params[] = $_rule['mode'];
                }
                $_cols[$_rule['name']][$_k] = $_row[$_rule['name']];
            }
        }
        $_params[] = &$_data;
        call_user_func_array('array_multisort', $_params);
        return $_data;
    }
    ?>
    Podziel się z innymi!

      Posted in PHP by Zbigniew Heintze · Tags: ,