1. Eloquent ORM
  2. Eloquent: Ресурсы API

Присоединяйся к нашему Telegram сообществу @webblend!

Здесь ты найдешь сниппеты по Laravel и полезные советы по веб-разработке.

Введение

При создании API вам может потребоваться слой трансформации, который находится между вашие моделями Eloquent и JSON-ответами, которые фактически возвращаются пользователям вашего приложения. Например, вы можете отображать определенные атрибуты для подмножества пользователей и не для других, или всегда включать определенные отношения в JSON-представлении ваших моделей. Ресурсы Eloquent позволяют вам выразительно и легко преобразовывать ваши модели и коллекции моделей в JSON.

Конечно, вы всегда можете преобразовывать модели или коллекции Eloquent в JSON с использованием их методов toJson; однако ресурсы Eloquent предоставляют более детальный и надежный контроль над JSON-сериализацией ваших моделей и их отношений.

Генерация ресурсов

Для создания класса ресурса вы можете использовать команду Artisan make:resource. По умолчанию ресурсы будут размещены в каталоге app/Http/Resources вашего приложения. Ресурсы расширяют класс Illuminate\Http\Resources\Json\JsonResource:

php artisan make:resource UserResource

Коллекции ресурсов

Помимо создания ресурсов, которые преобразуют отдельные модели, вы можете создавать ресурсы, которые отвечают за преобразование коллекций моделей. Это позволяет включать в ваши JSON-ответы ссылки и другую мета-информацию, которая относится ко всей коллекции заданного ресурса.

Для создания коллекции ресурсов вы должны использовать флаг --collection при создании ресурса. Или, включение слова Collection в имя ресурса указывает Laravel, что нужно создать коллекцию ресурсов. Классы коллекций ресурсов расширяют класс Illuminate\Http\Resources\Json\ResourceCollection:

php artisan make:resource User --collection
 
php artisan make:resource UserCollection

Обзор концепции

Примечание Это общий обзор ресурсов и коллекций ресурсов. Настоятельно рекомендуется прочитать другие разделы этой документации, чтобы получить более глубокое понимание возможностей и средств, предоставляемых вам ресурсами.

Прежде чем погружаться во все ваши варианты при написании ресурсов, давайте сначала обзорно рассмотрим, как ресурсы используются в Laravel. Класс ресурса представляет собой одну модель, которую необходимо преобразовать в структуру JSON. Например, вот простой класс ресурса UserResource:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
 
class UserResource extends JsonResource
{
/**
* Преобразует ресурс в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}

Каждый класс ресурса определяет метод toArray, который возвращает массив атрибутов, которые должны быть преобразованы в JSON, когда ресурс возвращается в качестве ответа из маршрута или метода контроллера.

Обратите внимание, что мы можем получать доступ к свойствам модели напрямую из переменной $this. Это потому, что класс ресурса автоматически передает доступ к свойствам и методам вниз к базовой модели для удобного доступа. После того как ресурс определен, его можно вернуть из маршрута или контроллера. Ресурс принимает экземпляр базовой модели через свой конструктор:

use App\Http\Resources\UserResource;
use App\Models\User;
 
Route::get('/user/{id}', function (string $id) {
return new UserResource(User::findOrFail($id));
});

Коллекции ресурсов

Если вы возвращаете коллекцию ресурсов или ответ с пагинацией, вы должны использовать метод collection, предоставленный вашим классом ресурса, при создании экземпляра ресурса в вашем маршруте или контроллере:

use App\Http\Resources\UserResource;
use App\Models\User;
 
Route::get('/users', function () {
return UserResource::collection(User::all());
});

Обратите внимание, что это не позволяет добавлять пользовательские метаданные, которые могут быть возвращены вместе с вашей коллекцией. Если вы хотите настроить ответ на коллекцию ресурсов, вы можете создать отдельный ресурс для представления коллекции:

php artisan make:resource UserCollection

После того как класс коллекции ресурсов был сгенерирован, вы можете легко определить любые метаданные, которые должны включаться в ответ:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;
 
class UserCollection extends ResourceCollection
{
/**
* Преобразует коллекцию ресурсов в массив.
*
* @return array<int|string, mixed>
*/
public function toArray(Request $request): array
{
return [
'data' => $this->collection,
'links' => [
'self' => 'link-value',
],
];
}
}

После определения вашей коллекции ресурсов ее можно вернуть из маршрута или контроллера:

