PHP code example of bit-mx / data-entities

1. Go to this page and download the library: Download bit-mx/data-entities 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/ */

    

bit-mx / data-entities example snippets


use BitMx\DataEntities\Executers\MySqlQueryExecutor;
use BitMx\DataEntities\Executers\SqlServerQueryExecutor;

return [
    'database' => env('DATA_ENTITIES_CONNECTION', 'sqlsrv'),

    'executers' => [
        'sqlsrv' => SqlServerQueryExecutor::class,
        'mysql' => MySqlQueryExecutor::class,
    ],
];

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;

class GetAllPostsDataEntity extends DataEntity
{
    public function __construct(
        protected int $authorId,
    ) {
    }

    #[\Override]
    public function resolveStoreProcedure(): string
    {
        return 'spListAllPost';
    }

    #[\Override]
    protected function defaultParameters(): array
    {
        return [
            'author_id' => $this->authorId,
        ];
    }
}

public function author_id', 'status'];
}

use App\DataEntities\GetAllPostsDataEntity;

$dataEntity = new GetAllPostsDataEntity(1);

$dataEntity->parameters()->add('tag', 'laravel');

namespace App\DataEntities;

use BitMx\DataEntities\Attributes\SingleItemResponse;
use BitMx\DataEntities\DataEntity;

#[SingleItemResponse]
class GetPostDataEntity extends DataEntity
{
    public function __construct(
        protected int $postId,
    ) {
    }

    #[\Override]
    public function resolveStoreProcedure(): string
    {
        return 'spListPost';
    }

    #[\Override]
    protected function defaultParameters(): array
    {
        return [
            'post_id' => $this->postId,
        ];
    }
}

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;

class GetAllPostsDataEntity extends DataEntity
{
    // ...

    #[\Override]
    public function resolveDatabaseConnection(): string|\Illuminate\Database\Connection
    {
        return 'sqlsrv';
    }
}

namespace App\DataEntities\Erp;

use BitMx\DataEntities\DataEntity;

abstract class ErpDataEntity extends DataEntity
{
    #[\Override]
    public function resolveDatabaseConnection(): string|\Illuminate\Database\Connection
    {
        return 'erp_sqlsrv';
    }
}

class GetCustomerDataEntity extends ErpDataEntity
{
    public function resolveStoreProcedure(): string
    {
        return 'dbo.spGetCustomer';
    }
}

namespace App\DataEntities\Crm;

use BitMx\DataEntities\DataEntity;

abstract class CrmDataEntity extends DataEntity
{
    #[\Override]
    public function resolveDatabaseConnection(): string|\Illuminate\Database\Connection
    {
        return 'crm_mysql';
    }
}

use Illuminate\Database\Connection;
use Illuminate\Support\Facades\DB;

#[\Override]
public function resolveDatabaseConnection(): string|Connection
{
    return DB::build([
        'driver' => 'sqlsrv',
        'host' => $this->host,
        'port' => $this->port,
        'database' => $this->database,
        'username' => $this->username,
        'password' => $this->password,
    ]);
}

use Illuminate\Support\Facades\DB;

(new GetCustomerDataEntity($id))
    ->onConnection(DB::build([
        'driver' => 'mysql',
        'host' => $host,
        'database' => $database,
        'username' => $user,
        'password' => $password,
    ]))
    ->execute();

(new GetCustomerDataEntity($id))
    ->onConnection('tenant_mysql') // connection name from config/database.php
    ->execute();

public function queryTimeout(): ?int
{
    return 30;
}

use BitMx\DataEntities\DataEntity;
use Illuminate\Support\Facades\DB;

DB::connection('sqlsrv')->transaction(function () {
    (new CreateOrderDataEntity($payload))->execute();
    (new ReserveInventoryDataEntity($orderId))->execute();
});

DataEntity::transaction(function () {
    (new CreateOrderDataEntity($payload))->execute();
    (new ReserveInventoryDataEntity($orderId))->execute();
}, connection: 'sqlsrv');

DataEntity::transaction(function () {
    (new CreateOrderDataEntity($payload))->execute();
}, connection: $dynamicConnection);

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Executers\MySqlQueryExecutor;

class GetAllPostsDataEntity extends DataEntity
{
    // ...

