torq/object-generator-bundle

1.0.0 2025-06-13 16:23 UTC

This package is auto-updated.

Last update: 2025-06-13 16:28:02 UTC


README

Getting Started

This bundle is for automatically generating objects using PHPFaker. It uses the object's parameter types and names to recursively generate real looking data. This bundle is currently designed with DTOs in mind, but there's nothing stopping you from using it to generate any kind of PHP object - just don't expect it to work for every parameter type yet. The intended usage for now is as such:

// define your DTO
class MyDto {
    public ?int $id;
    public ?string $name;
    ...
}
// Inside a command, or whatever script you use to generate your data

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Torq\ObjectGeneratorBundle\Service\FakeObjectFactory\FakeObjectFactory;

class GenerateDataCommand extends Command {

    // dependency inject the factory
    public function __construct(private FakeObjectFactory $fakeObjectFactory) {}
    
    public function execute(InputInterface $input, OutputInterface $output) 
    {
        // optionally define your config (see FakeObjectFactory::DEFAULT_CONFIG)
        $config = ['useConstructor' => false];
    
        // generate your dto
        $dto = $this->fakeObjectFactory->generateValue(MyDto::class, $config);

        // do whatever with the generated data, likely create a data object with it.
        $object = new DataObject();
        $object->setId($dto->id);
        $object->setName($dto->name);

        return self::SUCCESS;
    }
}
// You can override the automatic type checking by using #[GenerateAs]

use Torq\ObjectGeneratorBundle\Service\FakeObjectFactory\GenerateAs;
use Torq\ObjectGeneratorBundle\Service\DataGenerator\NameGenerator;

class AnotherDto {
    public ?int $id;

    // pass the class of the generator you want to use
    #[GenerateAs(NameGenerator::class)]
    public ?string $name;
}

Supported Types

Recursion isn't fully working yet. The workaround is to just set maxRecursionDepth to a large value depending on how many objects you're generating, e.g. like 300 or more.

Arrays and array-like types are not yet supported generically.

Right now we really only have support for primitives and recursive objects. However, you can very easily define a new custom DataGenerator and have the factory use it with no config necessary. Simply have your class either extend AbstractDataGenerator OR implement DataGeneratorInterface and the container will automatically tag it for the factory:

use Torq\ObjectGeneratorBundle\Service\DataGenerator\AbstractDataGenerator;
use Torq\ObjectGeneratorBundle\Service\DataGenerator\DataGeneratorInterface;

// Recommend extending AbstractDataGenerator to get utilities
class MyEmojiGenerator extends AbstractDataGenerator implements DataGeneratorInterface {
    // $config is passed through from factory->generateValue, maps to faker fn arguments
    public function generateValue(string $type, ?string $name = null, array $config = [])
    {
        // getConfigParser convenience utility comes from AbstractDataGenerator
        $parser = $this->getConfigParser($config);
        return $this->faker->emoji(...$parser('emoji'));
    }

    // Used to finely filter out generators per parameter during generation
    public function supportsGeneration(string $type, ?string $name = null): bool
    {
        return $type === 'string';
    }

    // Used to broadly filter generators prior to generation
    public function getSupportedTypes(): array
    {
        // Expected types found here: https://www.php.net/manual/en/reflectionnamedtype.getname.php
        return ['string'];
    }

    // Used to pick which generator from those where supportsGeneration is true and getSupportedTypes matches
    public function getPriority(): int
    {
        // default is 0, use positive values to increase priority, negative to decrease
        return 0;
    }
}

If you end up defining any custom generators you think are generic/useful enough for every project, feel free to open a PR to this project to include them as part of the default generators.