use App\Http\Resources\UserCollection;
use App\Models\User;
 
Route::get('/users', function () {
return new UserCollection(User::all());
});

Сохранение ключей коллекции

При возврате коллекции ресурсов из маршрута Laravel сбрасывает ключи коллекции так, чтобы они имели числовой порядок. Однако вы можете добавить свойство preserveKeys к своему классу ресурса, указывающее, следует ли сохранять исходные ключи коллекции:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Resources\Json\JsonResource;
 
class UserResource extends JsonResource
{
/**
* Указывает, следует ли сохранять ключи коллекции ресурсов.
*
* @var bool
*/
public $preserveKeys = true;
}

Когда свойство preserveKeys установлено в true, ключи коллекции будут сохранены при возврате коллекции из маршрута или контроллера:

use App\Http\Resources\UserResource;
use App\Models\User;
 
Route::get('/users', function () {
return UserResource::collection(User::all()->keyBy->id);
});

Настройка базового класса ресурса

Обычно свойство $this->collection коллекции ресурса автоматически заполняется результатом сопоставления каждого элемента коллекции с ее собственным ресурсом. Предполагается, что сингулярный класс ресурса - это имя класса коллекции без завершающей части Collection. Кроме того, в зависимости от вашего личного вкуса сингулярный класс ресурса может быть с суффиксом Resource или без него.

Например, UserCollection будет пытаться сопоставить заданные экземпляры пользователя с ресурсом UserResource. Чтобы настроить это поведение, вы можете переопределить свойство $collects вашей коллекции ресурсов:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Resources\Json\ResourceCollection;
 
class UserCollection extends ResourceCollection
{
/**
* Ресурс, который собирает этот ресурс.
*
* @var string
*/
public $collects = Member::class;
}

Написание ресурсов

Примечание Если вы еще не читали обзор концепции, настоятельно рекомендуется сделать это перед изучением этой документации.

Ресурсы должны преобразовывать заданную модель в массив. Таким образом, каждый ресурс содержит метод toArray, который преобразует атрибуты вашей модели в дружественный к API массив, который может быть возвращен из маршрутов или контроллеров вашего приложения:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
 
class UserResource extends JsonResource
{
/**
* Преобразует ресурс в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}

После того как ресурс был определен, его можно вернуть напрямую из маршрута или контроллера:

use App\Http\Resources\UserResource;
use App\Models\User;
 
Route::get('/user/{id}', function (string $id) {
return new UserResource(User::findOrFail($id));
});

Отношения

Если вы хотите включить связанные ресурсы в ваш ответ, вы можете добавить их в массив, возвращаемый методом toArray вашего ресурса. В этом примере мы будем использовать метод collection ресурса PostResource для добавления блог-постов пользователя в ответ ресурса:

use App\Http\Resources\PostResource;
use Illuminate\Http\Request;
 
/**
* Преобразует ресурс в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'posts' => PostResource::collection($this->posts),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}

Примечание Если вы хотите включать отношения только тогда, когда они уже были загружены, ознакомьтесь с документацией по условным отношениям.

Коллекции ресурсов

В то время как ресурсы преобразуют одну модель в массив, коллекции ресурсов преобразуют коллекцию моделей в массив. Однако абсолютно не обязательно определять класс коллекции ресурсов для каждой вашей модели, так как все ресурсы предоставляют метод collection для создания «временной» коллекции ресурсов на лету:

use App\Http\Resources\UserResource;
use App\Models\User;
 
Route::get('/users', function () {
return UserResource::collection(User::all());
});

Однако, если вам нужно настроить метаданные, возвращаемые с коллекцией, необходимо определить свою собственную коллекцию ресурсов:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;
 
class UserCollection extends ResourceCollection
{
/**
* Преобразует коллекцию ресурсов в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'data' => $this->collection,
'links' => [
'self' => 'link-value',
],
];
}
}

Как и с сингулярными ресурсами, коллекции ресурсов могут быть возвращены напрямую из маршрутов или контроллеров:

use App\Http\Resources\UserCollection;
use App\Models\User;
 
Route::get('/users', function () {
return new UserCollection(User::all());
});

Обертка данных

По умолчанию ваш самый внешний ресурс оборачивается в ключ data, когда ответ ресурса преобразуется в JSON. Таким образом, например, ответ на коллекцию ресурсов выглядит следующим образом:

{
"data": [
{
"id": 1,
"name": "Eladio Schroeder Sr.",
"email": "[email protected]"
},
{
"id": 2,
"name": "Liliana Mayert",
"email": "[email protected]"
}
]
}

Если вы хотите использовать пользовательский ключ вместо data, вы можете определить атрибут $wrap в классе ресурса:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Resources\Json\JsonResource;
 
class UserResource extends JsonResource
{
/**
* Обертка "data", которую следует применить.
*
* @var string|null
*/
public static $wrap = 'user';
}