    #[\Override]
    public function resolveQueryExecutor(): ?string
    {
        return MySqlQueryExecutor::class;
    }
}

use App\DataEntityExecuters\PostgresQueryExecutor;

return [
    // ...

    'executers' => [
        'sqlsrv' => SqlServerQueryExecutor::class,
        'mysql' => MySqlQueryExecutor::class,
        'pgsql' => PostgresQueryExecutor::class,
    ],
];

use App\DataEntities\GetAllPostsDataEntity;

$dataEntity = new GetAllPostsDataEntity(1);

$response = $dataEntity->execute();

$data = $response->data();

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;

class CreatePostDataEntity extends DataEntity
{
    public function __construct(
        protected string $title,
    ) {
    }

    #[\Override]
    public function resolveStoreProcedure(): string
    {
        return 'spCreatePost';
    }

    #[\Override]
    protected function defaultParameters(): array
    {
        return [
            'title' => $this->title,
        ];
    }

    #[\Override]
    protected function defaultOutputParameters(): array
    {
        return [
            'new_id' => 'INT',
        ];
    }
}

use App\DataEntities\CreatePostDataEntity;

$dataEntity = new CreatePostDataEntity('Hello world');

$response = $dataEntity->execute();

$newId = $response->output('new_id');

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;
use Carbon\Carbon;

class GetAllPostsDataEntity extends DataEntity
{
    // ...

    #[\Override]
    protected function defaultParameters(): array
    {
        return [
            'date' => Carbon::now(),
        ];
    }

    /**
     * @return array<string, string>
     */
    #[\Override]
    protected function mutators(): array
    {
        return [
            'date' => 'datetime:Y-m-d H:i',
        ];
    }
}

namespace App\DataEntityMutators;

use BitMx\DataEntities\Contracts\Mutable;

class CustomMutator implements Mutable
{
    /**
     * {@inheritDoc}
     */
    public function transform(string $key, mixed $value, array $parameters): mixed
    {
        //
    }
}

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;

class GetAllPostsDataEntity extends DataEntity
{
    // ...

    /**
     * @return array<string, string>
     */
    #[\Override]
    protected function accessors(): array
    {
        return [
            'contact_id' => 'integer',
        ];
    }
}

namespace App\DataEntityAccessors;

use BitMx\DataEntities\Contracts\Accessable;

class CustomAccessor implements Accessable
{
    /**
     * {@inheritDoc}
     */
    public function get(string $key, mixed $value, array $data): mixed
    {
        //
    }
}

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;

class GetAllPostsDataEntity extends DataEntity
{
    // ...

    /**
     * @return array<string, string>
     */
    #[\Override]
    protected function alias(): array
    {
        return [
            'post_title' => 'title',
            'post_body' => 'content',
        ];
    }
}

$data = $response->data();

$data = $response->data('key');

$data = $response->data('key', 'default value');

$data = $response->rawData();
$data = $response->rawData('key', 'default value');

$output = $response->output();
$newId = $response->output('new_id');

$response->addData('key', 'value');

$response->addData(['key' => 'value']);

$response->mergeData(['key' => 'value']);

$data = $response->object();

$data = $response->collect();

if ($response->isEmpty()) {
    // no rows
}

if ($response->isNotEmpty()) {
    // has rows
}

if ($response->success()) {
    // The stored procedure was executed successfully
} else {
    // There was an error executing the stored procedure
}

if ($response->failed()) {
    // There was an error executing the stored procedure
} else {
    // The stored procedure was executed successfully
}

$response->throw();

$message = $response->getError();

$response->isCached();

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\PendingQuery;

class GetAllPostsDataEntity extends DataEntity
{
    // ...

    #[\Override]
    public function boot(PendingQuery $pendingQuery): void
    {
        $pendingQuery->parameters()->add('tag', 'laravel');
    }
}

trait Taggable
{
    public function bootTaggable(PendingQuery $pendingQuery): void
    {
        $pendingQuery->parameters()->add('tag', 'laravel');
    }
}

use BitMx\DataEntities\Events\DataEntityExecuted;
use BitMx\DataEntities\Events\DataEntityFailed;
use Illuminate\Support\Facades\Event;

