0

I've added Router Features today to my Custom Component - all works finde beside the fact that the $pk variable inside the model holds a curios value (202n) where 'n' is different for each element...

Router:

public function __construct(SiteApplication $app, AbstractMenu $menu, CategoryFactoryInterface $categoryFactory, DatabaseInterface $db)
    {
        $this->categoryFactory = $categoryFactory;
        $this->db              = $db;

        $params = ComponentHelper::getParams('com_marathonmanager');
        $this->noIDs = (bool) $params->get('sef_ids');
        $categories = new RouterViewConfiguration('categories');
        $categories->setKey('id');
        $this->registerView($categories);
        $category = new RouterViewConfiguration('category');
        $category->setKey('id')->setParent($categories, 'catid')->setNestable();
        $this->registerView($category);

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

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

//        $this->registerView(new RouterViewConfiguration('featured'));
        $form = new RouterViewConfiguration('form');
        $form->setKey('id');
        $this->registerView($form);

        parent::__construct($app, $menu);

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

EventsNomenuRules:

     *
     * @var RouterView
     * @since 3.4
     */
    protected $router;

    /**
     * Class constructor.
     *
     * @param   RouterView  $router  Router this rule belongs to
     *
     * @since   3.4
     */
    public function __construct(RouterView $router)
    {
        $this->router = $router;
    }

    /**
     * Dummymethod to fullfill the interface requirements
     *
     * @param   array  &$query  The query array to process
     *
     * @return  void
     *
     * @since   3.4
     * @codeCoverageIgnore
     */
    public function preprocess(&$query)
    {
        $test = 'Test';
    }

    /**
     * Parse a menu-less URL
     *
     * @param   array  &$segments  The URL segments to parse
     * @param   array  &$vars      The vars that result from the segments
     *
     * @return  void
     *
     * @since   3.4
     */
    public function parse(&$segments, &$vars)
    {
        // with this url: http://localhost/events/event-n/event-title.html
        // segments: [[0] => event-n, [1] => event-title]
        // vars: [[option] => com_marathonmanager, [view] => events, [id] => 0]

        $vars['view'] = 'event';
        $vars['id'] = substr($segments[0], strpos($segments[0], '-') + 1);
        array_shift($segments);
        array_shift($segments);
        return;
    }

    /**
     * Build a menu-less URL
     *
     * @param   array  &$query     The vars that should be converted
     * @param   array  &$segments  The URL segments to create
     *
     * @return  void
     *
     * @since   3.4
     */
    public function build(&$query, &$segments)
    {
        // content of $query ($segments is empty or [[0] => mywalk-3])
        // when called by the menu: [[option] => com_mywalks, [Itemid] => 126]
        // when called by the component: [[option] => com_mywalks, [view] => mywalk, [id] => 1, [Itemid] => 126]
        // when called from a module: [[option] => com_mywalks, [view] => mywalks, [format] => html, [Itemid] => 126]
        // when called from breadcrumbs: [[option] => com_mywalks, [view] => mywalks, [Itemid] => 126]

        // the url should look like this: /site-root/mywalks/walk-n/walk-title.html



        // if the view is not mywalk - the single walk view
        if (!isset($query['view']) || (isset($query['view']) && $query['view'] !== 'event') || isset($query['format']))
        {
            return;
        }
        $alias = $this->getAliasForEvent($query['id']);
        error_log('alias: ' . var_export($alias, true));
        if($alias){

            $segments[] = $alias;
        }else {
            $segments[] = $query['view'] . '-' . $query['id'];
        }
        // the last part of the url may be missing
        if (isset($query['slug'])) {
            $segments[] = $query['slug'];
            unset($query['slug']);
        }
        unset($query['view']);
        unset($query['id']);
    }

    private function getAliasForEvent($id){
        if(!is_numeric($id)){
            return false;
        }
        $app = Factory::getApplication();
        $db = Factory::getContainer()->get(DatabaseInterface::class);
        $query = $db->getQuery(true);
        try
        {
            $query->select($db->quoteName('alias'))
                ->from($db->quoteName('#__com_marathonmanager_events'))
                ->where($db->quoteName('id') . ' = :id')
                ->bind(':id', $id, ParameterType::INTEGER);
            $db->setQuery($query);
            $app->enqueueMessage('NICE', 'default');
            return $db->loadResult();
        }
        catch (RuntimeException $e)
        {
            $app->enqueueMessage($e->getMessage(), 'error');
            return false;
        }
    }
}

In Fact when turning off SEF the event item url looks so: https://joomla4.local:8890/index.php?option=com_marathonmanager&view=event&id=5&Itemid=1282 And if turned on: https://joomla4.local:8890/marathon-manager-items/simm-2020-st-antoenien

But in the Model:

...
public function getItem($pk = null): object|bool
    {
        $app = Factory::getApplication();
        $pk = $app->input->getInt('id');

        error_log('EventModel::getItem() called with id: ' . $pk);

        if($this->_item === null)
        {
            $this->_item = array();
        }

        if(!isset($this->_item[$pk]))
        {
...

When checking the $pk var in the model it brings up a 202x number -which i cannot identify because its NOT the item ID

1 Answer 1

0

Ok I think I've got it now. I had to add a method to get the item ID based on the ALIAS of the item as visible below. Is this the correct way to handle this?

So in my EventsNomenuRules:

...
public function parse(&$segments, &$vars)
    {
        $vars['view'] = 'event';
        $vars['id'] = $this->getItemIdForAlias($segments[0]);
        array_shift($segments);
        array_shift($segments);
        return;
    }
...

private function getItemIdForAlias($alias){
        if(empty($alias)){
            return false;
        }
        $db = Factory::getContainer()->get(DatabaseInterface::class);
        $query = $db->getQuery(true);
        try
        {
            $query->select($db->quoteName('id'))
                ->from($db->quoteName('#__com_marathonmanager_events'))
                ->where($db->quoteName('alias') . ' = :alias')
                ->bind(':alias', $alias, ParameterType::STRING);
            $db->setQuery($query);
            return $db->loadResult();
        }
        catch (RuntimeException $e)
        {
            return false;
        }
    }

Your Answer

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

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