Если вы хотите отключить оборачивание самого внешнего ресурса, вы должны вызвать метод withoutWrapping на базовом классе Illuminate\Http\Resources\Json\JsonResource. Обычно вы должны вызывать этот метод из вашего AppServiceProvider или другого поставщика услуг, который загружается при каждом запросе к вашему приложению:

<?php
 
namespace App\Providers;
 
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\ServiceProvider;
 
class AppServiceProvider extends ServiceProvider
{
/**
* Регистрирует сервисы приложения.
*/
public function register(): void
{
// ...
}
 
/**
* Запускает любые службы приложения.
*/
public function boot(): void
{
JsonResource::withoutWrapping();
}
}

Внимание Метод withoutWrapping влияет только на внешний ответ и не удаляет ключи data, которые вы вручную добавляете в свои собственные коллекции ресурсов.

Обертывание вложенных ресурсов

У вас есть полная свобода определения того, как оборачиваются отношения вашего ресурса. Если вы хотите, чтобы все коллекции ресурсов оборачивались в ключ data, независимо от их вложенности, вы должны определить класс коллекции ресурсов для каждого ресурса и возвращать коллекцию внутри ключа data.

Возможно, вы задаетесь вопросом, не приведет ли это к тому, что ваш самый внешний ресурс будет упакован в два ключа data. Не волнуйтесь, Laravel никогда не позволит случайно дважды обернуть ваши ресурсы, так что вам не нужно беспокоиться о уровне вложенности коллекции ресурсов, которую вы преобразуете:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Resources\Json\ResourceCollection;
 
