Skip to content

Instantly share code, notes, and snippets.

@dantleech
Last active May 20, 2024 07:13
Show Gist options
  • Save dantleech/889b1b8f789909d20197df8e8ccca58a to your computer and use it in GitHub Desktop.
Save dantleech/889b1b8f789909d20197df8e8ccca58a to your computer and use it in GitHub Desktop.
POC for using a fixture contianer to lazily load "fixtures"
<?php
class OrganisationContext implements Context
{
/**
* Fixture container is similar to a service container, but for class instances.
*/
public function __construct(private FixtureContainer $fixture)
{
}
#[Given('I have an organisation :name')]
public function iHaveAnOrganisation(string $name): void
{
// register a _named_ fixture for this class
// a _Builder_ must be registered for the class and the parameters
// are passed to its __invoke method
$this->fixture->register(Organisation::class, $name, [
'name' => $name
]);
}
#[Given('I have a project :project in organisation :organisation')]
public function iHaveAProject(string $project, string $organisation): void
{
// the Builders also get the FixtureContainer so can retrieve dependencies
// (in this case the organisation by the name we previously registered)
$this->fixture->register(Project::class, $project, [
'name' => $project,
'organisation' => $organisation
]);
}
#[When('I upload an artifact to project :name')]
public function iUploadAnArtifactToThatProject(string $project): void
{
// calling `get` will lazily invoke the Builders
$project = $this->fixture->get(Project::class, $project);
}
}
<?php
/**
* Builder classes are registed in the "FixtureContainer" and provide fixtures
* based on the `__invoke` return type (not sure if that's a great idea).
*/
final class ProjectBuilder
{
public function __invoke(
FixtureContainer $container,
string $name,
string $organisation
): Project
{
return new Project(
Uuid::v4(),
// _get_ (or create) the organisation instance
$container->get(Organisation::class, $organisation),
$name
);
}
}
<?php
final class FixtureContainer
{
/**
* @var array<string,array<string,\Closure():object>>
*/
private array $factories = [];
/**
* @var array<string,array<string,object>>
*/
private array $instances = [];
/**
* @param list<object> $builders
*/
public function __construct(
private array $builders
)
{
}
/**
* @template TClass of object
* @param class-string<TClass> $className
* @return TClass
*/
public function get(string $className, string $identifier): object
{
// blah...
return $instance;
}
/**
* @param class-string $className
* @param array<string,mixed> $params
*/
public function register(string $className, string $identifier, array $params = []): void
{
// blah...
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment