minionfactory/raw-hydrator
Raw Hydrator is a small PHP package for turning raw data (arrays/records) into hydrated objects with minimal overhead. Useful for fast mapping of database results or API payloads into DTOs/entities without a full ORM.
Installation
composer require minionfactory/raw-hydrator
Add to config/app.php under providers:
MinionFactory\RawHydrator\RawHydratorServiceProvider::class,
First Use Case Fetch a single model with eager-loaded relations in one query:
use MinionFactory\RawHydrator\Facades\RawHydrator;
$user = RawHydrator::hydrate(
User::class,
'SELECT * FROM users WHERE id = ?',
[1]
);
Where to Look First
RawHydrator (for quick usage).RawHydratorServiceProvider (for binding custom hydrators).MinionFactory\RawHydrator\Contracts\Hydrator (for extending behavior).Basic Hydration
// Single model
$model = RawHydrator::hydrate(
Model::class,
'SELECT * FROM table WHERE id = ?',
[1]
);
// Collection of models
$models = RawHydrator::hydrateCollection(
Model::class,
'SELECT * FROM table WHERE active = ?',
[1]
);
Hydrating with Relations
$user = RawHydrator::hydrate(
User::class,
'SELECT users.*, posts.* FROM users
LEFT JOIN posts ON posts.user_id = users.id
WHERE users.id = ?',
[1],
['posts' => ['posts.*']] // Define relation columns
);
Custom Hydrators Bind a custom hydrator for a model:
RawHydrator::extend('App\Models\CustomModel', function () {
return new class implements Hydrator {
public function hydrate(array $data) {
return new CustomModel($data);
}
};
});
Integration with Query Builder
$query = DB::select('SELECT * FROM users WHERE ...');
$models = RawHydrator::hydrateCollectionFromResults(
User::class,
$query
);
find() or first() operations.hydrateCollection: For bulk operations (e.g., admin dashboards, reports).Column Mismatch Errors
$fillable or $casts, hydration fails.hydrate() with a custom hydrator or adjust your query to match the model’s expected structure.Relation Ambiguity
posts.* and comments.* both include id), hydration may fail.['posts' => ['posts.id as post_id', 'posts.title']]
Transaction Conflicts
retrieved, saved). If you rely on these, wrap in a transaction or manually trigger events:
$model->fireModelEvent('retrieved', false);
Performance Overhead
chunk() or cursor() for pagination:
DB::select('SELECT * FROM large_table')->chunk(100, function ($results) {
RawHydrator::hydrateCollectionFromResults(Model::class, $results);
});
DB::enableQueryLog();
$model = RawHydrator::hydrate(...);
dd(DB::getQueryLog());
$rawData = DB::select('...');
dd($rawData); // Verify structure before hydrating.
hydrateCollectionFromResults for Testing:
Pass raw query results directly to isolate hydration logic from SQL issues.Custom Hydrators
Implement MinionFactory\RawHydrator\Contracts\Hydrator for model-specific logic:
class CustomHydrator implements Hydrator {
public function hydrate(array $data) {
$model = new CustomModel();
$model->setRawAttributes($data);
$model->customLogic();
return $model;
}
}
Relation Resolvers Extend relation handling by binding a custom resolver:
RawHydrator::extendRelationResolver(function ($model, $relation, $columns) {
// Custom logic to resolve relations from $columns
});
Event Hooks Listen for hydration events (via service provider):
RawHydrator::hydrated(function ($model) {
// Post-hydration logic
});
Database-Specific Optimizations Override the default query builder for specific databases (e.g., PostgreSQL JSON fields):
RawHydrator::setQueryBuilder(function () {
return DB::connection('pgsql')->getQueryBuilder();
});
How can I help you explore Laravel packages today?