public function hasFactories( array|string|null $factoryFiles = null, string $directory = '../database/factories',): static
Added in 2.4.0. Like seeders, factories are publish-only.
$packager ->name('Blog') ->hasFactories();
php artisan vendor:publish --tag=blog::factories
Files land flat in database/factories/, which is where the application's Database\Factories
namespace resolves:
database/factories/BlogPostFactory.php
Why there is no "load factories" option
Laravel removed loadFactoriesFrom() in version 8, when factories became classes resolved by
convention rather than files scanned from a directory. There is no framework hook left for a package
to say "my factories live here" — so the toolkit does not pretend to offer one.
If you want your factories usable without the consumer publishing them, point at them from the model, which is the mechanism Laravel does still provide:
namespace Acme\Blog\Models; use Acme\Blog\Database\Factories\PostFactory;use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model; class Post extends Model{ use HasFactory; protected static function newFactory(): PostFactory { return PostFactory::new(); } }
namespace Acme\Blog\Database\Factories; use Acme\Blog\Models\Post;use Illuminate\Database\Eloquent\Factories\Factory; class PostFactory extends Factory{ protected $model = Post::class; public function definition(): array { return [ 'title' => $this->faker->sentence(), 'slug' => $this->faker->unique()->slug(), 'body' => $this->faker->paragraphs(3, true), 'published_at' => null, ]; } public function published(): static { return $this->state(fn () => ['published_at' => now()]); }}
Now Post::factory()->published()->create() works in the consumer's tests with nothing published,
because the factory lives under your PSR-4 prefix and the model resolves it directly.
The two approaches answer different questions, and a package can do both:
hasFactories() |
newFactory() |
|
|---|---|---|
| Consumer must publish | yes | no |
| Consumer can edit the definition | yes | only by extending |
| Namespace | Database\Factories |
your own |
| Useful for | seeding demo data, a starting point to customise | tests against your models |
Writing a publishable factory
A factory intended for publishing declares the application's namespace:
namespace Database\Factories; use Acme\Blog\Models\Post;use Illuminate\Database\Eloquent\Factories\Factory; class BlogPostFactory extends Factory{ protected $model = Post::class; public function definition(): array { return [ 'title' => fake()->sentence(), 'slug' => fake()->unique()->slug(), 'body' => fake()->paragraphs(4, true), 'published_at' => fake()->boolean(70) ? fake()->dateTimeThisYear() : null, ]; }}
Prefix the class name. database/factories/ belongs to the application, and PostFactory is a name
somebody else will want.
Naming specific files
$packager->hasFactories('BlogPostFactory.php');$packager->hasFactories(['BlogPostFactory.php', 'BlogCommentFactory.php']);$packager->hasFactories(directory: '../database/factory-stubs');
In the install command
use NyonCode\LaravelPackageToolkit\Commands\InstallCommand; $packager->hasInstallCommand(function (InstallCommand $command) { $command ->publishMigrations() ->publishFactories() ->publishSeeders();});
Factories are usually only wanted in development, which the installer can express:
$packager->hasInstallCommand(function (InstallCommand $command) { $command ->publishConfig() ->publishMigrations() ->publishForLocal('factories', 'seeders'); });
Introspection
$packager->isFactorable(); // bool$packager->factoryFiles(); // Support\SplFileInfo[]