1

in my component I made a List view of items and add with ToolbarHelper a New Button to add new items. Further I add a link to the item name to edit this item. As for SEF user friendly URLs I add a Router.php in site/src/Service. My router.php replace the item id with item name which works fine. - I can list, edit and save modified items.

The add function will be trigger if no item id is provided in the link. So if I de-active the SEO friendly URLs on the Gerneral Settings even the new button is working. With active SEO friendly URLs it seems the router.php is "blocking" the add functionality... even knowing I definitely misunderstood something here ....

my Router.php is as follows:

class Router extends RouterView
 {
    private $db;

    public function __construct(SiteApplication $app, AbstractMenu $menu, $category, DatabaseInterface $db)
    {
        $this->db = $db;
        $dogs = new RouterViewConfiguration('dogs');
        $this->registerView($dogs);
        $dog = new RouterViewConfiguration('dog');
        $dog->setKey('dogID')->setParent($dogs);
        $this->registerView($dog);

        parent::__construct($app, $menu);
        $this->attachRule(new MenuRules($this));
        $this->attachRule(new StandardRules($this));
        $this->attachRule(new NomenuRules($this));
    }

    public function getDogSegment($key, $urlQuery)
    {
   
        $query = $this->db->getQuery(true);
        $query->select($this->db->quoteName('dogName'))
            ->from($this->db->quoteName('#__bnc_dogs'))
            ->where($this->db->quoteName('dogID') . ' = ' . (int) $dogID);
        $this->db->setQuery($query);
        $dogName = $this->db->loadResult();
    }

    public function getDogId($segment, $urlQuery)
    {
        
        $query = $this->db->getQuery(true);
        $query->select($this->db->quoteName('dogID'))
            ->from($this->db->quoteName('#__bnc_dogs'))
            ->where($this->db->quoteName('dogName') . ' = :dogName')
            ->bind(':dogName', $segment);
        $this->db->setQuery($query);
        return (int) $this->db->loadResult();
    }
 }

I wonder if I could skip the router functionality if dogID is not set in the link.

I would highly appreciate any pointer to tackle that... Thanks, Gerald

3
  • Is your List of items and New functionality on the site front-end or on the administrator back-end? The router works only on the front end. Basically your RouterViewConfigurations should match your View classes on the front end. Mar 11 at 16:25
  • This page is on the front end. Is there a feasible way to deactivate SEO friendly URLs for a specific component. I hardly see the benefit but I also red that if you turn it off for the complete site some functionality of Joomla might not work properly. - In my View class I don't do any very special things. I only load the form, state and item.
    – Gerald
    Mar 11 at 19:35
  • I've always found it's a bit of trial and error to work out what the RouterViewConfigurations should be. Another thing you could try would be to create a menuitem to point to your new item form. Even if it's a hidden menuitem the router can still use it as a basis for the SEF URL. Mar 12 at 16:16

1 Answer 1

1

I have always had SEO friendly switched on and not had an issue with the router blocking. So I thought I might as well post my whole router.php file here so that hopefully it may help. I have 3 views per "function" being an item view, list view and a form view. In the below example I have "transaction", "transactions", and "transactionform" views. So if I have more "functions" then I would add these by replicating each of the methods involved. Hope this helps.

/**
 * @version    0.0.2
 * @package    com_mycomponent
 * @author     Glenn Arkell <[email protected]>
 * @copyright  2021 Glenn Arkell
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 */

namespace GlennArkell\Component\Mycomponent\Site\Service;

// No direct access
defined('_JEXEC') or die;

use \Joomla\CMS\Component\Router\RouterViewConfiguration;
use \Joomla\CMS\Component\Router\RouterView;
use \Joomla\CMS\Component\Router\Rules\StandardRules;
use \Joomla\CMS\Component\Router\Rules\NomenuRules;
use \Joomla\CMS\Component\Router\Rules\MenuRules;
use \Joomla\CMS\Factory;
use \Joomla\CMS\Categories\Categories;
use \Joomla\CMS\Application\SiteApplication;
use \Joomla\CMS\Categories\CategoryFactoryInterface;
use \Joomla\CMS\Categories\CategoryInterface;
use \Joomla\Database\DatabaseInterface;
use \Joomla\CMS\Menu\AbstractMenu;
//use \GlennArkell\Component\Mycomponent\Administrator\Helper\MycomponentHelper;

/**
 * Class Component Router
 */
class Router extends RouterView
{
    private $noIDs;

    /**
     * The category factory
     * @var CategoryFactoryInterface
     * @since  4.0.0
     */
    private $categoryFactory;

