Всем привет, прошёл почти год с публикации первой части. Обсуждение в комментариях было жарким, выводы я для себя сделал, изменения в либу внёс почти сразу, но написать об этом времени не нашлось.
На днях расширил функционал парой методов, и хочу поделиться с вами этими новостями.
И конечно я напишу о работе над ошибками.
Для тех кто не знал и забыл, что такое ArrayHandler
SpoilerОтветим на вопрос: "что такое типобезопасная работа с массивами в PHP ?"
Типобезопасная это:
-
Когда мы можем получить элемент массива без опасности получить эксепшен о не существующем индексе;
-
Когда мы можем передать полученный элемент в метод и мы точно не получим эксепшен несоответствия типов;
И последние в списке, но не последнее по значению, типобезопасный код - это когда нам приятно писать хороший код. Для меня это наверное даже самое важное, потому что я устал от бесконечных:
$a = 0;if (key_exists($key, $collection)) {$a = (int) $collection[$key];}
И даже когда я узнал о современном способе писать через:
$a = (int) $collection[$key] ?? 0;
Мне от этого не полегчало, потому что вложенность у массивов бывает "мама не горюй".
Кроме этих трёх преимуществ, ArrayHandler даёт иммутабельность, то есть мы можем спокойно пробрасывать наш ArrayHandler, через слои абстракций и ни кто случайно не поменяет элементы внутри исходного массива. Для того что бы поменять значение, надо создать новый экземпляр ArrayHandler - и такое пропустить на код ревью сложнее, чем пропустить запись нового значения в элемент массива.
Не буду копипастить примеры работы с либой, их можно посмотреть в первой части или можно почитать документацию.
Либа устанавливается через Композер:
composer require sbwerewolf/language-specific
Есть версии для PHP 5.6 / 7.0 / 7.2 .
Это было долгое вступление теперь по существу.
Обновления
Пару дней назад мне было и грустно и скучно, захотелось сделать что ни будь хорошее, например сделать так что бы, когда пробегаешь по элементам с помощью foreach(), можно было не только получить элемент ( ValueHandler ), но индекс этого элемента.
Я с энтузиазмом принялся за работу и уже написав тонны кода, наткнулся на комент в документации к PHP, который сделал весь новый код бесполезным.
Оказывается можно делать так:
yield $key => $value;
И в foreach() будет возвращён индекс элемента. Эврика!
Теперь IArrayHandler::pulling() возвращает и новый IArrayHandler от элемента массива, и индекс этого элемента. Я был счастлив, кажется теперь ArrayHandler стал идеальной библиотекой для работы с массивами (в том виде как я обозначил в начале статьи).
На эмоциях я запилил ещё два метода. То есть ещё один метод - IArrayHandler::getting(), плюс я добавил поддержку интерфейса Iterator и теперь экземпляр ArrayHandler можно использовать в foreach() как обычный массив.
Теперь IArrayHandler::pulling() возвращает ArrayHandler для каждого вложенного массива (будут проигнорированы элементы исходного массива, которые не являются массивами). Название метода "pulling" образовалось от названия другого метода - IArrayHandler::pull(), с помощью которого можно получить экземпляр ArrayHandler от элемента массива.
IArrayHandler::getting() возвращает IValueHandler для всех элементов массива, не являющимися массивами. Название метода "getting" образовалось от названия другого метода - IArrayHandler::get(), с помощью которого можно получить экземпляр IValueHandler от элемента массива.
Теперь у нас IArrayHandler::pulling() для массивов, и IArrayHandler::getting() для всех остальных типов.
Более наглядно:
$data = new ArrayHandler( [ 'first' => ['A' => 1], 'next' => ['B'=>2], 'last' => ['C'=>3], 4=>[5,6], 7, 8, 9 ]);echo 'arrays'.PHP_EOL;foreach ($data->pulling() as $key => $value) { echo "[$key] => class is ".get_class($value).' '.PHP_EOL;}echo 'values'.PHP_EOL;foreach ($data->getting() as $key => $value) { echo "[$key] => {$value->asIs()} , class is ".get_class($value).' '.PHP_EOL;}
Вывод скрипта:
arrays[first] => class is LanguageSpecific\ArrayHandler [next] => class is LanguageSpecific\ArrayHandler [last] => class is LanguageSpecific\ArrayHandler [4] => class is LanguageSpecific\ArrayHandler values[5] => 7 , class is LanguageSpecific\ValueHandler [6] => 8 , class is LanguageSpecific\ValueHandler [7] => 9 , class is LanguageSpecific\ValueHandler
Если нам надо пробежаться по всем элементам исходного массива, мы используем обычный foreach():
$data = new ArrayHandler( [ 'first' => ['A' => 1], 'next' => ['B'=>2], 'last' => ['C'=>3], 4=>[5,6], 7, 8, 9 ]);echo 'ALL'.PHP_EOL;foreach ($data as $key => $value) { $type = gettype($value->asIs()); echo "[$key] => value type is $type , class is ".get_class($value).PHP_EOL;}
Вывод скрипта:
ALL[first] => value type is array , class is LanguageSpecific\ValueHandler[next] => value type is array , class is LanguageSpecific\ValueHandler[last] => value type is array , class is LanguageSpecific\ValueHandler[4] => value type is array , class is LanguageSpecific\ValueHandler[5] => value type is integer , class is LanguageSpecific\ValueHandler[6] => value type is integer , class is LanguageSpecific\ValueHandler[7] => value type is integer , class is LanguageSpecific\ValueHandler
Соответственно, если мы какие то элементы хотим обработать как элементы, а какие то как массивы, то мы в foreach(), делаем так:
foreach ($data as $key => $value) { /* @var \LanguageSpecific\ValueHandler $value */ if($value->type() === 'array'){ $handler = new ArrayHandler($value->array()); /* some code */ }}
Работа над ошибками
Метод IValueHandler::default() перестал быть статическим, его опасность до меня пытался донести @GreedyIvan, до меня дошло через неделю, спасибо.
Метод ArrayHandler::simplify() был удалён, потому что на самом деле
Зачем ArrayHandler->simplify(), когда есть array_column? (c) @olegmar
Cпасибо @olegmar.
Метод IArrayHandler::next() был заменён на IArrayHandler::pulling(), этот метод перебирает все вложенные массивы (первый уровень вложенности). Не то что бы комент от @Hett меня прямо убедил, но к размышлениям подтолкнул.
Спасибо @ReDev1L за поддержку в коментах.
Был добавлен метод IArrayHandler::raw(), что бы можно было получить исходный массив. Раньше, когда не было возможности получить индекс элемента, приходилось перебирать исходный массив, сейчас по опыту использования, бывает необходимость добавить/убавить элементы массива и создать из изменённого массива новый ArrayHandler.
На этом всё. Спасибо за чтение.