This commit is contained in:
2026-05-01 23:40:14 +08:00
commit b8f599a617
3867 changed files with 478663 additions and 0 deletions
@@ -0,0 +1,19 @@
<?php
namespace Illuminate\Database\Eloquent\Factories\Attributes;
use Attribute;
#[Attribute(Attribute::TARGET_CLASS)]
class UseModel
{
/**
* Create a new attribute instance.
*
* @param string $class
*/
public function __construct(public string $class)
{
//
}
}
@@ -0,0 +1,81 @@
<?php
namespace Illuminate\Database\Eloquent\Factories;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
class BelongsToManyRelationship
{
/**
* The related factory instance.
*
* @var \Illuminate\Database\Eloquent\Factories\Factory|\Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array
*/
protected $factory;
/**
* The pivot attributes / attribute resolver.
*
* @var callable|array
*/
protected $pivot;
/**
* The relationship name.
*
* @var string
*/
protected $relationship;
/**
* Create a new attached relationship definition.
*
* @param \Illuminate\Database\Eloquent\Factories\Factory|\Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array $factory
* @param callable|array $pivot
* @param string $relationship
*/
public function __construct($factory, $pivot, $relationship)
{
$this->factory = $factory;
$this->pivot = $pivot;
$this->relationship = $relationship;
}
/**
* Create the attached relationship for the given model.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function createFor(Model $model)
{
$factoryInstance = $this->factory instanceof Factory;
if ($factoryInstance) {
$relationship = $model->{$this->relationship}();
}
Collection::wrap($factoryInstance ? $this->factory->prependState($relationship->getQuery()->pendingAttributes)->create([], $model) : $this->factory)->each(function ($attachable) use ($model) {
$model->{$this->relationship}()->attach(
$attachable,
is_callable($this->pivot) ? call_user_func($this->pivot, $model) : $this->pivot
);
});
}
/**
* Specify the model instances to always use when creating relationships.
*
* @param \Illuminate\Support\Collection $recycle
* @return $this
*/
public function recycle($recycle)
{
if ($this->factory instanceof Factory) {
$this->factory = $this->factory->recycle($recycle);
}
return $this;
}
}
@@ -0,0 +1,96 @@
<?php
namespace Illuminate\Database\Eloquent\Factories;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class BelongsToRelationship
{
/**
* The related factory instance.
*
* @var \Illuminate\Database\Eloquent\Factories\Factory|\Illuminate\Database\Eloquent\Model
*/
protected $factory;
/**
* The relationship name.
*
* @var string
*/
protected $relationship;
/**
* The cached, resolved parent instance ID.
*
* @var mixed
*/
protected $resolved;
/**
* Create a new "belongs to" relationship definition.
*
* @param \Illuminate\Database\Eloquent\Factories\Factory|\Illuminate\Database\Eloquent\Model $factory
* @param string $relationship
*/
public function __construct($factory, $relationship)
{
$this->factory = $factory;
$this->relationship = $relationship;
}
/**
* Get the parent model attributes and resolvers for the given child model.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return array
*/
public function attributesFor(Model $model)
{
$relationship = $model->{$this->relationship}();
return $relationship instanceof MorphTo ? [
$relationship->getMorphType() => $this->factory instanceof Factory ? $this->factory->newModel()->getMorphClass() : $this->factory->getMorphClass(),
$relationship->getForeignKeyName() => $this->resolver($relationship->getOwnerKeyName()),
] : [
$relationship->getForeignKeyName() => $this->resolver($relationship->getOwnerKeyName()),
];
}
/**
* Get the deferred resolver for this relationship's parent ID.
*
* @param string|null $key
* @return \Closure
*/
protected function resolver($key)
{
return function () use ($key) {
if (! $this->resolved) {
$instance = $this->factory instanceof Factory
? ($this->factory->getRandomRecycledModel($this->factory->modelName()) ?? $this->factory->create())
: $this->factory;
return $this->resolved = $key ? $instance->{$key} : $instance->getKey();
}
return $this->resolved;
};
}
/**
* Specify the model instances to always use when creating relationships.
*
* @param \Illuminate\Support\Collection $recycle
* @return $this
*/
public function recycle($recycle)
{
if ($this->factory instanceof Factory) {
$this->factory = $this->factory->recycle($recycle);
}
return $this;
}
}
@@ -0,0 +1,25 @@
<?php
namespace Illuminate\Database\Eloquent\Factories;
use Illuminate\Support\Arr;
class CrossJoinSequence extends Sequence
{
/**
* Create a new cross join sequence instance.
*
* @param array ...$sequences
*/
public function __construct(...$sequences)
{
$crossJoined = array_map(
function ($a) {
return array_merge(...$a);
},
Arr::crossJoin(...$sequences),
);
parent::__construct(...$crossJoined);
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,62 @@
<?php
namespace Illuminate\Database\Eloquent\Factories;
use Illuminate\Database\Eloquent\Attributes\UseFactory;
/**
* @template TFactory of \Illuminate\Database\Eloquent\Factories\Factory
*/
trait HasFactory
{
/**
* Get a new factory instance for the model.
*
* @param (callable(array<string, mixed>, static|null): array<string, mixed>)|array<string, mixed>|int|null $count
* @param (callable(array<string, mixed>, static|null): array<string, mixed>)|array<string, mixed> $state
* @return TFactory
*/
public static function factory($count = null, $state = [])
{
$factory = static::newFactory() ?? Factory::factoryForModel(static::class);
return $factory
->count(is_numeric($count) ? $count : null)
->state(is_callable($count) || is_array($count) ? $count : $state);
}
/**
* Create a new factory instance for the model.
*
* @return TFactory|null
*/
protected static function newFactory()
{
if (isset(static::$factory)) {
return static::$factory::new();
}
return static::getUseFactoryAttribute() ?? null;
}
/**
* Get the factory from the UseFactory class attribute.
*
* @return TFactory|null
*/
protected static function getUseFactoryAttribute()
{
$attributes = (new \ReflectionClass(static::class))
->getAttributes(UseFactory::class);
if ($attributes !== []) {
$useFactory = $attributes[0]->newInstance();
$factory = $useFactory->factoryClass::new();
$factory->guessModelNamesUsing(fn () => static::class);
return $factory;
}
}
}
@@ -0,0 +1,76 @@
<?php
namespace Illuminate\Database\Eloquent\Factories;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
use Illuminate\Database\Eloquent\Relations\MorphOneOrMany;
class Relationship
{
/**
* The related factory instance.
*
* @var \Illuminate\Database\Eloquent\Factories\Factory
*/
protected $factory;
/**
* The relationship name.
*
* @var string
*/
protected $relationship;
/**
* Create a new child relationship instance.
*
* @param \Illuminate\Database\Eloquent\Factories\Factory $factory
* @param string $relationship
*/
public function __construct(Factory $factory, $relationship)
{
$this->factory = $factory;
$this->relationship = $relationship;
}
/**
* Create the child relationship for the given parent model.
*
* @param \Illuminate\Database\Eloquent\Model $parent
* @return void
*/
public function createFor(Model $parent)
{
$relationship = $parent->{$this->relationship}();
if ($relationship instanceof MorphOneOrMany) {
$this->factory->state([
$relationship->getMorphType() => $relationship->getMorphClass(),
$relationship->getForeignKeyName() => $relationship->getParentKey(),
])->prependState($relationship->getQuery()->pendingAttributes)->create([], $parent);
} elseif ($relationship instanceof HasOneOrMany) {
$this->factory->state([
$relationship->getForeignKeyName() => $relationship->getParentKey(),
])->prependState($relationship->getQuery()->pendingAttributes)->create([], $parent);
} elseif ($relationship instanceof BelongsToMany) {
$relationship->attach(
$this->factory->prependState($relationship->getQuery()->pendingAttributes)->create([], $parent)
);
}
}
/**
* Specify the model instances to always use when creating relationships.
*
* @param \Illuminate\Support\Collection $recycle
* @return $this
*/
public function recycle($recycle)
{
$this->factory = $this->factory->recycle($recycle);
return $this;
}
}
@@ -0,0 +1,64 @@
<?php
namespace Illuminate\Database\Eloquent\Factories;
use Countable;
class Sequence implements Countable
{
/**
* The sequence of return values.
*
* @var array
*/
protected $sequence;
/**
* The count of the sequence items.
*
* @var int
*/
public $count;
/**
* The current index of the sequence iteration.
*
* @var int
*/
public $index = 0;
/**
* Create a new sequence instance.
*
* @param mixed ...$sequence
*/
public function __construct(...$sequence)
{
$this->sequence = $sequence;
$this->count = count($sequence);
}
/**
* Get the current count of the sequence items.
*
* @return int
*/
public function count(): int
{
return $this->count;
}
/**
* Get the next value in the sequence.
*
* @param array<string, mixed> $attributes
* @param \Illuminate\Database\Eloquent\Model|null $parent
* @return mixed
*/
public function __invoke($attributes = [], $parent = null)
{
return tap(value($this->sequence[$this->index % $this->count], $this, $attributes, $parent), function () {
$this->index = $this->index + 1;
});
}
}