    /**
     * The category cache
     * @var  array
     * @since  4.0.0
     */
    private $categoryCache = [];

    public function __construct(SiteApplication $app, AbstractMenu $menu, CategoryFactoryInterface $categoryFactory, DatabaseInterface $db)
    {
        $params = Factory::getApplication()->getParams('com_gabarebone');
        $this->noIDs = (bool) $params->get('sef_ids');
        $this->categoryFactory = $categoryFactory;
        
        /* -------------------------------------------------------- */
        /* -------   transactions Config  --------------- */
        /* -------------------------------------------------------- */
        $transactions = new RouterViewConfiguration('transactions');
        $this->registerView($transactions);

        $transaction = new RouterViewConfiguration('transaction');
        $transaction->setKey('id')->setParent($transactions, 'catid');
        $this->registerView($transaction);

        $transactionform = new RouterViewConfiguration('transactionform');
        $transactionform->setKey('id');
        $this->registerView($transactionform);

        /* -------------------------------------------------------- */
        /* -------   parent construct and rules  --------------- */
        /* -------------------------------------------------------- */
        parent::__construct($app, $menu);

        $this->attachRule(new MenuRules($this));
        $this->attachRule(new StandardRules($this));
        $this->attachRule(new NomenuRules($this));
    }

    /* -------------------------------------------------------- */
    /* -------   transactions segments & id linkage  --------------- */
    /* -------------------------------------------------------- */
    /**
     * Method to get the segment(s)
     * @param   string  $id     ID of the category to retrieve the segments for
     * @param   array   $query  The request that is built right now
     * @return  array|string  The segments of this item
     */
    public function getTransactionsSegment($id, $query)
    {
        $category = $this->getCategories(["access" => true])->get($id);

        if ($category) {
            $path = array_reverse($category->getPath(), true);
            $path[0] = '1:root';

            if ($this->noIDs) {
                foreach ($path as &$segment) {
                    list($id, $segment) = explode(':', $segment, 2);
                }
            }

            return $path;
        }

        return array();
    }

    /**
     * Method to get the segment(s) for a single record
     * @param   string  $id     ID of the record to retrieve the segments for
     * @param   array   $query  The request that is built right now
     * @return  array|string  The segments of this item
     */
    public function getTransactionSegment($id, $query)
    {
        return array((int) $id => $id);
    }

    /**
     * Method to get the segment(s) for a record when using a form
     * @param   string  $id     ID of the record to retrieve the segments for
     * @param   array   $query  The request that is built right now
     * @return  array|string  The segments of this item
     */
    public function getTransactionformSegment($id, $query)
    {
        return $this->getTransactionSegment($id, $query);
    }

    /**
     * Method to get the id reference for a record segment
     * @param   string  $segment  Segment of the record to retrieve the ID for
     * @param   array   $query    The request that is parsed right now
     * @return  mixed   The id of this item or false
     */
    public function getTransactionId($segment, $query)
    {
        return (int) $segment;
    }

    /**
     * Method to get the id reference for a record segment when using a form
     * @param   string  $segment  Segment of the record to retrieve the ID for
     * @param   array   $query    The request that is parsed right now
     * @return  mixed   The id of this item or false
     */
    public function getTransactionformId($segment, $query)
    {
        return $this->getTransactionId($segment, $query);
    }

    /**
     * Method to get the id for a record list
     * @param   string  $segment  Segment to retrieve the ID for
     * @param   array   $query    The request that is parsed right now
     * @return  mixed   The id of this item or false
     */
    public function getTransactionsId($segment, $query)
    {
        if (isset($query['id'])) {
            $category = $this->getCategories(["access" => true])->get($query['id']);

            if ($category) {
                foreach ($category->getChildren() as $child) {
                    if ($this->noIDs) {
                        if ($child->alias == $segment) {
                            return $child->id;
                        }
                    } else {
                        if ($child->id == (int) $segment) {
                            return $child->id;
                        }
                    }
                }
            }
        }

        return false;
    }

    /**
     * Method to get categories from cache
     * @param   array  $options   The options for retrieving categories
     * @return  CategoryInterface  The object containing categories
     * @since   4.0.0
     */
    private function getCategories(array $options = []): CategoryInterface
    {
        $key = serialize($options);

        if (!isset($this->categoryCache[$key])) {
            $this->categoryCache[$key] = $this->categoryFactory->createCategory($options);
        }

        return $this->categoryCache[$key];
    }

    /* -------------------------------------------------------- */
    /* -------   other segments & id linkage  --------------- */
    /* -------------------------------------------------------- */

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.