prestaconcept / PrestaSitemapBundle

A symfony bundle that provides tools to build a rich application sitemap. The main goals are : simple, no databases, various namespace (eg. google image), respect constraints etc.
MIT License
347 stars 100 forks source link

How to manually dispatch SitemapPopulateEvent to dump the map from service? #255

Closed sabat24 closed 3 years ago

sabat24 commented 3 years ago

I tired to dispatch the SitemapPopulateEvent from my service like that:

$this->eventDispatcher->dispatch($event);

where $event should be I guess the SitemapPopulateEvent

However I can't inject SitemapPopulateEvent because I get an error Presta\SitemapBundle\Event\SitemapPopulateEvent" but no such service exists

If I try to just create an object like that new sitemapPopulateEvent() I need to pass the UrlContainerInterface which creates me another error if I try to DI it: references interface "Presta\SitemapBundle\Service\UrlContainerInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "presta_sitemap.generator_default", "presta_sitemap.dumper_default"

So how can I dump the sitemap on demand from my service?

yann-eugone commented 3 years ago

Hello @sabat24 !

There is only one way to dump sitemap from a service : using symfony/messenger. But this is a very recent feature (#237) which is documentated but not tagged yet (will be availlable in next tag: v2.3.0).

So what you are trying to do : dispatching the SitemapPopulateEvent will not help you anyway : dispatching the event is not sufficient to dump the sitemap. If you want to do it by yourself, you should have a look to how it has been done in the #237 Pull Request, and try to do the same.


I will still try to answer your questions :

Event can't be services, because services are (kind of) singletons, and event are simple objects that are different one time from an other.

The error you have with Presta\SitemapBundle\Service\UrlContainerInterface is not a service is "normal". This bundle is not registering any autowiring alias for that interface. You must either add that alias in your project :

# config/services.yaml
services:
  Presta\SitemapBundle\Service\UrlContainerInterface: '@presta_sitemap.dumper_default'
sabat24 commented 3 years ago

Thank you for detailed clarification. I tried in various ways dump the sitemap, this is why I have used such weird things like injecting the event object :)

Meanwhile I found also a way to dump the sitemap calling your command from my service (or any part of application). I guess that this approach is quite similar to that with Messenger one.

The most directly way is to use Process Component. Implementation could looks like that

$process = new Process(['/path/to/php', 'path/bin/console', 'presta:sitemaps:dump']);
$process->run() / start();

Second method is to use cron jobs especially with some kind of bundle to help handle executing commands. You only need to create your own command which will be executed for example once a day (the period doesn't matter). Then from custom command you can easily call the presta:sitemaps:dump for example like that:

protected function execute(InputInterface $input, OutputInterface $output)
    {
        $command = $this->getApplication()->find('presta:sitemaps:dump');
        $greetInput = new ArrayInput(['--gzip' => true]);
        $output = new NullOutput();
        $command->run($greetInput, $output);
        return 0;
    }

And then in service you just need to only "bump" your command to run right now and cron will do it's job.

yann-eugone commented 3 years ago

Yes, you can also call the command from anywhere you can't using the process command. Although this is not something I would recommend : not possible in every app, not easy to debug when it fails.