Skip to content

Instantly share code, notes, and snippets.

@leroy
Created July 25, 2024 13:34
Show Gist options
  • Save leroy/96f25b1cca5d7b501b4c13875931269f to your computer and use it in GitHub Desktop.
Save leroy/96f25b1cca5d7b501b4c13875931269f to your computer and use it in GitHub Desktop.
Make Laravel's eloquent model factories stateful.
<?php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
trait StatefulFactory
{
/**
* Set factory state, which is not persisted to the database.
*
* Factory state is wiped using clearFactoryState() method.
*
* @param array $state
* @return $this
*/
public function factoryState(array $state): static
{
return $this->state(function(array $attributes) use ($state) {
$factoryStateKeys = $attributes['factoryState'] ?? [];
$factoryStateKeys = array_unique(array_merge($factoryStateKeys, array_keys($state)));
return array_merge($attributes, $state, ['factoryState' => $factoryStateKeys]);
});
}
/**
* After creating callback with factory state.
*
* @param callable $callback
* @return $this
*/
public function afterCreatingWithFactoryState(callable $callback): static
{
$factoryState = null;
return $this->afterMaking(function(Model $model) use (&$factoryState) {
$factoryState = Arr::only($model->getAttributes(), $model->factoryState ?? []);
})->afterCreating(function(Model $model) use (&$factoryState, $callback) {
$callback($model, $factoryState);
});
}
/**
* Wipes the factory state before persisting to the database
*/
protected function clearFactoryState()
{
return $this->afterMaking(function(Model $model) {
$factoryStateKeys = $model->factoryState ?? [];
foreach ($factoryStateKeys as $key) {
unset($model->$key);
}
unset($model->factoryState);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment