Контент


Хэлпер Arr: работа с массивами

Пока плодятся поспешные минорные релизы Kohana 3.0.6.x, давайте-как лучше рассмотрим полезнейший хэлпер Arr, предназначенный для работы с массивами. Вроде бы ничего сложного, массивы как массивы, а какие удобства обеспечивает один небольшой класс! Итак, к делу.

  • Метод is_assoc(array $array). Позволяет проверить, является ли массив ассоциативным или нет. Алгоритм достаточно интересный (впервые увидел двойной вызов array_keys()). Стоит отметить, что если в исходном массиве ключи числовые, то все равно вернется TRUE (единственное исключение — массив с индексами от нуля с шагом 1, т.е. типичный неассоциативный массив).
  • Метод path($array, $path, $default = NULL). Просто жизненно важный метод для работы с многомерными массивами, он позволяет обратиться в вложенному элементу, используя точку в качестве разделителей уровня вложенности. Например, если есть элемент
    $array['test']['var']['value']

    , то

    arr::path($array, 'test.var.value')

    вернет его значение. Третий параметр, как несложно догадаться, предназначен для значения на случай, если элемент отсутствует.

  • Метод range($step = 10, $max = 100) вернет массив, заполненный элементами с шагом $step, вплоть до максимального числа $max. Не очень удобно, что нельзя указать начальный элемент (для данного метода он всегда будет совпадать с числом $step).
  • Метод get($array, $key, $default = NULL), думаю, самый известный в данном классе. Он ищет элемент в массиве, с поддержкой дефолтного значения. Отличается от arr::path() тем, что ищет только в первом уровне вложенности.
  • Метод extract($array, array $keys, $default = NULL). Метод, часто используемый для безопасной обработки данных глобальных массивов. Передавая массив $keys, мы определяем ключи, которые надо извлекать из массива $array. Все прочие ключи игнорируются. Если по какому-то ключу значение не найдено, подставляется $default. Например,
    $user_data = arr::extract($_POST, array('username', 'password', 'remember'), NULL)

    , позволит получить массив из ключей ‘username‘, ‘password‘ и ‘remember‘ массива $_POST.

  • Метод binary_search($needle, $haystack, $sort = FALSE), в ветке 2.3.x использовавшийся для бинарного поиска, теперь просто вызывает array_search(), так что смысла в его использовании нет (оставлен для совместимости).
  • Метод unshift(array & $array, $key, $val) позволяет вставить в начало ассоциативного массива значение $val по ключу $key.
  • Метод map($callback, $array) рекурсивно применяет функцию $callback ко всем элементам $array, в том числе и подмассивам. В отличие от стандартного array_map(), arr::map() не работает с несколькими массивами (т.е.
    arr::map('trim', $array1, $array2, $array3)

    не пройдет).

  • Метод merge(array $a1, array $a2) рекурсивно объединяет два массива. В отличие от array_merge_recursive(), она не принимает более 2х массивов. Кроме того, если массивы неассоциативные, то значения не будут дублироваться. Например,
    arr::merge(array('foo'), array('foo'))

    вернет

    array('foo')

    , а не

    array('foo', 'foo')

  • Метод overwrite($array1, $array2) перезаписывает значения массива $array1 значениями из $array2. При этом новые ключи в $array1 не добавляются. Таким образом, пример из пункта про arr::extract() можно записать как
    arr::overwrite(array('username' => null, 'password' => null, 'remember' => null), $_POST);

  • Метод callback($str) пытается разбить строковое представление вызова функции с параметрами на массив (функция, параметры). Например,
    arr::callback('foo::bar(1,2,$_POST)')

    вернет массив:

     array(2) 
    { 
       [0]=>  array(2) 
       { 
          [0]=>  string(3) "foo" 
          [1]=>  string(3) "bar" 
       } 
       [1]=>  array(3) 
       { 
          [0]=>  string(1) "1" 
          [1]=>  string(1) "2" 
          [2]=>  string(6) "$_POST"  
       } 
    }

    Если в строку заключать не в одиночные кавычки, а в двойные, то, что естественно, вместо строки $_POST подставится строковое представление этого глобального массива, т.е. строка ‘array‘.

    В версии 2.3.4 был похожий метод callback_string(), но он предусматривал использование квадратных скобок в строке, т.е. ‘foo::bar[1,2]‘. Вероятно это связано с использованием такого синтаксиса в Валидаторе, при объявлении правил.

  • Метод flatten($array) преобразовывает многомерный массив в одномерный. Значения просто переносятся в «корень» массива. При этом ключи сохранятся только для конечных элементов (не являющихся массивами). Пример:

    $arr = array
    (
       '1' => array
       (
          '2' => 2, 
          '3' => array
          (
             4, 
             6 => 6
          )
       ), 
       '5' => 5
    );
    var_dump(arr::flatten($arr));


    В результате получим массив:

    array(4) 
    {
       [2]=>  int(2) 
       [0]=>  int(4)  
       [6]=>  int(6) 
       [5]=>  int(5) 
    }


    У элемента ’4′ ключ сгенерирован заново, а массив под ключом ’3′ исчез, оставив только свое содержимое. Тут стоит обратить внимание, что в целом ключи остались прежними. А что, если у двух элементов будет одно и то же значение ключа? Проверим:

    $arr = array
    (
       '1' => array
       (
          '2' => 2, 
          '3' => array
          (
             4, 
             5 => 6
          )
       ), 
       '5' => 5
    );
    var_dump(arr::flatten($arr));


    Здесь я для значения ’6′ поменял ключ. В результате получим:
    array(3)
    {
    [2]=> int(2)
    [0]=> int(4)
    [5]=> int(5)
    }

    Один элемент пропал — шестерка была затерта пятеркой, т.к. ключи совпадали. Так что будьте осторожнее с этим методом.