Event::listen(DataEntityExecuted::class, function (DataEntityExecuted $event) {
    logger()->info('data-entity.executed', [
        'entity' => $event->dataEntity::class,
        'duration_ms' => $event->durationMs,
    ]);
});

Event::listen(DataEntityFailed::class, function (DataEntityFailed $event) {
    logger()->warning('data-entity.failed', [
        'entity' => $event->dataEntity::class,
        'error' => $event->exception->getMessage(),
    ]);
});

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\PendingQuery;
use BitMx\DataEntities\Responses\Response;

class GetAllPostsDataEntity extends DataEntity
{
    // ...

    #[\Override]
    public function boot(PendingQuery $pendingQuery): void
    {
        $pendingQuery->middleware()->onQuery(function (PendingQuery $pendingQuery) {
            $pendingQuery->parameters()->add('tag', 'laravel');
        });

        $pendingQuery->middleware()->onResponse(function (Response $response) {
            $response->addData('tag', 'laravel');

            return $response;
        });
    }
}

use BitMx\DataEntities\Contracts\QueryMiddleware;
use BitMx\DataEntities\PendingQuery;

class PageMiddleware implements QueryMiddleware
{
    public function __invoke(PendingQuery $pendingQuery): PendingQuery
    {
        $pendingQuery->parameters()->add('page', 1);

        return $pendingQuery;
    }
}

use BitMx\DataEntities\Contracts\ResponseMiddleware;
use BitMx\DataEntities\Responses\Response;

class TagMiddleware implements ResponseMiddleware
{
    public function __invoke(Response $response): Response
    {
        $response->addData('tag', 'laravel');

        return $response;
    }
}

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\PendingQuery;

class GetAllPostsDataEntity extends DataEntity
{
    // ...

    #[\Override]
    public function boot(PendingQuery $pendingQuery): void
    {
        $pendingQuery->middleware()->onQuery(new PageMiddleware());

        $pendingQuery->middleware()->onResponse(new TagMiddleware());
    }
}

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Plugins\AlwaysThrowOnError;

class GetAllPostsDataEntity extends DataEntity
{
    use AlwaysThrowOnError;

    // ...
}

namespace App\DataEntities;

use BitMx\DataEntities\Contracts\Cacheable;
use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Plugins\HasCache;

class GetAllPostsDataEntity extends DataEntity implements Cacheable
{
    use HasCache;

    // ...

    public function cacheExpiresAt(): \DateTimeInterface
    {
        return now()->addMinutes(10);
    }
}

use App\DataEntities\GetPostDataEntity;

$dataEntity = new GetPostDataEntity(1);

$dataEntity->invalidateCache();
$response = $dataEntity->execute();

use App\DataEntities\GetPostDataEntity;

$dataEntity = new GetPostDataEntity(1);

$dataEntity->disableCaching();
$response = $dataEntity->execute();

$dataEntity->clearCache();

use App\DataEntities\GetPostDataEntity;

$dataEntity = new GetPostDataEntity(1);
$response = $dataEntity->execute();

$response->isCached();

namespace App\DataEntities;

use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Plugins\HasRetries;
use Carbon\CarbonInterval;

class GetAllPostsDataEntity extends DataEntity
{
    use HasRetries;

    protected function maxRetryAttempts(): int
    {
        return 3;
    }

    protected function retryBackoff(): int|CarbonInterval
    {
        return CarbonInterval::milliseconds(50);
        // or: return 50; // milliseconds
    }
}

namespace App\DataEntities;

use BitMx\DataEntities\Attributes\UseLazyQuery;
use BitMx\DataEntities\DataEntity;

#[UseLazyQuery]
class GetAllPostsDataEntity extends DataEntity
{
    public function resolveStoreProcedure(): string
    {
        return 'spListAllPost';
    }
}

use App\DataEntities\GetAllPostsDataEntity;

$dataEntity = new GetAllPostsDataEntity();
$response = $dataEntity->execute();

$posts = $response->lazy();

$count = $posts->count(); // first full pass; rows are now remembered
$titles = $posts->pluck('title'); // second pass; uses remembered rows (no extra DB round-trip)

foreach ($response->stream() as $post) {
    // process one row at a time without keeping the full result set in memory
}

