mellivora / laravel-api-caster
Convert API response results to Entity objects like Laravel Eloquent. Supports PHP 8.3+ and Laravel 10+.
Fund package maintenance!
zhouyl
Installs: 48
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/mellivora/laravel-api-caster
Requires
- php: ^8.3|^8.4
- brick/math: ^0.10|^0.11|^0.12
- illuminate/contracts: ^10.0|^11.0|^12.0
- illuminate/http: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- nesbot/carbon: ^2.0|^3.0
- psr/http-message: ^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- guzzlehttp/psr7: ^2.0
- phpstan/extension-installer: *
- phpstan/phpstan: ^1.0|^2.0
- phpstan/phpstan-strict-rules: *
- phpunit/phpunit: ^10.5|^11.0
- rector/rector: ^1.0|^2.0
README
Convert API response results to Entity objects like Laravel Eloquent. This package provides a powerful and flexible way to transform API responses into structured, type-safe entities with support for casting, mapping, and data transformation.
Features
- ๐ Laravel Eloquent-like API - Familiar syntax for Laravel developers
- ๐ Automatic Type Casting - Built-in support for common data types
- ๐ฏ Custom Casters - Create your own casting logic
- ๐ฆ Entity Mapping - Map nested data to Entity objects
- ๐ง Flexible Configuration - Includes, excludes, renames, and more
- ๐งช Fully Tested - Comprehensive test suite with 100% coverage
- โก High Performance - Optimized for speed and memory efficiency
- ๐ Type Safe - Full PHP 8.3+ type declarations
Requirements
- PHP 8.3 or 8.4
- Laravel 10.x, 11.x, or 12.x
Installation
You can install the package via composer:
composer require mellivora/laravel-api-caster
Quick Start
Basic Usage
use Mellivora\Http\Api\Entity; use Mellivora\Http\Api\Response; // From HTTP Response $response = new Response($httpResponse); $entity = Entity::from($response); // From array data $entity = new Entity([ 'id' => 123, 'name' => 'John Doe', 'email' => 'john@example.com' ]); // Access data echo $entity->id; // 123 echo $entity->name; // John Doe echo $entity->email; // john@example.com
Collections
// Create collection from response $collection = Entity::collectionResponse($response); // Create collection from array $collection = Entity::collection([ ['id' => 1, 'name' => 'User 1'], ['id' => 2, 'name' => 'User 2'], ]); foreach ($collection as $entity) { echo $entity->name; }
Advanced Usage
Type Casting
class UserEntity extends Entity { protected array $casts = [ 'id' => 'int', 'email_verified_at' => 'datetime', 'settings' => 'json', 'score' => 'decimal:2', 'status' => UserStatusEnum::class, ]; } $user = new UserEntity([ 'id' => '123', 'email_verified_at' => '2023-01-01 12:00:00', 'settings' => '{"theme": "dark"}', 'score' => '95.75', 'status' => 'active', ]); // Automatically casted $user->id; // int(123) $user->email_verified_at; // Carbon instance $user->settings; // array ['theme' => 'dark'] $user->score; // string '95.75' $user->status; // UserStatusEnum::ACTIVE
Entity Mapping
class ProductEntity extends Entity { protected array $mappings = [ 'category' => CategoryEntity::class, 'tags[]' => TagEntity::class, ]; } $product = new ProductEntity([ 'id' => 1, 'name' => 'Laptop', 'category' => ['id' => 1, 'name' => 'Electronics'], 'tags' => [ ['id' => 1, 'name' => 'Tech'], ['id' => 2, 'name' => 'Gadget'], ], ]); $product->category; // CategoryEntity instance $product->tags; // Collection of TagEntity instances $product->tags->first(); // TagEntity instance
Field Configuration
class UserEntity extends Entity { // Include only specific fields protected array $includes = ['id', 'name', 'email']; // Exclude specific fields protected array $excludes = ['password', 'secret']; // Rename fields protected array $renames = [ 'user_id' => 'id', 'full_name' => 'name', ]; // Append computed attributes protected array $appends = ['display_name']; public function getDisplayNameAttribute(): string { return $this->name . ' (' . $this->email . ')'; } }
Custom Casters
use Mellivora\Http\Api\Contracts\Castable; use Mellivora\Http\Api\Contracts\CastsAttributes; class MoneyCaster implements Castable { public static function castUsing(array $arguments): CastsAttributes { return new class implements CastsAttributes { public function getCastValue(Entity $entity, string $key, $value): Money { return new Money($value); } public function fromCastValue(Entity $entity, string $key, mixed $value): int { return $value->getCents(); } }; } } class OrderEntity extends Entity { protected array $casts = [ 'total' => MoneyCaster::class, ]; }
Available Cast Types
Type | Description | Example |
---|---|---|
int , integer |
Cast to integer | '123' โ 123 |
float , double , real |
Cast to float | '12.34' โ 12.34 |
string |
Cast to string | 123 โ '123' |
bool , boolean |
Cast to boolean | 1 โ true |
array |
Cast JSON to array | '[1,2,3]' โ [1,2,3] |
json |
Alias for array | Same as array |
object |
Cast JSON to object | '{"a":1}' โ stdClass |
collection |
Cast to Collection | [1,2,3] โ Collection |
date |
Cast to Carbon date | '2023-01-01' โ Carbon |
datetime |
Cast to Carbon datetime | '2023-01-01 12:00:00' โ Carbon |
timestamp |
Cast timestamp to Carbon | 1672574400 โ Carbon |
decimal:2 |
Cast to decimal string | 12.345 โ '12.35' |
date:Y-m-d |
Custom date format | Custom format |
datetime:Y-m-d H:i |
Custom datetime format | Custom format |
Testing
composer test
Code Quality
# Run all quality checks composer quality # Fix code style composer phpcs-fix # Run static analysis composer phpstan # Run rector composer rector-fix
API Documentation
Entity Class
Methods
__construct(iterable $attributes = [], array $meta = [])
- Create new entityfrom(Response $response): static
- Create from Response objectcollection(iterable $items, array $meta = []): Collection
- Create collectioncollectionResponse(Response $response): Collection
- Create collection from ResponsetoArray(): array
- Convert to arraytoJson(int $options = 0): string
- Convert to JSONkeys(): array
- Get all keysvalues(): array
- Get all valuesisEmpty(): bool
- Check if emptycopy(): static
- Create a copymeta(string $key = null, mixed $default = null): mixed
- Get meta dataorigin(string $key = null, mixed $default = null): mixed
- Get original data
Response Class
Methods
__construct(HttpResponse|MessageInterface $response)
- Create new responsecode(): int
- Get response codemessage(): string
- Get response messagedata(string $key = null, mixed $default = null): mixed
- Get response datameta(string $key = null, mixed $default = null): mixed
- Get response metatoArray(): array
- Convert to array
Caster Class
Methods
cast(string $cast, mixed $value): mixed
- Cast valuevalue(string $cast, mixed $value): mixed
- Get original value
Best Practices
- Use Type Hints: Always define proper types in your entity classes
- Leverage Caching: Cache frequently used entities to improve performance
- Validate Data: Use Laravel's validation before creating entities
- Handle Nulls: Always consider null values in your casting logic
- Test Thoroughly: Write tests for your custom entities and casters
Performance Tips
- Use
includes
to limit processed fields - Avoid deep nesting when possible
- Cache entity instances for repeated use
- Use collections for bulk operations
Troubleshooting
Common Issues
Issue: "Class not found" error when using custom casters
Solution: Ensure your caster class implements the Castable
interface
Issue: Infinite recursion with circular references
Solution: Use excludes
to break circular references
Issue: Memory issues with large datasets Solution: Process data in chunks using collections
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.