zero-to-prod/data-model
Reflection-based PHP data models that hydrate typed objects from arrays with a single from($data) call. Use #[Describe] attributes to define casting, validation, defaults, nullable/required rules, and assignments—keeping mapping logic predictable, readable, and verifiable.
DataModel classes for queries/updates.DataModel and validating payloads at boundaries.array_key_exists failures) with compile-time checks via PHP attributes.validate() calls, custom if checks) into declarative Describe attributes.if-else hydration logic into modular, testable DataModel classes.strval(), intval()) with optimized cast hooks.Describe attributes (via DataModelHelper or custom scripts).Adopt when:
isset($data['x']) ? $obj->x = $data['x'] : ...).pre/post hooks) reduces risk of missed edge cases in scattered logic.Illuminate\Support\Collection or FormRequest validation classes.Look elsewhere if:
DataModel’s via attribute can’t handle."This package lets us write data transformation logic once and reuse it everywhere—cutting dev time by 30%+ and slashing bugs from manual mapping. For example:
null values or type mismatches.#[Describe(['required' => true])] clearly marks mandatory fields).DataModel attributes.
It’s like Laravel’s Eloquent for data transformation—but for any class, any layer."ROI:
Describe attributes."This is a drop-in replacement for manual DTO hydration that gives you:
array_key_exists or isset checks—PHP’s type system + Describe attributes handle it.if checks (e.g., in controllers, services) into declarative attributes on your model.User::from(['address' => [...]]) → Address object).pre/post hooks or cast methods without subclassing.// Before (manual)
$user = new User();
$user->name = $data['name'] ?? '';
$user->age = (int)($data['age'] ?? 0);
if (!filter_var($data['email'] ?? '', FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException('Invalid email');
}
$user->email = $data['email'] ?? '';
// After (DataModel)
class User {
use \Zerotoprod\DataModel\DataModel;
#[Describe(['required' => true])] public string $name;
#[Describe(['cast' => 'intval'])] public int $age;
#[Describe(['cast' => [self::class, 'validateEmail']])] public string $email;
}
$user = User::from($data); // Done.
Migration Path:
DataModelHelper to batch-convert existing classes.DataModel-validated DTOs for cleaner controllers.Trade-offs:
How can I help you explore Laravel packages today?