По сравнению с 2.3.4, в хэлпере не хватает таких методов, как rotate(), remove() и to_object(). Но их всегда можно перенести в третью ветку, ничего сложного в этом нет.

На этом наше короткое теоретическое знакомство с данным хэлпером закончено — приступайте к практике. Пользуйтесь этим классом, не изобретайте велосипед ;)

Google Bookmarks Digg Reddit del.icio.us Ma.gnolia Technorati Slashdot Yahoo My Web News2.ru БобрДобр.ru RUmarkz Ваау! Memori.ru rucity.com МоёМесто.ru Mister Wong

Опубликовано в cправочник.

Теги: , .


Комментарии (10)

Будьте в курсе обсуждения, подпишитесь на RSS ленту комментариев к этой записи.

  1. php code пишет:

    спасибо за статью

  2. Мимошёл пишет:

    А ещё жутко не хватает метода из 2.3.4, который мог по такому пути foo.bar.val установить значение.

  3. Богдан пишет:

    Мимошёл ну так его же можно очень просто реализовать

  4. biakaveron пишет:

    Как я и писал в конце статьи — по сути все эти методы просто копируются и работают :)

  5. stalker пишет:

    Работая над очередным проектом расширил стандартный Arr следующим образом:
    http://pastie.org/1012138

  6. biakaveron пишет:

    Позволю несколько замечаний:
    1. Почему класс абстрактный?
    2. Строка №29. Зачем проверка is_array(), если тип параметра указан явно (array & $array)?
    3. Функция get_ref(). Какой смысл возвращать указатель на дефолтное значение? Может, тогда уж вставлять его в массив?
    4. Функция set(). Стало привычным уже, что первым параметром идет массив. Почему тут он последний? Да и возвращать его зачем? Может тогда уж передавать по ссылке?

  7. stalker пишет:

    1. Потому что это часть библиотеки Mobitech, классы которой не должны иметь инстансов. В проекте добавляется extends класс вида:
    class Arr extends Mobitech_Arr {};

    2. Верно подмечено. ИМХО, array в параметрах функции был добавлен позже.

    3. Например для того, чтобы на вход можно было задать ‘другую ветку’ того же массива и получить на нее ссылку вместо не найденой.

    4. Обратите внимание, что в функции set() последний параметр имеет default значение ($haystack = array()) .. Это позволяет делать сокращенную запись вида: Arr::set($path, $value) и на выходе получить новый массив с одной парой $key=>$value. А возвращается он для того, чтобы можно было делать такие штуки:

    $this->template->set( Arr::set(‘data’, $data) );
    $this->template->set( Arr::set_multi(array(‘data1′ => $data1, ‘data2′ => $data2, ..)) );

  8. Мимошёл пишет:

    2 Богдан и biakaveron, спасибо но догадаться что нужные методы можно вытащить из другого фреймворка не сложно. Речь не о том, отсутствие некоторых вещей в кохане 3, всё же некоторый регресс, ничем не оправданный.

  9. Сергей пишет:

    Ч то такое int arr size?

  10. biakaveron пишет:

    Где нашли?



Можно включить подсветку кода: <code><pre lang="">...</pre></code>
Разрешены некоторые HTML теги

или используйте trackback.