Generate Bag Value Objects, Collections, and Factories
Bag includes the make:bag
artisan command to make it easy to generate new Bag classes, Factories, and Collections.
Namespaces
The make:bag
command will use the provided namespace to determine the location of the generated classes. You can set the namespace using the --namespace
option or you will be prompted for it. The default namespace is \App\Values
.
Generating Bags
To create a new Bag class, use the make:bag
command:
php artisan make:bag MyBag
This will create a new MyBag
class in app/Values/MyBag.php
:
<?php
declare(strict_types=1);
namespace App\Values;
use Bag\Bag;
readonly class MyBag extends Bag
{
public function __construct() {
}
}
Generating Bag Collections
To create a new Bag Collection class, use the make:bag
command with the --collection
option:
php artisan make:bag MyBag --collection
You can optionally specify the name of the collection class:
php artisan make:bag MyBag --collection=MyBagCollection
If none is specified, it will use prompt you for the collection name, and defaults to the Bag class name with Collection
appended to it.
This will create a new MyBagCollection
class in app/Values/Collections/MyBagCollection.php
.
<?php
declare(strict_types=1);
namespace App\Values\Collections;
use Bag\Collection;
class MyBagCollection extends Collection
{
}
NOTE
When creating a new Bag or when specifying the --update
flag, it will automatically add the Collection
attribute to the Bag class if necessary.
Generating Bag Factories
The make:bag
command can also generate Bag Factory classes, and will automatically generate the definition()
function based on the Bag class properties.
To create a new Bag Factory class, use the make:bag
command with the --factory
option:
php artisan make:bag MyBag --factory
This will create a new MyBagFactory
class in app/Values/Factories/MyBagFactory.php
:
<?php
declare(strict_types=1);
namespace App\Values\Factories;
use Bag\Factory;
class TestFactory extends Factory
{
public function definition(): array
{
return [
];
}
}
TIP
When creating a new Bag or when specifying the --update
flag, it will automatically add the Factory
attribute and HasFactory
trait to the Bag class.
Updating Factories
Once you had added properties to your Bag class, you can update the Factory class using the --update
option:
php artisan make:bag MyBag --factory --docs --update
TIP
If you update the Bag class properties, you can re-run the make:bag
command with the --update
and --force-excluding-bag
options to update the Factory class.
For example, if we update our MyBag
constructor to look like the following:
public function __construct(
public string $name,
public int $age,
#[Cast(DateTime::class, 'y-m-d')]
public CarbonImmutable $birthday,
public Money $money,
public AnotherBag $test,
#[Cast(CollectionOf::class, AnotherBag::class)]
public Collection $collection,
) {
}
The generated factory will look like this:
<?php
declare(strict_types=1);
namespace App\Values\Factories;
use App\Values\AnotherBag;
use Bag\Factory;
use Brick\Money\Money;
use Carbon\CarbonImmutable;
class MyBagFactory extends Factory
{
public function definition(): array
{
return [
'name' => $this->faker->word(),
'age' => $this->faker->randomNumber(),
'birthday' => new CarbonImmutable(),
'money' => Money::ofMinor($this->faker->numberBetween(100, 10000), 'USD'),
'test' => AnotherBag::factory()->make(),
'collection' => AnotherBag::collect([AnotherBag::factory()->make()]),
];
}
}
Documentation/Auto-Complete Helpers
To enable easier use of named/positional arguments when creating a new Bag, you can use the --docs
option to automatically generate it for the Bag, this will add an @method
annotation to the Bag class to provide auto-complete for the ::from()
method:
php artisan make:bag MyBag --docs
This will add the following to the MyBag
class:
/**
* @method static static from(array $data)
*/
Updating Documentation
Similar to Factories, you can update the documentation using the --update
option:
php artisan make:bag MyBag --docs --update
This will update the @method
annotation to include documentation for all defined Value attributes. For example, given the following bag:
use App\Values\Collections\ReportCollection;
use App\Values\Report;
use App\Values\Team;
use Carbon\CarbonImmutable;
readonly class User extends Bag {
public function __construct(
public string $name,
public int $age,
public Team $team,
#[Cast(CollectionOf::class, Report::class)]
public ReportCollection $reports,
public CarbonImmutable $lastLogin,
) {
}
}
The @method
annotation will added to the User
class:
use App\Values\Collections\ReportCollection;
use App\Values\Report;
use App\Values\Team;
use Carbon\CarbonImmutable;
/**
* @method static static from(string $name, int $age, Team $team, ReportCollection<Report> $reports, CarbonImmutable $lastLogin)
*/
readonly class User extends Bag {
public function __construct(
public string $name,
public int $age,
public Team $team,
#[Cast(CollectionOf::class, Report::class)]
public ReportCollection $reports,
public CarbonImmutable $lastLogin,
) {
}
}
Expected Usage
Because the factory is based on the Bag class properties, you will typically create and customize the Bag value object, and then create the factory and add docs. To do this, you would follow these steps:
- Create the Bag class (optionally, with a collection):
php artisan make:bag MyBag --collection
Customize the Bag class
Create the Bag Factory and docs:
php artisan make:bag MyBag --factory --docs --update
If you have already created the factory, you must add the --force-except-bag
option to overwrite it:
php artisan make:bag MyBag --factory --docs --update --force-except-bag
WARNING
If you use the --force
option instead of --force-except-bag
it will overwrite your customized Bag Value class, losing any customizations.
The make:bag
Command
The make:bag
command has the following options:
Description:
Create a new Bag value class, with optional factory and collection.
Usage:
make:bag [options] [--] <name>
Arguments:
name
Options:
-F, --force Force overwriting all files
-E, --force-except-bag Force overwriting Factory/Collection files
-u, --update Update Bag class to add factory/collection
-f, --factory[=FACTORY] Create a Factory for the Bag [default: "interactive"]
-c, --collection[=COLLECTION] Create a Collection for the Bag [default: "interactive"]
-d, --docs Add Bag::from() docs to the Bag for IDE auto-complete
-N, --namespace[=NAMESPACE] Specify the namespace for the Bag
--pretend Dump the file contents instead of writing to disk
-h, --help Display help for the given command. When no command is given display help for the list command
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
--env[=ENV] The environment the command should run under
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug