mf1dd/object-builder
Composer 安装命令:
composer require mf1dd/object-builder
包简介
Automatically creates fully populated PHP object instances with random, type-safe values. Designed for test fixtures and runtime object generation. Supports all PHP class types — regular classes, readonly classes, abstract classes, enums, traits, interfaces, and built-in stock classes like DateInter
README 文档
README
Automatic object creation with random values for PHP 8.2+.
Why?
Manually creating test objects is repetitive, error-prone, and time-consuming — especially for deeply nested object graphs with dozens of properties. Every constructor change forces you to update all test fixtures.
ObjectBuilder solves this: class name in, fully populated instance out. Recursive, type-safe, with semantically meaningful values.
Advantages
- No boilerplate —
ObjectBuilder::init(Foo::class)->build()instead of manualnew Foo(...)with 10 parameters - Type-safe — reflection-based, supports all native and custom types including enums, interfaces, traits, abstract, and readonly classes
- Deep object graphs — nested dependencies are resolved
automatically and recursively (
Person → Address → Street) - Semantic values — detects property names (
email,timezone,firstname) and generates matching random values - Constraints — value ranges and formats via the
with()API:->with('age', ['min' => 18, 'max' => 65]) - Overridable — set specific properties to fixed values while keeping the rest random
- Extensible — custom type builders and stock class handlers can be registered, builders are swappable
- No framework — pure PHP library, zero external runtime
dependencies except
nikic/php-parser
Compatibility
| PHP Version | Status |
|---|---|
| 8.2 | Fully supported, CI-tested |
| 8.3 | Fully supported, CI-tested |
| 8.4 | Fully supported, CI-tested |
| 8.5 | CI-tested (once available) |
- Runtime dependency:
nikic/php-parser ^5.0 - No framework (Symfony, Laravel, etc.) required
- Package name:
mf1dd/object-builder
Basic Usage
Simple classes are automatically populated with random values.
class Address { public function __construct( private readonly mixed $street, private readonly string|int $zip, private readonly string $city, private readonly ?string $country, private readonly bool $mainResidence, ) {} } $result = ObjectBuilder::init(Address::class)->build(); // returns instance of Address with random values
You can override specific values. Unset values are generated randomly. Nested objects are resolved automatically.
class Person { public function __construct( private readonly Name $name, private readonly int $age, private readonly Address $address, ) {} } $result = ObjectBuilder::init(Person::class, [ 'age' => 25, 'name' => [ 'firstName' => 'Max', 'lastName' => 'Mustermann' ], 'address' => [ 'city' => 'Berlin', ] ])->build(); // $result->getAge() === 25 // $result->getName()->getFirstName() === 'Max' // $result->getAddress()->getCity() === 'Berlin' // $result->getAddress()->getZip() === random int|string
Enumerations
enum MyEnumeration: string { case OK = 'OK'; case WARNING = 'WARNING'; case ERROR = 'ERROR'; }
$result = ObjectBuilder::init(MyEnumeration::class)->build(); // returns one of MyEnumeration cases
You can specify which values the enum should use.
$result = ObjectBuilder::init(MyEnumeration::class, ['OK'])->build(); // returns MyEnumeration::OK $result = ObjectBuilder::init(MyEnumeration::class, ['WARNING', 'ERROR'])->build(); // returns one of MyEnumeration::WARNING|MyEnumeration::ERROR
Traits
For traits, an anonymous class is created that uses the trait. Parameters passed to the TraitBuilder are ignored.
$result = ObjectBuilder::init(MyTrait::class)->build(); // returns {class@anonymous/...}
Interfaces
The given interface is loaded and a class is dynamically generated from it. It returns the interface with the required methods and implements the interface.
The return value of methods is determined and a random value is assigned.
$result = ObjectBuilder::init(MyInterface::class)->build(); // returns Object of MyInterfaceClass $value = $result->myMethod() // returns random value matching its return type.
You can specify which values the methods should return. Pass an array with the method name as the key.
$options = [ 'getMyString' => 'testString' ]; $result = ObjectBuilder::init(MyInterface::class, $options)->build(); // returns Object of MyInterfaceClass $value = $result->getMyString() // returns 'testString'
If a method returns an object and you want to set values in it, that works too.
$options = [ 'getMyObject' => new SomeObject('Gustav', 27) ]; $result = ObjectBuilder::init(MyInterface::class, $options)->build(); // returns Object of MyInterfaceClass $value = $result->getMyObject() /** * returns class SomeObject { * string $name => "Gustav", * int $age => 27, * } */
It is also possible to pass individual parameters to the object.
$options = [ 'getMyObject' => ['name' => 'Bernhard'] ]; $result = ObjectBuilder::init(MyInterface::class, $options)->build(); // returns Object of MyInterfaceClass $value = $result->getMyObject() /** * returns class SomeObject { * string $name => "Bernhard", * int $age => 27356453, * } */
Readonly Classes
Readonly classes (PHP 8.2+) are supported. Properties are automatically populated in the constructor — including nested ones.
readonly class ReadonlyPerson { public function __construct( public string $name, public int $age, public ?ReadonlyAddress $address = null, ) {} } $result = ObjectBuilder::init(ReadonlyPerson::class, [ 'name' => 'Alice', 'address' => ['street' => 'Main St', 'city' => 'Springfield'], ])->build(); // $result->name === 'Alice' // $result->address->street === 'Main St'
Abstract Classes
Abstract classes are resolved via existing concrete subclasses. The builder automatically finds a suitable implementation.
abstract class AbstractVehicle { public function __construct(public readonly string $brand) {} abstract public function getType(): string; } class Car extends AbstractVehicle { public function getType(): string { return 'car'; } } $result = ObjectBuilder::init(AbstractVehicle::class)->build(); // returns instance of Car (or another concrete subclass)
Stock Classes (PHP Built-Ins)
Built-in PHP classes like DateInterval, DatePeriod, DateTime, DateTimeImmutable, ReflectionFunction, ArrayObject, and SplFileInfo are automatically supported.
$interval = ObjectBuilder::init(DateInterval::class)->build(); // returns DateInterval('P7D') $date = ObjectBuilder::init(DateTimeImmutable::class)->build(); // returns random DateTimeImmutable instance $ref = ObjectBuilder::init(ReflectionFunction::class)->build(); // returns new ReflectionFunction('strlen')
Custom handlers for additional stock classes can be registered:
use MF1DD\Application\Services\StockClassHandlerService; StockClassHandlerService::register(new MyCustomHandler());
Value Constraints (with())
The with() method allows setting constraints for value ranges.
use MF1DD\UserInterface\ObjectBuilder; $result = ObjectBuilder::init(Person::class) ->with('age', ['min' => 18, 'max' => 65]) ->with('email', ['format' => 'email']) ->build(); // $result->getAge() is between 18 and 65 // $result->getEmail() is a random email address
Available constraints:
min/max— value range for int and floatmin_length/max_length— string lengthformat— predefined formats:email,url,uuid
Semantic String Detection
The StringBuilder recognizes specific property names and generates matching values:
class User { public function __construct( public readonly string $timezone, // random IANA timezone public readonly string $countrycode, // random ISO country code public readonly string $email, // random email address public readonly string $firstname, // random first name public readonly string $lastname, // random last name public readonly string $city, // random city name public readonly string $street, // random street name public readonly string $zip, // random postal code public readonly string $phone, // random phone number public readonly string $uuid, // random UUID v4 public readonly string $url, // random URL ) {} } $result = ObjectBuilder::init(User::class)->build(); // All properties contain semantically meaningful random values
Custom Type Builders
Custom type builders can be registered for specific data types:
use MF1DD\Application\Services\DataTypeService; use MF1DD\Domain\DataTypeInterface; use MF1DD\Domain\Dto\Property; class CustomBuilder implements DataTypeInterface { public function build(): mixed { return 'custom value'; } public function setProperty(Property $property): self { return $this; } public function buildAsString(): string { return "'custom value'"; } } DataTypeService::register('custom_type', new CustomBuilder());
Custom Builder Override
The automatically selected builder can be overridden:
use MF1DD\Domain\ClassBuilderInterface; $result = ObjectBuilder::init(MyClass::class) ->withBuilder($myCustomBuilder) ->build();
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 3
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-13