1

I have a component com_something that I am developing. Whenever a user goes to any view in this component (i.e. when the URL starts with index.php?option=com_something), I want to check the URL for a parameter trackingToken=2. If it exists, I log something into the database.

Does Joomla have a URL middleware hook that I can use (like below)?

public function handleUrl(string $url): void
{
    $app = $this->getApplication();
    $db = $this->getDatabase();
    $trackingToken = $app->input->getString('trackingToken', null);
    if (!is_null($trackingToken)) {
        trackToken($db, $trackingToken);
    }
}

Or do I have to make sure that every HtmlView.php also extends some base HtmlView that does this?

abstract class MiddlewareHtmlView extends \Joomla\CMS\MVC\View\HtmlView
{
    public function display($tpl = null): void
    {
        $app = \Joomla\CMS\Factory::getApplication();
        $db = \Joomla\CMS\Factory::getDbo();
        $trackingToken = $app->input->getString('trackingToken', null);
        if (!is_null($trackingToken)) {
            trackToken($db, $trackingToken);
        }

        parent::display($tpl);
    }
}

final class HtmlView extends MiddlewareHtmlView
{
    public function display($tpl = null): void
    {
        parent::display($tpl);
    }
}

2 Answers 2

2

If your component uses Joomla's core MVC, add the code to your display controller's display() method:

namespace [Vendor]\Component\[Component]\[Application]\Controller;

use Joomla\CMS\MVC\Controller\BaseController;

final class DisplayController extends BaseController
{
    public function display($cachable = false, $urlparams = [])
    {
        //your logic here
        $trackingToken = $this->input->getString('trackingToken', null);
        ...

        return parent::display();
    }
}

This method is executed when any view is accessed in your component. In case you want the code executed on all requests, not just views, you could place it in the dispatch() method of your component's dispatcher.

namespace [Vendor]\Component\[Component]\[Application]\Dispatcher;

use Joomla\CMS\Dispatcher\ComponentDispatcher;

final class Dispatcher extends ComponentDispatcher
{
    public function dispatch()
    {
         //your logic here
         $trackingToken = $this->input->getString('trackingToken', null);
         ...

        parent::dispatch();
    }
0

You can put the handling code in the component boot function. Not sure if this is best practices or not though.

// com_something/admin/src/Extension/SomethingComponent.php
// ...
public function boot(ContainerInterface $container): void
{
    $app = $container->get(\Joomla\CMS\Application\SiteApplication::class);
    $db = $container->get(\Joomla\Database\DatabaseDriver::class);
    $trackingToken = $app->input->getString('trackingToken', null);
    if (!is_null($trackingToken)) {
        trackToken($db, $trackingToken);
    }
}
// ...
1
  • 1
    This is not good. Extension's boot() method is called when the extension is instantiated and that doesn't necessarily happen when the component is dispatched. It can be called from other extensions (e.g. modules or plugins when using $app->bootComponent() to get component's MVC factory) or from CLI. It should not contain request-specific logic.
    – Sharky
    Commented Jan 20 at 12:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.