Проверка типов данных в Коллекциях Laravel с помощью метода ensure()
Введение
В проектах Laravel могут возникать ситуации, когда необходимо вручную создать Коллекции данных. Это может быть связано с тем, что данные поступают из внешнего источника, например из API, или с тем, что вы генерируете их самостоятельно.
Подобное создание Коллекций вручную иногда может привести к тому, что будут добавлены элементы с неправильным типом данных. Например, нужно добавить в Коллекцию целое число, а вместо него случайно добавляется строка.
Конечно, качественный набор тестов, скорее всего, выявит подобные проблемы. Но, к сожалению, иногда эти проблемы могут проскальзывать сквозь трещины.
Поэтому может быть целесообразно проверить Коллекции, и убедиться, что они содержат правильные типы данных, прежде чем начать взаимодействовать с ними.
Именно здесь на помощь приходит метод ensure()
. В этой статье мы рассмотрим, как использовать метод ensure()
, чтобы гарантировать, что элементы в Коллекции имеют правильный тип данных.
Использование метода ensure()
Метод ensure()
позволяет убедиться, что элементы в Коллекции имеют определённый тип данных. Если элемент в Коллекции не имеет указанного типа данных, метод выбросит исключение UnexpectedValueException
.
Рассмотрим несколько примеров использования метода ensure()
.
Проверка примитивов
С помощью метода ensure()
можно проверить, что все элементы в Коллекции относятся к следующим примитивным типам: string
, int
, float
, bool
или array
.
Например, если необходимо проверить, что Коллекция содержит только элементы типа string
, это можно сделать следующим образом:
$collection = collect(['Ash', 'Allen']);
$collection->ensure('string');
Аналогично, если необходимо проверить, что Коллекция содержит только элементы int
, это можно сделать следующим образом:
$collection = collect([1, 2, 3, 4, 5]);
$collection->ensure('int');
В следующем примере метод ensure выбросит исключение UnexpectedValueException
, потому что коллекция содержит элемент int
, а мы пытаемся убедиться, что она содержит только элементы string
:
// ❌ Метод `ensure` выбросит исключение!
$collection = collect([1, 2, 3, 4, 5]);
$collection->ensure('string');
Сообщение выброшенного исключения будет следующим:
Collection should only include 'string' items, but 'int' found.
Проверка объектов и интерфейсов
Кроме того, что вы можете проверить, содержит ли Коллекция только примитивные типы, можно также использовать метод ensure()
для проверки того, что Коллекция содержит только объекты определённого класса или интерфейса.
Например, если необходимо проверить, что Коллекция содержит только элементы класса App\Models\User
, то это можно сделать следующим образом:
use App\Models\User;
$collection = collect([
new User('Ash'),
new User('Allen'),
]);
$collection->ensure(User::class);
В следующем примере метод ensure выбросит исключение UnexpectedValueException
, поскольку коллекция содержит объект Post
, а мы пытаемся убедиться, что она содержит только объекты User
:
// ❌ Метод `ensure` выбросит исключение!
use App\Models\User;
use App\Models\Post;
$collection = collect([
new User('Ash'),
new User('Allen'),
new Post(),
]);
$collection->ensure(User::class);
Также можно использовать метод ensure для проверки того, что Коллекция содержит только элементы, реализующие определённый интерфейс. Например, если необходимо проверить, что Коллекция содержит только элементы, реализующие интерфейс Illuminate\Auth\Authenticatable
, это можно сделать следующим образом:
use App\Models\User;
use Illuminate\Auth\Authenticatable;
$collection = collect([
new User('Ash'),
new User('Allen'),
]);
$collection->ensure(Authenticatable::class);
В приведённом выше примере предполагается, что класс App\Models\User
реализует интерфейс Illuminate\Auth\Authenticatable
.
Проверка нескольких типов
Бывают случаи, когда необходимо проверить, содержит ли Коллекция элементы нескольких типов. Это можно сделать, передав массив типов в метод ensure()
.
Пока каждый элемент соответствует хотя бы одному из типов в массиве, метод ensure не будет выбрасывать исключение.
Например, если необходимо проверить, содержит ли Коллекция элементы, которые являются либо int
, либо float
, это можно сделать следующим образом:
$collection = collect([1, 2, 3.5, 4, 5]);
$collection->ensure(['int', 'float']);
Аналогично, если необходимо проверить, что коллекция содержит элементы, являющиеся экземплярами App\Models\User
или App\Models\Post
, это можно сделать следующим образом:
use App\Models\User;
use App\Models\Post;
$collection = collect([
new User('Ash'),
new User('Allen'),
new Post(),
]);
$collection->ensure([User::class, Post::class]);
Если вы используете метод ensure для проверки того, что Коллекция содержит элементы нескольких классов, это может быть признаком того, что вам следует использовать интерфейсы. Поэтому следует подумать о рефакторинге ваших классов, чтобы они реализовывали один и тот же интерфейс. Это позволит использовать метод ensure для проверки того, что Коллекция содержит элементы, реализующие этот интерфейс, а не проверять оба указанных класса.
Однако это не всегда возможно или необходимо. Всё зависит от конкретного случая использования.
Использование описанного выше подхода (передача нескольких типов в метод ensure) может быть очень полезно, если это не ваши классы в Коллекции. Например, классы могут принадлежать стороннему пакету, и поэтому сложно (или невозможно) изменить их так, чтобы они реализовывали один и тот же интерфейс.
В этом случае метод ensure может стать полезным способом убедиться, что Коллекция содержит элементы правильных типов.
На что следует обратить внимание
Важно отметить, что метод ensure проверяет только те элементы, которые уже есть в Коллекции. Если после вызова метода ensure вы добавите в Коллекцию ещё какие-либо элементы, это не помешает добавить в Коллекцию элемент неправильного типа.
По этой причине, если собираетесь запускать метод ensure, стоит подумать о том, чтобы запускать его только после завершения добавления элементов в Коллекцию.
Кроме того, рекомендуется использовать метод ensure в крайнем случае, чтобы отловить все ошибки, которые могли ускользнуть от внимания. В идеальном мире вы не захотите, чтобы этот метод выбрасывал исключение.
Поэтому, хотя метод ensure и может быть полезным инструментом, он не заменит качественный код и тщательный набор тестов.
Правильное использование подсказок типов, возвращаемых типов и строгой проверки типов поможет избежать добавления неправильных данных в Коллекцию.