shrink / examples
Compose example objects
Requires
- php: ^8.1
Requires (Dev)
- dq5studios/psalm-junit: ^2.0
- phpunit/phpunit: ^9.3
- squizlabs/php_codesniffer: ^3.5
- vimeo/psalm: ^4.3
README
Compose example objects.
use Shrink\Examples\E; use Shrink\Examples\Examples; final class Person { public function __construct( public readonly string $name, public readonly int $age ) { } } $examplePersonDefinition = E::define(Person::class, name: "Alice", age: 30); ($examples = new Examples())->register($examplePersonDefinition); $person = $examples->make(E::g(Person::class, name: "Bob")); self::assertSame( "Hello, Bob (age 30).", "Hello, {$person->name} (age {$person->age})." );
Usage
Install
dev:~$ composer require shrink/examples --dev
🧶 The latest version of Examples requires PHP 8.1, use Examples v1 for PHP 7.4 and PHP 8.0 support.
Instantiate Examples
An Examples::class
instance holds your example definitions and creates your
objects from these definitions.
use Shrink\Examples\Examples; $examples = new Examples();
Define Examples
The E::define()
method accepts a class type
and zero or more named
arguments, which map to the type
's constructor arguments.
E::define()
returns a definition to register with your instance of Examples.
use Shrink\Examples\E; $examples->register(E::define(Person::class, name: "Alice", age: 30));
✨ Since v2, named arguments are used instead of a parameters array.
🧬 E::define()
is a shortcut to create a simple example definition, see
Internals -> Definition for building your own implementation.
Make An Object
The E::g()
method accepts a class type
(referring to a registered example)
and zero or more named arguments to overwrite the example defaults. E::g()
returns an example configuration, which your instance of Examples will make()
.
use Shrink\Examples\E; $example = $examples->make(E::g(Person::class, name: "Bob")); echo "Hello, {$example->name} (age {$example->age})."; // Hello, Bob (age 30).
🧬 E::g()
is a shortcut to create a simple example configuration, see
Internals -> Creation for building your own implementation.
Features
Nested Examples
Examples::class will resolve any example definitions it encounters when making an example, allowing for many levels of nested example definitions and configuration.
final class Person { public function __construct( public readonly string $name, public readonly int $age, public readonly ?Location $location ) { } } final class Location { public function __construct( public readonly string $streetAddress, public readonly string $country ) { } } $examples = new Examples(); $examples->register( E::define( Location::class, streetAddress: "123 Default Street", country: "England" ) ); $examples->register( E::define( Person::class, name: "Alice", age: 30, location: E::g(Location::class, country: "United States") ) ); $person = $examples->make( E::g( Person::class, name: "Bob", location: E::g(Location::class, country: "The Netherlands") ) ); self::assertSame( "Hello, {$person->name} (age {$person->age}) from {$person->location->country}.", "Hello, Bob (age 30) from The Netherlands." );
Internals
Definition
Examples are registered using an example definition (DefinesExample
) which in
turn uses a builder (BuildsExampleInstances
) to create an object using
optional configuration.
use Shrink\Examples\Definition; use Shrink\Examples\Examples; use Shrink\Examples\Example; $examples = new Examples(); $examples->register(new Definition( Person::class, BuildsExampleInstances $builder, array $defaults )); $person = $examples->make(new Example( Person::class, array $parameters ));
Implicit instance building is handled through Reflection by ReflectionBuilder
which accepts a class name to build.
use Shrink\Examples\Definition; use Shrink\Examples\ReflectionBuilder; $examples->register( new Definition(Person::class, new ReflectionBuilder(Person::class), [ "name" => "Alice", "age" => 30, ]) );
E::define()
is a shortcut for creating an example definition with implicit
building. Explicit instance building is handled by providing a callable which is
called with the Example parameters as method parameters.
use Shrink\Examples\CallableBuilder; use Shrink\Examples\Definition; $examples->register( new Definition( Person::class, new CallableBuilder( fn(string $name, int $age): Person => new Person($name, $age) ), [ "name" => "Alice", "age" => 30, ] ) );
Creation
Objects are made, from an example, with an optional configuration of
parameters
. Ask the Examples
instance to
make(ConfiguresExample $configuration)
. A default implementation of
ConfiguresExample
is included which is constructed with the type and
parameters.
use Shrink\Examples\Example; $person = $examples->make(new Example(Person::class));
Parameters may be provided to overwrite any defaults.
use Shrink\Examples\Example; $person = $examples->make( new Example(Person::class, [ "name" => "Alice", ]) );
License
Examples is open-sourced software licensed under the MIT license.