ascetic-soft/rowcast
Lightweight PDO DataMapper for PHP 8.4+ that maps DB rows to DTOs and back via reflection. Supports auto or explicit mappings, type conversion, and a fluent query builder with dialect-aware UPSERT.
Installation
composer require ascetic-soft/rowcast
Add to config/app.php under providers:
AsceticSoft\Rowcast\RowcastServiceProvider::class,
Basic Usage
Register a cast in AppServiceProvider:
use AsceticSoft\Rowcast\Rowcast;
public function boot()
{
Rowcast::macro('toArray', function ($value) {
return json_decode($value, true);
});
}
First Use Case Cast a JSON string to an array in a model attribute:
use AsceticSoft\Rowcast\Rowcast;
class Post extends Model
{
protected $casts = [
'metadata' => Rowcast::toArray,
];
}
Dynamic Casting Useful for API responses or database fields:
Rowcast::macro('toDateTime', function ($value) {
return Carbon::parse($value);
});
Model Integration
Apply casts in App\Models\Model for global reuse:
class Model extends \Illuminate\Database\Eloquent\Model
{
protected $casts = [
'created_at' => Rowcast::toDateTime,
'updated_at' => Rowcast::toDateTime,
];
}
API Request Handling Cast incoming request data:
use AsceticSoft\Rowcast\Rowcast;
$request->merge([
'tags' => Rowcast::toArray($request->tags),
]);
Illuminate\Support\Collection for batch casting:
Collection::macro('cast', function ($macro) {
return $this->map(fn ($item) => Rowcast::macro($macro, $item));
});
handle():
$validated = $this->validate();
$validated['config'] = Rowcast::toArray($validated['config']);
Macro Overrides
Avoid naming conflicts with Laravel’s built-in casts (e.g., toArray).
Fix: Use unique prefixes (e.g., rowcast_toArray).
Null Handling
Uncasted null values may break type checks.
Fix: Add null checks in macros:
Rowcast::macro('toArray', function ($value) {
return $value ? json_decode($value, true) : [];
});
Performance
Heavy casting in loops (e.g., Model::all()) can slow queries.
Fix: Use selectRaw or cast in application logic.
dd(Rowcast::getMacros());
try-catch for graceful failures:
Rowcast::macro('toDateTime', function ($value) {
try {
return Carbon::parse($value);
} catch (\Exception $e) {
Log::error("Rowcast failed: {$e->getMessage()}");
return null;
}
});
Custom Cast Classes For reusable logic, create a trait:
trait Castable
{
public static function castToArray($value) { ... }
}
Then use:
Rowcast::macro('toArray', [Castable::class, 'castToArray']);
Database-Level Casting
Combine with Laravel’s $attributes for raw SQL casting:
protected $attributes = [
'metadata' => '{}', // Default empty array
];
Testing Mock macros in PHPUnit:
Rowcast::macro('toArray', fn ($x) => ['test']);
$this->assertEquals(['test'], Rowcast::macro('toArray', '{}'));
How can I help you explore Laravel packages today?