PHP code example of skiexx / laravel-data-scramble
1. Go to this page and download the library: Download skiexx/laravel-data-scramble library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
skiexx / laravel-data-scramble example snippets
use App\Data\UserData;
use App\Data\CreateUserData;
class UserController
{
public function index(): UserData
{
return UserData::from(User::first());
}
public function store(CreateUserData $data): UserData
{
$user = User::create($data->toArray());
return UserData::from($user);
}
}
use Spatie\LaravelData\Data;
use Spatie\LaravelData\Attributes\Validation\Email;
use Spatie\LaravelData\Attributes\Validation\Min;
use Spatie\LaravelData\Attributes\Validation\Max;
class CreateUserData extends Data
{
public function __construct(
#[Min(2), Max(255)]
public string $name,
#[Email]
public string $email,
#[Min(8)]
public string $password,
public ?string $phone,
) {
}
}
// config/skiexx-data-scramble.php
return [
// Автоматическая регистрация расширения в Scramble.
// Установите false, если хотите зарегистрировать вручную.
'auto_register' => true,
// Пропускать свойства с атрибутом #[Hidden].
'skip_hidden' => true,
// Lazy-свойства считаются необязательными (не попадают в
enum Status: string
{
case Active = 'active';
case Inactive = 'inactive';
}
class UserData extends Data
{
public function __construct(
public string $name,
public Status $status,
) {
}
}
class AddressData extends Data
{
public function __construct(
public string $city,
public string $street,
) {
}
}
class UserData extends Data
{
public function __construct(
public string $name,
public AddressData $address,
) {
}
}
class TeamData extends Data
{
/**
* @param UserData[] $members
*/
public function __construct(
public string $name,
#[DataCollectionOf(UserData::class)]
public array $members,
) {
}
}
use Spatie\LaravelData\Attributes\MapOutputName;
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
#[MapOutputName(SnakeCaseMapper::class)]
class UserProfileData extends Data
{
public function __construct(
public string $firstName, // -> first_name
public string $lastName, // -> last_name
public int $userAge, // -> user_age
) {
}
}
use Spatie\LaravelData\Attributes\MapOutputName;
use Spatie\LaravelData\Attributes\MapInputName;
class OrderData extends Data
{
public function __construct(
#[MapInputName('order_id')]
public string $orderId,
#[MapOutputName('total_amount')]
public float $totalAmount,
) {
}
}
class Data extends \Spatie\LaravelData\Data
{
public function __construct(
public ?string $name, // nullable: true, не в
class Data extends \Spatie\LaravelData\Data
{
public function __construct(
public string $status = 'active', // не в
use Spatie\LaravelData\Attributes\Hidden;
class Data extends \Spatie\LaravelData\Data
{
public function __construct(
public string $name,
#[Hidden]
public string $internalToken, // полностью исключено из схемы
) {
}
}
use Spatie\LaravelData\Attributes\Computed;
class UserData extends \Spatie\LaravelData\Data
{
#[Computed]
public string $fullName;
public function __construct(
public string $firstName,
public string $lastName,
) {
$this->fullName = "$firstName $lastName";
}
}
use Spatie\LaravelData\Lazy;
class UserData extends \Spatie\LaravelData\Data
{
public function __construct(
public string $name,
public Lazy|AddressData $address, // не в
use Skiexx\LaravelDataScramble\Contracts\OpenApiSchema;
class ExternalPaymentResponse implements OpenApiSchema
{
public function __construct(
public string $transactionId,
public float $amount,
public string $currency,
) {
}
public static function openApiSchema(): array
{
return [
'type' => 'object',
'properties' => [
'transaction_id' => [
'type' => 'string',
'format' => 'uuid',
'description' => 'Уникальный идентификатор транзакции',
],
'amount' => [
'type' => 'number',
'format' => 'double',
'description' => 'Сумма платежа',
],
'currency' => [
'type' => 'string',
'enum' => ['USD', 'EUR', 'RUB'],
],
],
'
use Spatie\LaravelData\Data;
use Skiexx\LaravelDataScramble\Contracts\OpenApiSchema;
use Skiexx\LaravelDataScramble\Traits\HasOpenApiSchema;
class UserData extends Data implements OpenApiSchema
{
use HasOpenApiSchema;
public function __construct(
public string $name,
public string $email,
) {
}
}
use Skiexx\LaravelDataScramble\Contracts\OpenApiSchema;
use Skiexx\LaravelDataScramble\Traits\Formats\UuidFormat;
class UserId implements OpenApiSchema
{
use UuidFormat;
public function __construct(
public readonly string $value,
) {
}
public static function openApiSchema(): array
{
return static::openApiType();
}
}
use Spatie\LaravelData\Data;
use Spatie\LaravelData\Attributes\FromRouteParameter;
use Spatie\LaravelData\Attributes\Validation\Min;
use Spatie\LaravelData\Attributes\Validation\Max;
class GetUsersData extends Data
{
public function __construct(
#[Min(1), Max(100)]
public int $page,
public ?string $search,
public int $perPage = 15,
) {
}
}
class UserController
{
// GET /api/users?page=1&search=john&perPage=15
public function index(GetUsersData $data): JsonResource
{
return JsonResource::collection(User::paginate($data->perPage));
}
}
class CreateUserData extends Data
{
public function __construct(
#[Min(2), Max(255)]
public string $name,
#[Email]
public string $email,
) {
}
}
class UserController
{
// POST /api/users — body: { "name": "...", "email": "..." }
public function store(CreateUserData $data): JsonResource
{
return new JsonResource(User::create($data->toArray()));
}
}
use Spatie\LaravelData\Attributes\FromRouteParameter;
class UpdateUserData extends Data
{
public function __construct(
#[FromRouteParameter('user')]
public int $userId,
#[Min(2), Max(255)]
public string $name,
#[Email]
public string $email,
) {
}
}
class UserController
{
// PUT /api/users/{user}
public function update(UpdateUserData $data): JsonResource
{
// $data->userId автоматически берется из route param {user}
return new JsonResource(User::findOrFail($data->userId)->update($data->toArray()));
}
}
use Spatie\LaravelData\Attributes\FromRouteParameterProperty;
class OrderData extends Data
{
public function __construct(
#[FromRouteParameterProperty('user', property: 'id')]
public int $userId,
public string $product,
) {
}
}
use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
#[MapInputName(SnakeCaseMapper::class)]
class FilterData extends Data
{
public function __construct(
public string $firstName, // query param: first_name
public string $lastName, // query param: last_name
) {
}
}
class UserController
{
// Scramble видит JsonResource, но не знает что внутри UserData
public function show(string $id): JsonResource
{
return new JsonResource($action->execute($id));
}
public function index(): JsonResource
{
return JsonResource::collection($action->execute());
}
}
use Skiexx\LaravelDataScramble\Attributes\ResponseData;
class UserController
{
#[ResponseData(UserData::class)]
public function show(string $id): JsonResource
{
return new JsonResource($action->execute($id));
}
#[ResponseData(UserData::class, collection: true)]
public function index(): JsonResource
{
return JsonResource::collection($action->execute());
}
}
#[ResponseData(UserData::class)]
public function show(string $id): JsonResource
{
return new JsonResource($action->execute($id));
}
#[ResponseData(UserData::class, collection: true)]
public function index(): JsonResource
{
return JsonResource::collection($action->execute());
}
#[ResponseData(UserData::class, paginated: true)]
public function index(): JsonResource
{
return JsonResource::collection($action->execute());
}
#[ResponseData(UserData::class, cursorPaginated: true)]
public function index(): JsonResource
{
return JsonResource::collection($action->execute());
}
#[ResponseData(UserData::class, status: 201)]
public function store(CreateUserData $data): JsonResource
{
return new JsonResource($action->execute($data));
}
#[ResponseData(UserData::class, wrapped: false)]
public function show(string $id): JsonResource
{
return new JsonResource($action->execute($id));
}
// AppServiceProvider.php или другой провайдер
use Dedoc\Scramble\Scramble;
use Skiexx\LaravelDataScramble\Extensions\LaravelDataTypeToSchemaExtension;
public function boot(): void
{
// Регистрация для конкретного API
Scramble::registerExtension(LaravelDataTypeToSchemaExtension::class);
}
use Skiexx\LaravelDataScramble\Extensions\LaravelDataTypeToSchemaExtension;
use Dedoc\Scramble\Support\Generator\Types\Type as OpenApiType;
use Dedoc\Scramble\Support\Type\Type;
use Dedoc\Scramble\Support\Type\ObjectType;
class CustomDataExtension extends LaravelDataTypeToSchemaExtension
{
public function shouldHandle(Type $type): bool
{
// Обрабатывать только классы из определенного namespace
if ($type instanceof ObjectType && str_starts_with($type->name, 'App\\Data\\')) {
return parent::shouldHandle($type);
}
return false;
}
public function toSchema(Type $type): OpenApiType
{
/** @var ObjectType $type */
$schema = parent::toSchema($type);
// Добавить описание ко всем схемам
$schema->setDescription("Автогенерированная схема для {$type->name}");
return $schema;
}
}
use Skiexx\LaravelDataScramble\Support\ValidationAttributeMap;
use Dedoc\Scramble\Support\Generator\Types\Type as OpenApiType;
use Spatie\LaravelData\Attributes\Validation\ValidationAttribute;
// В вашем расширении или сервис-провайдере
class ExtendedValidationMap extends ValidationAttributeMap
{
public static function apply(ValidationAttribute $attribute, OpenApiType $type): void
{
// Сначала применяем стандартные маппинги
parent::apply($attribute, $type);
// Добавляем кастомную обработку
if ($attribute instanceof YourCustomAttribute) {
$type->format('your-custom-format');
}
}
}
use Skiexx\LaravelDataScramble\Resolvers\DataClassSchemaResolver;
use Dedoc\Scramble\Support\Generator\Types\ObjectType as OpenApiObjectType;
class CustomSchemaResolver extends DataClassSchemaResolver
{
// Переопределите нужные методы
}
class CustomDataExtension extends TypeToSchemaExtension
{
public function toSchema(Type $type): OpenApiType
{
$resolver = new CustomSchemaResolver($this->components);
return $resolver->resolve($type->name);
}
}
use Dedoc\Scramble\Scramble;
use Skiexx\LaravelDataScramble\Extensions\LaravelDataTypeToSchemaExtension;
// Расширение регистрируется глобально для всех API
Scramble::registerExtension(LaravelDataTypeToSchemaExtension::class);
// Настройка конкретного API
Scramble::configure('v2')
->routes(fn (Route $route) => str_starts_with($route->uri, 'api/v2'));