Reputation: 1
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;
}
Upvotes: 0
Views: 374
Reputation: 1
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 '';
}
Upvotes: 0
Reputation: 886
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 Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
#[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');
}
}
Upvotes: 0