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));
}

#[ResponseData(UserData::class, collection: true, wrapped: false)]

// config/skiexx-data-scramble.php
return [
    'auto_register' => false,  // Отключаем авторегистрацию
];

// 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;
    }
}

// config/skiexx-data-scramble.php
return [
    'auto_register' => false,
];

// AppServiceProvider.php
Scramble::registerExtension(CustomDataExtension::class);

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'));
yaml
members:
  type: array
  items:
    $ref: '#/components/schemas/UserData'
yaml
responses:
  200:
    content:
      application/json:
        schema:
          type: array
          items:
            $ref: '#/components/schemas/UserData'