class CommentsCollection extends ResourceCollection
{
/**
* Преобразует коллекцию ресурсов в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return ['data' => $this->collection];
}
}

Обертка данных и пагинация

При возврате пагинированных коллекций через ответ ресурса Laravel будет оборачивать данные вашего ресурса в ключ data, даже если метод withoutWrapping был вызван. Это потому, что ответы с пагинацией всегда содержат ключи meta и links с информацией о состоянии пагинатора:

{
"data": [
{
"id": 1,
"name": "Eladio Schroeder Sr.",
"email": "[email protected]"
},
{
"id": 2,
"name": "Liliana Mayert",
"email": "[email protected]"
}
],
"links":{
"first": "http://example.com/users?page=1",
"last": "http://example.com/users?page=1",
"prev": null,
"next": null
},
"meta":{
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "http://example.com/users",
"per_page": 15,
"to": 10,
"total": 10
}
}

Пагинация

Вы можете передать экземпляр пагинатора Laravel методу collection ресурса или пользовательской коллекции ресурсов:

use App\Http\Resources\UserCollection;
use App\Models\User;
 
Route::get('/users', function () {
return new UserCollection(User::paginate());
});

Ответы с пагинацией всегда содержат ключи meta и links с информацией о состоянии пагинатора:

{
"data": [
{
"id": 1,
"name": "Eladio Schroeder Sr.",
"email": "[email protected]"
},
{
"id": 2,
"name": "Liliana Mayert",
"email": "[email protected]"
}
],
"links":{
"first": "http://example.com/users?page=1",
"last": "http://example.com/users?page=1",
"prev": null,
"next": null
},
"meta":{
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "http://example.com/users",
"per_page": 15,
"to": 10,
"total": 10
}
}

Настройка информации о пагинации

Если вы хотите настроить информацию, включаемую в ключи links или meta ответа с пагинацией, вы можете определить метод paginationInformation в ресурсе. Этот метод будет получать данные $paginated и массив $default с информацией, содержащим ключи links и meta:

/**
* Настраивает информацию о пагинации для ресурса.
*
* @param \Illuminate\Http\Request $request
* @param array $paginated
* @param array $default
* @return array
*/
public function paginationInformation($request, $paginated, $default)
{
$default['links']['custom'] = 'https://example.com';
 
return $default;
}

Условные атрибуты

Иногда вы можете захотеть включить атрибут в ответ ресурса только в том случае, если выполняется определенное условие. Например, вы можете захотеть включить значение только в том случае, если текущий пользователь является "администратором". Laravel предоставляет различные вспомогательные методы, чтобы помочь вам в этой ситуации. Метод when можно использовать для условного добавления атрибута в ответ ресурса:

/**
* Преобразует ресурс в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'secret' => $this->when($request->user()->isAdmin(), 'secret-value'),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}

В этом примере ключ secret будет возвращен в конечном ответе ресурса только в том случае, если метод isAdmin аутентифицированного пользователя возвращает true. Если метод возвращает false, ключ secret будет удален из ответа ресурса перед его отправкой клиенту. Метод when позволяет вам выразительно определять ваши ресурсы, не прибегая к условным операторам при построении массива.

Метод when также принимает замыкание в качестве второго аргумента, что позволяет вам вычислить конечное значение только в том случае, если данное условие истинно:

'secret' => $this->when($request->user()->isAdmin(), function () {
return 'modify_10x/eloquent-resources.return_text_541';
}),

Метод whenHas можно использовать для включения атрибута, если он действительно присутствует в основной модели:

'name' => $this->whenHas('name'),

Кроме того, метод whenNotNull можно использовать для включения атрибута в ответ ресурса, если атрибут не равен null:

'name' => $this->whenNotNull($this->name),

Слияние условных атрибутов

Иногда у вас может быть несколько атрибутов, которые должны включаться в ответ ресурса только при выполнении одного и того же условия. В этом случае вы можете использовать метод mergeWhen, чтобы включать атрибуты в ответ только при условии, что заданное условие истинно:

/**
* Преобразует ресурс в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
$this->mergeWhen($request->user()->isAdmin(), [
'first-secret' => 'value',
'second-secret' => 'value',
]),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}

Опять же, если заданное условие ложно, эти атрибуты будут удалены из ответа ресурса перед отправкой его клиенту.

Внимание Метод mergeWhen не следует использовать внутри массивов, в которых смешиваются строковые и числовые ключи. Кроме того, его не следует использовать внутри массивов с числовыми ключами, которые не упорядочены последовательно.

Условные отношения

Помимо условной загрузки атрибутов, вы можете условно включать отношения в ответах на ваши ресурсы, основываясь на том, было ли отношение загружено на модель. Это позволяет вашему контроллеру решать, какие отношения следует загружать на модель, и ваш ресурс может легко включать их только тогда, когда они действительно были загружены. В конечном итоге это облегчает избегание проблем с "N+1" запросами в ваших ресурсах.

Метод whenLoaded можно использовать для условной загрузки отношения. Чтобы избежать ненужной загрузки отношений, этот метод принимает имя отношения вместо самого отношения:

use App\Http\Resources\PostResource;
 
/**
* Преобразует ресурс в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'posts' => PostResource::collection($this->whenLoaded('posts')),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}

В этом примере, если отношение не было загружено, ключ posts будет удален из ответа ресурса перед отправкой его клиенту.

Условные счетчики отношений

Помимо условного включения отношений, вы можете условно включать счетчики отношений в ответах на ваши ресурсы, основываясь на том, было ли количество отношений загружено на модель:

new UserResource($user->loadCount('posts'));

Метод whenCounted можно использовать для условного включения счетчика отношений в ответ ресурса. Этот метод избегает ненужного включения атрибута, если счетчик отношений отсутствует:

/**
* Преобразует ресурс в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'posts_count' => $this->whenCounted('posts'),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}

В этом примере, если количество отношений posts не было загружено, ключ posts_count будет удален из ответа ресурса перед отправкой его клиенту.

Другие типы агрегаций, такие как avg, sum, min и max, также могут быть условно загружены с использованием метода whenAggregated:

'words_avg' => $this->whenAggregated('posts', 'words', 'avg'),
'words_sum' => $this->whenAggregated('posts', 'words', 'sum'),
'words_min' => $this->whenAggregated('posts', 'words', 'min'),
'words_max' => $this->whenAggregated('posts', 'words', 'max'),

Условная информация о связи через pivot

Помимо условного включения информации об отношениях в ваши ответы ресурсов, вы можете условно включать данные из промежуточных таблиц многие ко многим с использованием метода whenPivotLoaded. Метод whenPivotLoaded принимает имя таблицы связи в качестве первого аргумента. Вторым аргументом должно быть замыкание, которое возвращает значение, которое следует возвращать, если информация о связи доступна на модели:

/**
* Преобразует ресурс в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'expires_at' => $this->whenPivotLoaded('role_user', function () {
return $this->pivot->expires_at;
}),
];
}

Если ваше отношение использует свою модель промежуточной таблицы, вы можете передать экземпляр модели промежуточной таблицы в качестве первого аргумента методу whenPivotLoaded:

'expires_at' => $this->whenPivotLoaded(new Membership, function () {
return $this->pivot->expires_at;
}),

Если ваша промежуточная таблица использует метод доступа, отличный от pivot, вы можете использовать метод whenPivotLoadedAs:

/**
* Преобразует ресурс в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'expires_at' => $this->whenPivotLoadedAs('subscription', 'role_user', function () {
return $this->subscription->expires_at;
}),
];
}

Добавление метаданных

Некоторые стандарты JSON API требуют добавления метаданных к вашим ответам на ресурсы и коллекции ресурсов. Это часто включает в себя такие вещи, как links к ресурсу или связанным ресурсам, или метаданные о самом ресурсе. Если вам нужно вернуть дополнительные метаданные о ресурсе, включите их в ваш метод toArray. Например, вы можете включить информацию о link при преобразовании коллекции ресурсов:

/**
* Преобразует ресурс в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'data' => $this->collection,
'links' => [
'self' => 'link-value',
],
];
}

Возвращая дополнительные метаданные из ваших ресурсов, вам никогда не придется беспокоиться о том, что вы случайно перезапишете ключи links или meta, которые автоматически добавляются Laravel при возврате пагинированных ответов. Любые дополнительные links, которые вы определите, будут объединены с ссылками, предоставленными пагинатором.

Метаданные верхнего уровня

Иногда вам может потребоваться включить определенные метаданные только в ответ ресурса, если ресурс является внешним ресурсом, который возвращается. Обычно это включает в себя метаинформацию об ответе в целом. Чтобы определить эти метаданные, добавьте метод with в свой класс ресурса. Этот метод должен возвращать массив метаданных, которые следует включать в ответ ресурса только в том случае, если ресурс является внешним ресурсом, который преобразуется:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\Resources\Json\ResourceCollection;
 
class UserCollection extends ResourceCollection
{
/**
* Преобразует коллекцию ресурсов в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
}
 
/**
* Получает дополнительные данные, которые следует вернуть вместе с массивом ресурсов.
*
* @return array<string, mixed>
*/
public function with(Request $request): array
{
return [
'meta' => [
'key' => 'value',
],
];
}
}

