skip to Main Content

I have a problem with the proper arrangement of services.I want to create a generator that, thanks to the provider, will create the corresponding generator object through the factory method.In my mind it would more or less look like this:

API Request with provider -> GeneratorController::generate -> factory method -> Generator class service

I would like to generate a pdf file using twig, but I have a problem with the ContainerInterface.I’m afraid that my concept of operation is not correct. Is anyone able to tell me if I am going in the right direction?

I would like to make a pdf generator that is created through a provider and generator classes.

GeneratorController

public function generate($provider, Request $request): Response
{
    $generator = $this->factory->createGenerator($provider);
    $content = json_decode($request->getContent(), true);
    $generator->generate($content['params']);
    
    return new JsonResponse($generator->getData());
}

GeneratorFactory

class GeneratorFactory
{
    public function createGenerator($generator): Generator
    {
        $generatorName = "App\Generators\" . ucwords($generator) . "\Generator";

        if (!class_exists($generatorName)) {
            throw new Exception("We dont find genarator with name: " . $generator);
        }

        return new $generatorName;
    }
}

Generator from factory

 public function __construct()
    {
        $this->object = new GeneratorObject;
        $this->validator = new Validator;
        $this->service = new PdfService();
    }
    public function generate(array $params): void
    {
        $valided = $this->validator->Validate($params);
        if (!$valided) {
            throw new Exception("Invalid parameters", 1);
        }
        $this->setDataToObject($params);
        $pdf = $this->service->createPdf($this->object);
        $this->data = $pdf;
    }

Service for pdf

public function createPdf(GeneratorObject $pdfObject): string
{
    $url = '';
    $html = $this->templating->render('pdf/index.html.twig',[$pdfObject]);

    return $url;
}

2

Answers


  1. Chosen as BEST ANSWER

    I think I have solved my problem. I changed the concept a little bit. I divided the services accordingly and now it injects the service in the controller. When injecting the service, I made an autoload for twig and set it as a variable of the object created from the factory method.Now it looks like this

    Controller

    public function generate($provider, Request $request, GeneratorFactory $factory): Response
    {
        $generator = $factory->createGenerator($provider);
        $factory->setTwig($generator);
        $content = json_decode($request->getContent(), true);
        $generator->generate($content['params']);
    
        return new JsonResponse($generator->getData());
    }
    

    Factory method

    public function __construct(Environment $twig)
    {
        $this->twig = $twig;
    }
    

    Object from factory

    /**
     * generate
     *
     * @param  array $params
     * @return void
     */
    public function generate(array $params): void
    {
        $valided = $this->validator->Validate($params);
        if (!$valided) {
            throw new Exception("Invalid parameters", 1);
        }
        $this->setDataToObject($params);
        $pdf = $this->createPdf($this->object);
        $this->data = $pdf;
    }
    /**
     * createPdf
     *
     * @param  object $params
     * @return string
     */
    private function createPdf(object $params): string
    {
        $pdfHtml = $this->twig->render('pdf/cv.html.twig',[$params]);
    
        return '';
    }
    

  2. If I understand right, you should use a tagged iterator. I haven’t found a nice example/article. So here is an untested example. But tagged iterator is the keyword for more information.

    For #[TaggedIterator] and #[AutoconfigureTag] you need at least PHP 8 and Symfony 5.4.

    <?php
    
    use SymfonyBundleFrameworkBundleControllerAbstractController;
    use SymfonyComponentDependencyInjectionAttributeAutoconfigureTag;
    use SymfonyComponentDependencyInjectionAttributeTaggedIterator;
    
    #[AutoconfigureTag('app.custom_generator_tag')]
    interface GeneratorInterface
    {
        public function support(string $format): bool;
        public function generate(): string;
    }
    
    abstract class GeneratorAbstract implements GeneratorInterface
    {
        public function support(string $format): bool
        {
            return strtoupper($format) === $this::FORMAT;
        }
    }
    
    class PdfGenerator extends GeneratorAbstract
    {
        public const FORMAT = 'PDF';
    
        public function __construct(/* autowire services */) { }
    
        public function generate(): string
        {
            return 'pdf file';
        }
    }
    
    class WordGenerator extends GeneratorAbstract
    {
        public const FORMAT = 'WORD';
    
        public function __construct(/* autowire services */) { }
    
        public function generate(): string
        {
            return 'word file';
        }
    }
    
    class GeneratorFactory
    {
        /**
         * @var GeneratorInterface[]
         */
        private array $generators;
    
        public function __construct(#[TaggedIterator('app.custom_generator_tag')] $generators)
        {
            $this->generators = $generators;
        }
    
        public function generate(string $format): string
        {
            foreach ($this->generators as $generator) {
                if ($generator->support($format)) {
                    return $generator->generate();
                }
            }
    
            throw new Exception('Generator not found');
        }
    }
    
    class Generatorcontroller extends AbstractController
    {
        public function __construct(private GeneratorFactory $generatorFactory) {}
    
        public function generateAction()
        {
            return $this->generatorFactory->generate('pdf');
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search