// Wrong: second foreach fails
$stream = $response->stream();
foreach ($stream as $post) { /* ... */ }
foreach ($stream as $post) { /* RuntimeException */ }

// Right (moderate sets, multiple passes): use lazy() up front
foreach ($response->lazy() as $post) { /* first pass */ }
foreach ($response->lazy() as $post) { /* second pass; remembered */ }

// Right (large sets, need another pass): re-execute
$response = $dataEntity->execute();
foreach ($response->stream() as $post) { /* ... */ }

'mysql' => [
    // ...
    'options' => [
        PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false,
    ],
],

namespace App\Data;

class PostData
{
    public function __construct(
        public int $id,
        public string $title,
        public string $content,
    ) {
    }
}

namespace App\DataEntities;

use App\Data\PostData;
use BitMx\DataEntities\Attributes\MapTo;
use BitMx\DataEntities\Attributes\SingleItemResponse;
use BitMx\DataEntities\DataEntity;

#[SingleItemResponse]
#[MapTo(PostData::class)]
class GetPostDataEntity extends DataEntity
{
    public function __construct(protected int $postId) {}

    public function resolveStoreProcedure(): string
    {
        return 'spListPost';
    }

    protected function defaultParameters(): array
    {
        return ['post_id' => $this->postId];
    }
}

/** @var PostData $post */
$post = (new GetPostDataEntity(1))->execute()->dto();

namespace App\DataEntities;

use App\Data\PostData;
use BitMx\DataEntities\Attributes\MapTo;
use BitMx\DataEntities\DataEntity;
use Illuminate\Support\Collection;

#[MapTo(PostData::class, Collection::class)]
class GetPostsDataEntity extends DataEntity
{
    public function resolveStoreProcedure(): string
    {
        return 'spListPosts';
    }
}

/** @var Collection<int, PostData> $posts */
$posts = (new GetPostsDataEntity())->execute()->dto();

$posts->each(fn (PostData $post) => /* ... */);

namespace App\DataEntities;

use App\Data\PostData;
use BitMx\DataEntities\Attributes\SingleItemResponse;
use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Responses\Response;

#[SingleItemResponse]
class GetPostDataEntity extends DataEntity
{
    public function __construct(protected int $postId) {}

    public function resolveStoreProcedure(): string
    {
        return 'spListPost';
    }

    protected function defaultParameters(): array
    {
        return ['post_id' => $this->postId];
    }

    public function createDtoFromResponse(Response $response): PostData
    {
        $data = $response->data();

        return new PostData(
            id: $data['id'],
            title: $data['title'],
            content: $data['content'],
        );
    }
}

/** @var PostData $post */
$post = (new GetPostDataEntity(1))->execute()->dto();

use App\DataEntities\GetPostDataEntity;

$dataEntity = new GetPostDataEntity(1);

$dataEntity->dd();

$dataEntity->ddRaw();

use App\DataEntities\GetPostDataEntity;
use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Responses\MockResponse;

it('should get the post', function () {
    DataEntity::fake([
        GetPostDataEntity::class => MockResponse::make([
            'id' => 1,
            'title' => 'Post title',
            'content' => 'Post content',
        ]),
    ]);

    $dataEntity = new GetPostDataEntity(1);

    $response = $dataEntity->execute();

    $post = $response->dto();

    expect($post->id)->toBe(1);
    expect($post->title)->toBe('Post title');
    expect($post->content)->toBe('Post content');

    DataEntity::assertExecutedOnce(GetPostDataEntity::class);
    expect(DataEntity::recorded(GetPostDataEntity::class))->toHaveCount(1);
});

afterEach(fn () => DataEntity::resetMock());

use BitMx\DataEntities\Responses\MockResponse;

MockResponse::make(['title' => 'New post'])->withOutput(['p_new_id' => 42]);
MockResponse::make(['title' => 'New post'], ['p_new_id' => 42]);
MockResponse::empty();
MockResponse::make()->withException(new RuntimeException('boom'));
// or
MockResponse::makeWithException(new RuntimeException('boom'));

use App\DataEntities\GetPostDataEntity;
use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Responses\MockResponse;
use BitMx\DataEntities\Testing\RecordedExecution;

it('should get the post', function () {
    DataEntity::fake([
        GetPostDataEntity::class => MockResponse::make([
            'id' => 1,
            'title' => 'Post title',
            'content' => 'Post content',
        ]),
    ]);

    $dataEntity = new GetPostDataEntity(1);

    $response = $dataEntity->execute();

    DataEntity::assertExecuted(GetPostDataEntity::class);
});

DataEntity::assertExecutedWith(GetPostDataEntity::class, ['post_id' => 1]);
DataEntity::assertExecutedWith(GetPostDataEntity::class, fn (array $parameters) => $parameters['post_id'] > 0);
DataEntity::assertExecutedWith(
    GetPostDataEntity::class,
    fn (RecordedExecution $execution) => $execution->procedure === 'sp_get_post',
);
DataEntity::assertNothingExecuted();
DataEntity::assertTotalExecutedCount(1);
DataEntity::assertExecutedInOrder([GetPostDataEntity::class, OtherDataEntity::class]);

use BitMx\DataEntities\PendingQuery;
use BitMx\DataEntities\Responses\MockResponse;
use BitMx\DataEntities\Responses\MockResponseSequence;

DataEntity::fake([
    GetPostDataEntity::class => fn (PendingQuery $query) => MockResponse::make([
        'id' => $query->parameters()->get('post_id'),
    ]),
]);

DataEntity::fake([
    GetPostDataEntity::class => MockResponseSequence::make(
        MockResponse::make(['id' => 1]),
        MockResponse::make(['id' => 2]),
    )->whenEmpty(MockResponse::make(['id' => 0])),
]);

DataEntity::fake([
    GetPostDataEntity::class => MockResponse::make(['id' => 1]),
]);

DataEntity::mock([
    OtherDataEntity::class => MockResponse::empty(),
]);

DataEntity::fallback(MockResponse::make(['fallback' => true]));

namespace Tests\DataEntityFactories;

use BitMx\DataEntities\Factories\DataEntityFactory;

class PostDataEntityFactory extends DataEntityFactory
{
    /**
     * {@inheritDoc}
     */
    public function definition(): array
    {
        return [
            'id' => $this->faker->unique()->randomNumber(),
            'title' => $this->faker->sentence(),
            'content' => $this->faker->paragraph(),
        ];
    }
}

use App\DataEntities\GetPostDataEntity;
use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Responses\MockResponse;
use Tests\DataEntityFactories\PostDataEntityFactory;

it('should get the post', function () {
    DataEntity::fake([
        GetPostDataEntity::class => MockResponse::make(PostDataEntityFactory::new()),
    ]);

    $dataEntity = new GetPostDataEntity(1);

    $response = $dataEntity->execute();

    $post = $response->data();

    expect($post)->toHaveKeys(['id', 'title', 'content']);
});

use App\DataEntities\GetPostDataEntity;
use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Responses\MockResponse;
use Tests\DataEntityFactories\PostDataEntityFactory;

it('should get the post', function () {
    DataEntity::fake([
        GetPostDataEntity::class => MockResponse::make(PostDataEntityFactory::new()->create()),
    ]);

    $dataEntity = new GetPostDataEntity(1);

    $response = $dataEntity->execute();

    expect($response->data())->toHaveKeys(['id', 'title', 'content']);
});

use App\DataEntities\GetPostDataEntity;
use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Responses\MockResponse;
use Tests\DataEntityFactories\PostDataEntityFactory;

it('should get a collection of posts', function () {
    DataEntity::fake([
        GetPostDataEntity::class => MockResponse::make(
            PostDataEntityFactory::new()->count(10)->asCollection()
        ),
    ]);

    $dataEntity = new GetPostDataEntity(1);

    $response = $dataEntity->execute();

    expect($response->data())->toHaveCount(10);
});

use App\DataEntities\GetPostDataEntity;
use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Responses\MockResponse;
use Tests\DataEntityFactories\PostDataEntityFactory;

it('should get the post', function () {
    DataEntity::fake([
        GetPostDataEntity::class => MockResponse::make(
            PostDataEntityFactory::new()->state([
                'title' => 'Custom title',
            ])
        ),
    ]);

    $dataEntity = new GetPostDataEntity(1);

    $response = $dataEntity->execute();

    expect($response->data('title'))->toBe('Custom title');
});

namespace Tests\DataEntityFactories;

use BitMx\DataEntities\Factories\DataEntityFactory;

class PostDataEntityFactory extends DataEntityFactory
{
    /**
     * {@inheritDoc}
     */
    public function definition(): array
    {
        return [
            'id' => $this->faker->unique()->randomNumber(),
            'title' => $this->faker->sentence(),
            'content' => $this->faker->paragraph(),
        ];
    }

    public function withPublishedDate(): DataEntityFactory
    {
        return $this->state([
            'published_date' => now()->toDateTimeString(),
        ]);
    }
}

use App\DataEntities\GetPostDataEntity;
use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Responses\MockResponse;
use Tests\DataEntityFactories\PostDataEntityFactory;

it('should get the post', function () {
    DataEntity::fake([
        GetPostDataEntity::class => MockResponse::make(
            PostDataEntityFactory::new()->withPublishedDate()
        ),
    ]);

    $dataEntity = new GetPostDataEntity(1);

    $response = $dataEntity->execute();

    expect($response->data())->toHaveKey('published_date');
});

use App\DataEntities\GetPostDataEntity;
use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Plugins\AlwaysThrowOnError;
use BitMx\DataEntities\Responses\MockResponse;

it('should throw when the stored procedure fails', function () {
    DataEntity::fake([
        GetPostDataEntity::class => MockResponse::makeWithException(new \Exception('Error')),
    ]);

    $dataEntity = new class(1) extends GetPostDataEntity
    {
        use AlwaysThrowOnError;
    };

    $dataEntity->execute();
})->throws(\Exception::class, 'Error');

namespace Tests\DataEntityFactories;

use BitMx\DataEntities\Enums\ResponseType;
use BitMx\DataEntities\Factories\DataEntityFactory;

class PostDataEntityFactory extends DataEntityFactory
{
    /**
     * {@inheritDoc}
     */
    public function definition(): array
    {
        return [
            'id' => $this->faker->unique()->randomNumber(),
            'title' => $this->faker->sentence(),
            'content' => $this->faker->paragraph(),
        ];
    }

    public function responseType(): ResponseType
    {
        return ResponseType::COLLECTION;
    }
}

use App\DataEntities\GetPostDataEntity;
use BitMx\DataEntities\DataEntity;
use BitMx\DataEntities\Responses\MockResponse;
use Tests\DataEntityFactories\PostDataEntityFactory;

it('should get a collection of posts', function () {
    DataEntity::fake([
        GetPostDataEntity::class => MockResponse::make(
            PostDataEntityFactory::new()->asCollection()
        ),
    ]);

    $dataEntity = new GetPostDataEntity(1);

    $response = $dataEntity->execute();

    expect($response->data())->toBeArray();
});

namespace App\DataEntities;

use BitMx\DataEntities\Attributes\SingleItemResponse;
use BitMx\DataEntities\DataEntity;

#[SingleItemResponse]
class GetPostDataEntity extends DataEntity
{
    public function __construct(
        protected int $postId,
    ) {
    }

    #[\Override]
    public function resolveStoreProcedure(): string
    {
        return 'spListPost';
    }

    #[\Override]
    protected function defaultParameters(): array
    {
        return [
            'post_id' => $this->postId,
        ];
    }
}



declare(strict_types=1);

use BitMx\DataEntities\Rector\RemoveMethodFromDataEntityRector;
use BitMx\DataEntities\Rector\ResponseTypePropertyToAttributeRector;
use Rector\Config\RectorConfig;

return RectorConfig::configure()
    ->withRules([
        ResponseTypePropertyToAttributeRector::class,
        RemoveMethodFromDataEntityRector::class,
    ])
    ->withImportNames();
bash
php artisan vendor:publish --provider="BitMx\DataEntities\DataEntitiesServiceProvider" --tag="config"
bash
php artisan boost:install
# or later
php artisan boost:update
bash
php artisan make:data-entity GetAllPostsDataEntity
bash
php artisan data-entities:list
php artisan data-entities:check
bash
php artisan make:data-entity-mutator CustomMutator
bash
php artisan make:data-entity-accessor CustomAccessor
bash
php artisan make:data-entity-factory PostDataEntityFactory