Добавление метаданных при создании ресурсов

Вы также можете добавлять данные верхнего уровня при создании экземпляров ресурсов в вашем маршруте или контроллере. Метод additional, доступный для всех ресурсов, принимает массив данных, которые должны быть добавлены в ответ ресурса:

return (new UserCollection(User::all()->load('roles')))
->additional(['meta' => [
'key' => 'value',
]]);

Ответы ресурсов

Как вы уже читали, ресурсы могут быть возвращены напрямую из маршрутов и контроллеров:

use App\Http\Resources\UserResource;
use App\Models\User;
 
Route::get('/user/{id}', function (string $id) {
return new UserResource(User::findOrFail($id));
});

Однако иногда вам может потребоваться настроить исходящий HTTP-ответ перед его отправкой клиенту. Есть два способа сделать это. Во-первых, вы можете цеплять метод response к ресурсу. Этот метод вернет экземпляр Illuminate\Http\JsonResponse, предоставляя полный контроль над заголовками ответа:

use App\Http\Resources\UserResource;
use App\Models\User;
 
Route::get('/user', function () {
return (new UserResource(User::find(1)))
->response()
->header('X-Value', 'True');
});

В качестве альтернативы, вы можете определить метод withResponse внутри самого ресурса. Этот метод будет вызван, когда ресурс возвращается в качестве внешнего ресурса в ответе:

<?php
 
namespace App\Http\Resources;
 
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
 
class UserResource extends JsonResource
{
/**
* Преобразует ресурс в массив.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
];
}
 
/**
* Настраивает исходящий ответ для ресурса.
*/
public function withResponse(Request $request, JsonResponse $response): void
{
$response->header('X-Value', 'True');
}
}