0

For a Joomla 4 component I just cannot figure out how to successfully forward or call a Controller function from within a custom Router.

This is the Controller - it basically loads an image:

<?php

namespace Mycompany\Component\Myproject\Site\Controller;

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Image\Image;
use Joomla\CMS\MVC\Controller\BaseController;


class ImageController extends BaseController
{

    /**
     * 
     */
    public function show()
    {
        $id = $app->input->get('id', \null, 'string');
        // ... logic to load the image 
    }
}

Using this URL the image shows up:

/index.php?option=com_myproject&task=image.show&id=123

To support SEF URLs inside the component the URL gets called like this:

/img/product_12312.jpg

In Joomla 3 I did this by configure mod_rewrite in the .htaccess. Now this should get done by the Router:

<?php

namespace Mycompany\Component\Myproject\Site\Service;

\defined('_JEXEC') or die;

use Joomla\CMS\Component\Router\RouterBase;


class Router extends RouterBase
{
    
    public function parse(&$segments)
    {
        $total = \count($segments);

        $vars  = [];

        switch ($segments[0]) {
            case ('img'):

                $vars['id'] = str_replace('.jpg', '', explode('_', $segments[1])[1]);
                $vars['task'] = 'image.show';
                break;
        }
        // print_r($vars); // seems to work so far
        
        return $vars;
    }
    // .... other code
}

The parse() function correctly splits the URL into the $vars array().

When I call the SEF image URL in the browser, I get a 404 error. - What am I missing to internally call the show() function of the ImageController class?

1 Answer 1

1

I wrote up in https://docs.joomla.org/J3.x:Developing_an_MVC_Component/Upgrading_to_Joomla4#Router what I found were the differences in the router between v3 and v4. In particular you have to find the Itemid in the preprocess() function and you also now have to unset the segments in parse() otherwise you'll get a 404.

1
  • Thanks for the tip! Unsetting the segments in the parse() did the trick. foreach ($segments as $key => $segment) {unset($segments[$key]);} I did not need a menu item to access my controller. So I did not overwrite the preprocess() in my RouterBase. Since the code was not using the router to build URLs, I simply added an build() to the RouterBase that just returns an empty segments array like this public function build(&$query) { $segments = []; return $segments;} Very valuable overview and video tutorial indeed. Thanks again!
    – cappu
    Sep 1, 2023 at 14: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.