Package Data | |
---|---|
Maintainer Username: | makeabledk |
Package Create Date: | 2018-04-30 |
Package Last Update: | 2024-09-27 |
Home Page: | |
Language: | PHP |
License: | CC-BY-SA-4.0 |
Last Refreshed: | 2025-02-02 03:17:14 |
Package Statistics | |
---|---|
Total Downloads: | 103,132 |
Monthly Downloads: | 474 |
Daily Downloads: | 1 |
Total Stars: | 181 |
Total Watchers: | 6 |
Total Forks: | 7 |
Total Open Issues: | 0 |
Bring the magic of eloquent relationships into the Laravel Factory.
Traditionally if you wanted to factory a team with some users, you'd have to manually create the individual team and users and then tie them together afterwards. This can easily lead to very verbose tests.
Before
$team = factory(Team::class)->create();
$user = factory(User::class)->create();
$member = factory(TeamMember::class)->create([
'team_id' => $team,
'user_id' => $user,
]);
After
$team = factory(Team::class)->with(1, 'users')->create();
How about 10 teams each with 3 users?
$team = factory(Team::class)->with(3, 'users')->times(10)->create();
You may install the package via composer
composer require makeabledk/laravel-factory-enhanced
Installing on Laravel 5.5+ will automatically load the package service provider.
Once the package is installed, you may use the factory()
helper exactly as you normally would. Only now you have additional functionality at your disposal.
If you're not familiar with Laravel factories, please refer to the official documentation: https://laravel.com/docs/master/database-testing
You may use the enhanced factory to create any additional relationships defined on the model.
Example: A Server
model with a sites()
relationship (has-many)
factory(Server::class)->with(3, 'sites')->create();
Note that you may still use any native functionality that you are used to, such as states and attributes:
factory(Server::class)->states('online')->with(3, 'sites')->create([
'name' => 'production-1'
]);
You are free to specify multiple relationships on the same factory.
Given our previous Server
model has another relationship called team
(belongs-to), you may do:
factory(Server::class)
->with('team')
->with(3, 'sites')
->create();
Now you would have 1 team
that has 1 server
which has 3 sites
.
Moving on to the more advanced use-cases, you may also do nested relationships.
For instance we could rewrite our example from before using nesting:
factory(Team::class)
->with(3, 'servers.sites')
->create();
Please note that the count '3' applies to the final relationship, in this case sites
.
If you are wanting 2 servers each of which has 3 sites, you may write it as following:
factory(Team::class)
->with(2, 'servers')
->with(3, 'servers.sites')
->create();
Just as you may specify pre-defined states on the factoring model (see official documentation), you may also apply the very same states on the relation.
factory(Team::class)
->with(2, 'online', 'servers')
->create();
You may finding yourself wanting a relationship in multiple states. In this case you may use the andWith()
method.
factory(Team::class)
->with(2, 'online', 'servers')
->andWith(1, 'offline', 'servers')
->create();
By using the andWith
we will create a 'clean cut', so that no further calls to with
can interfere with relations specified prior to the andWith
.
In the above example any further nesting of relations will apply to the 'offline' server.
factory(Team::class)
->with(2, 'online', 'servers')
->andWith(1, 'offline', 'servers')
->with(3, 'servers.sites')
->create();
The above example will create 1x team that has
In addition to passing count and state directly into the with
function, you may also pass a closure that will receive the FactoryBuilder
instance directly.
factory(Team::class)
->with('servers', function (FactoryBuilder $servers) {
$servers
->times(2)
->states('active')
})
->create();
You may also nest further relationships in the builder should you wish to.
One advantage by using closures, is that it will be evaluated each time the factory-model (in this case a server
) is created.
This is especially handy if you'd like some random relations in your DevelopmentSeeder
.
factory(Team::class)
->with('servers', function (FactoryBuilder $servers) {
$servers
->times(random_int(1, 5))
->states(array_random(['online', 'offline']))
})
->create();
For seeding an entire development environment it can be useful with random relations. Here we may utilize the 'odds' helper.
Consider the following example from a real-life project:
$courses = Collection::times(5)->map(function () {
return factory(Course::class)
->with(random_int(1, 5), 'chapters')
->with(random_int(1, 5), 'chapters.videos')
->odds('66%', function ($course) { // 66% of courses will be translated. 'Odds' also accepts decimals, ie 2/3
$course
->with(1, 'danish', 'translations')
->with(random_int(1, 5), 'translations.chapters')
->with(random_int(1, 5), 'danish', 'translations.chapters.videos')
})
});
});
With a few lines of code we have seeded several models in several random states. Pretty neat!
Traditionally trying to use factory()
on a model with no defined model-factory would throw an exception. Not anymore!
After installing this package, you are completely free to use factory()
on any Eloquent model, whether or not you have defined a model factory.
If need be, you may pass attributes inline through the with
method or use the fill
helper.
Passing attributes inline
factory(Server::class)->with(1, 'sites', ['name' => 'example.org'])->create();
Using the fill
method
factory(Server::class)->with(1, 'sites', function (FactoryBuilder $sites) {
$sites->fill(function (Faker $faker) {
return [
'name' => $faker->name,
];
});
})->create();
These are the provided methods on the FactoryBuilder
instance in addition to the core methods.
This package swaps the native factory implementation with it's own implementation.
While the public API is aimed to be 100% compatible with the native one, some differences may occur. In that case we're happy to hear from you.
Please see CHANGELOG for more information what has changed recently.
You can run the tests with:
composer test
We are happy to receive pull requests for additional functionality. Please see CONTRIBUTING for details.
Attribution-ShareAlike 4.0 International. Please see License File for more information.