diff --git a/routes/web.php b/routes/web.php index 9c63920f..cc5a070b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -53,6 +53,7 @@ Route::view('/library/upgrade', 'library.upgrade')->name('library.upgrade'); Route::view('/library/security', 'library.security')->name('library.security'); Route::view('/library/how-to-ask', 'library.how-to-ask')->name('library.how-to-ask'); +Route::view('/library/collection', 'library.collection')->name('library.collection'); /* |-------------------------------------------------------------------------- diff --git a/storage/library/collection/basics.md b/storage/library/collection/basics.md new file mode 100755 index 00000000..c488080a --- /dev/null +++ b/storage/library/collection/basics.md @@ -0,0 +1,17 @@ +--- +title: "Основы" +description: "Понимание основных принципов работы с коллекциями" +--- + +Использование коллекций не является обязательным элементом, они не добавляют новую функциональность в PHP, но +предоставляют удобный интерфейс для работы с массивами. При написании кода с использованием коллекций вы будете писать +более выразительный код упрощая множество операций с данными, таких как фильтрация, сортировка, слияние и трансформация +и т.д. + +> [!NOTE] +> Результаты запросов `Eloquent` всегда возвращаются как экземпляры `Collection`. + +Когда вы пишете код в императивном стиле, вы указываете, как выполнить задачу, в то время как декларативный стиль +позволяет описывать что вы хотите достичь, без явного указания шагов выполнения. Использование коллекций способствует +более декларативному подходу к программированию, где вы объявляете операции над данных, а не реализуете их самостоятельно. + diff --git a/storage/library/collection/dont-primitives.md b/storage/library/collection/dont-primitives.md new file mode 100644 index 00000000..eb878bf1 --- /dev/null +++ b/storage/library/collection/dont-primitives.md @@ -0,0 +1,71 @@ +--- +title: "Не используйте примитивы" +description: "Что-то написать" +--- + +Помимо явной цепочки вызовов, мы можем передавать промежуточные значения для дальнейшей обработки. +Например, в одном методе мы можем сформировать коллекцию активных пользователей, а в другом продолжить высокоуровневую обработку: + +```php +function getActiveUsers(): array +{ + // ... + + $activeUsers = array_filter($activeUsers, function (User $user) { + return $user->isActive(); + }); + + $activeUsers = array_filter($activeUsers, function (User $user) { + return !$user->isAdmin(); + }); + + usort($activeUsers, function (User $a, User $b) { + return $a->created_at <=> $b->created_at; + }); + + retrun $activeUsers; +} + + +$activeUsers = getActiveUsers(); + +// Вычисление среднего возраста активных пользователей +$totalAge = 0; +foreach ($activeUsers as $user) { + $totalAge += $user->age; +} +$averageAge = $totalAge / count($activeUsers); + +// Формирование списка электронных адресов активных пользователей +$emailList = []; +foreach ($activeUsers as $user) { + $emailList[] = $user->email; +} +``` + +```php +// Хорошо ✅ +function getActiveUsers(): Collection +{ + // ... + + return $users + ->filter(function (User $user) { + return $user->isActive(); + }) + ->filter(function (User $user) { + return !$user->isAdmin(); + }) + ->sortBy('created_at'); +} + + + +$activeUsers = getActiveUsers(); + +// Вычисление среднего возраста активных пользователей +$averageAge = $activeUsers->avg('age'); + +// Формирование списка электронных адресов активных пользователей +$emailList = $activeUsers->pluck('email'); +``` diff --git a/storage/library/collection/foreach.md b/storage/library/collection/foreach.md new file mode 100644 index 00000000..216cc935 --- /dev/null +++ b/storage/library/collection/foreach.md @@ -0,0 +1,34 @@ +--- +title: "Не используйте циклы" +description: "Замените циклов на методы коллекций при обработке данных." +--- + +Циклы, такие как `foreach` и `for`, широко используются для обработки данных в PHP. +Однако, при использовании циклов код может стать трудночитаемым, запутанным, а следовательно подверженным ошибкам. +Рассмотрим следующий распространённый пример: + +```php +// Плохо ❌ +$activeUsers = []; + +foreach ($users as $user) { + if ($user->isActive()) { + $activeUsers[] = $user; + } +} +``` + +Здесь мы используем цикл `foreach` для фильтрации активных пользователей. +Этот подход требует создания временного массива и ведет к увеличению объема кода. + +При использовании коллекций доступно множество методов, таких как `filter`, `map`, `reduce`, которые позволяют заменить типичные циклы на более элегантные и понятные конструкции. Перепишем предыдущий пример, используя метод `filter`: + +```php +// Хорошо ✅ +$activeUsers = $users->filter(function (User $user) { + return $user->isActive(); +}); +``` + +Этот код короче, проще читается и не требует создания временного массива. +Метод `filter` применяет заданное условие к каждому элементу коллекции, возвращая только те, которые соответствуют критерию. diff --git a/storage/library/collection/thinking-in-steps.md b/storage/library/collection/thinking-in-steps.md new file mode 100644 index 00000000..420c7ffe --- /dev/null +++ b/storage/library/collection/thinking-in-steps.md @@ -0,0 +1,87 @@ +--- +title: "Думай поэтапно" +description: "Замените циклов на методы коллекций при обработке данных." +--- + +В программировании часто возникают задачи, требующие последовательного выполнения нескольких шагов для достижения +конечного результата. Методология "Думая поэтапно" помогает справиться с такими задачами, разбивая их на более мелкие, +управляемые этапы. Давайте рассмотрим, как мы можем использовать методы коллекций в PHP для реализации этого подхода. + +Давайте снова вернёмся к примеру с фильтрацией активных пользователей: + +```php +// Плохо ❌ +$activeUsers = []; + +foreach ($users as $user) { + if ($user->isActive()) { + $activeUsers[] = $user; + } +} +``` + +Теперь нам нужно добавить ещё один шаг: убрать администраторов из списка активных пользователей и мы не хотим +использовать массивы: + +```php +// Лучше, но не идеально ❌ +$activeUsers = array_filter($activeUsers, function (User $user) { + return $user->isActive(); +}); + +$activeUsers = array_filter($activeUsers, function (User $user) { + return !$user->isAdmin(); +}); +``` + +Нам пришлось объявить переменную `$activeUsers` дважды, но это не самое худшее. + +При использовании коллекции каждый вызов метода, это отдельный шаг, который можно легко прочитать и понять: + +```php +// Хорошо ✅ +$activeUsers = $users + ->filter(function (User $user) { + return $user->isActive(); + }) + ->filter(function (User $user) { + return !$user->isAdmin(); + }); +``` + + +Теперь введём ещё одно условие, нам нужно отсортировать пользователей по дате регистрации: + +```php +// Лучше, но не идеально ❌ +$activeUsers = array_filter($activeUsers, function (User $user) { + return $user->isActive(); +}); + +$activeUsers = array_filter($activeUsers, function (User $user) { + return !$user->isAdmin(); +}); + +usort($activeUsers, function (User $a, User $b) { + return $a->created_at <=> $b->created_at; +}); +``` + +Используя методы коллекций, мы можем добавить сортировку в цепочку методов: + +```php +// Хорошо ✅ +$activeUsers = $users + ->filter(function (User $user) { + return $user->isActive(); + }) + ->filter(function (User $user) { + return !$user->isAdmin(); + }) + ->sortBy('created_at'); +``` + + +Использование методов коллекций позволяет нам более явно выразить наши намерения при обработке данных, делая код более +структурированным и легким для понимания. +