简体   繁体   中英

Joomla component router

I'm trying to follow the instructions on this docs page, but I seem to be missing something: https://docs.joomla.org/Supporting_SEF_URLs_in_your_component

The URI that needs to be corrected is: index.php?com_component&view=legal&page=customermasteragreement

It seems like the routing function should be simple, but the page is just displaying default instead of the sub-view.

Here's my current code:

function ComponentBuildRoute(&$query)
{
    $segments = array();
        if (isset($query['view'])) {
            $segments[] = $query['view'];
            unset($query['view']);
       }
        if (isset($query['page'])) {
            $segments[] = $query['page'];
            unset($query['page']);
    }

    return $segments;
}

function ComponentParseRoute($segments)
{
       $vars = array();
       switch($segments[0])
       {
               case 'legal':
                       $vars['view'] = 'legal';
                       break;
               case 'customermasteragreement':
                       $vars['page'] = 'customermasteragreement';
                       break;

       }

       return $vars;
}

Update This code works to display the subpage, but it gives me a URI like: legal-agreements/legal?page=customermasteragreement

class ComponentRouter extends JComponentRouterBase {

    public function build(&$query) {
        $segments = array();
        $view = null;

        if (isset($query['view'])) {
            $segments[] = $query['view'];
            $view = $query['view'];

            unset($query['view']);
        }

        if (isset($query['id'])) {
            if ($view !== null) {
                $segments[] = $query['id'];
            } else {
                $segments[] = $query['id'];
            }

            unset($query['id']);
        }

        return $segments;
    }


    public function parse(&$segments) {

        $vars = array();

        // View is always the first element of the array
        $vars['view'] = array_shift($segments);

        return $vars;
    }
}

EDIT 2

If it helps, here's my model and views

models/legal.php

// import Joomla modelitem library
jimport('joomla.application.component.modelitem');

class ComponentModelLegal extends JModelItem {
    public function __construct($config = array())
            {
       JLoader::register('ComponentHelper', JPATH_COMPONENT_ADMINISTRATOR . '/helpers/component.php');
       parent::__construct($config);
            }

    /**
     * 
     * @return string
     */
    public function getLegal() {
        $app = JFactory::getApplication();
        $page = $app->input->get('page', '', 'STRING');

        if ($page) {
            ComponentHelper::add('type', $page);   //This is an API request to an external service, returning JSON formatted data
            $legal = ComponentHelper::getData('commons/legal-agreements.json', TRUE);


            if (isset($legal[0]['status'])) {
                JError::raiseError(400, $legal[0]['ERROR']);
                return false;
            } else {
                if (!isset($this->legal)) {
                    $this->legal = $legal;
                }
                return $this->legal;
            }
        }
    }

}

views/legal/view.html.php

class ComponentViewLegal extends JViewLegacy {
    function display($tpl = null) {
        // Assign data to the view
        $this->legal = $this->get('legal');

        // Check for errors.
        if (count($errors = $this->get('Errors'))) {
            JLog::add(implode('<br />', $errors), JLog::WARNING, 'jerror');
            return false;
        }

        // Display the view
        parent::display($tpl);
    }
}

views/legal/tmpl/default.php

$page = JRequest::getVar('page');
$pages = array(
    'resellermasteragreement',
    'customermasteragreement',
    'resellerdomainagreement',
    'customerdomainagreement',
    'resellerwebserviceagreement',
    'customerwebserviceagreement',
    'resellerdigicertagreement',
    'customerdigicertagreement',
    'registraragreement',
    'customerhostingproductagreement',
    'resellerhostingproductagreement'
);

    ?>
    <div class="col-lg-12">
        <?php 
        echo in_array($page, $pages) ? $this->loadTemplate('legal') : $this->loadTemplate('home');
        ?>
    </div>

views/legal/tmpl/default_legal.php

$page = JRequest::getVar('page');

echo nl2br(htmlspecialchars($this->legal[$page]['defaultagreement'], ENT_NOQUOTES, "UTF-8"));
?>
<a type="button" class="btn btn-primary" href="<?php echo JROUTE::_("index.php?option=com_component&view=legal"); ?>">Back</a>

EDIT 3 This works because I wasn't navigating directly to the page from a menu item. There's a top level menu, then a page a links to the agreements. I have a hidden menu to each item, but that wasn't the link I followed.

$app = JFactory::getApplication()->getMenu();
$customermaster = $app->getItems( 'link', 'index.php?option=com_component&view=legal&page=customermasteragreement', true );
JRoute::_('index.php?Itemid='.$customermaster->id); 

You have one view but you're not actually set the page argument correctly when you catch a view argument, but you treat page as some king of another view. Can you please try this and check if it works:

function [componentname]ParseRoute($segments)
{
    $vars = array();
    switch($segments[0])
    {
        case 'legal':
            $vars['view'] = 'legal';
            $vars['page'] = $segments[1];
            break;
    }

    return $vars;
}

Also the functions ComponentBuildRoute , ComponentParseRoute must have your components name instead of Component at the beginning.

EDIT

[componentname]BuildRoute and [componentname]ParseRoute are deprecated, you should stick the the class that extends JComponentRouterBase as you have it in your updated second example. Try this one here and see if it works:

class ComponentRouter extends JComponentRouterBase {

    public function build(&$query) {
        $segments = array();
        $view = null;

        if (isset($query['view'])) {
            $segments[] = $query['view'];
            $view = $query['view'];

            unset($query['view']);
        }

        if (isset($query['page'])) {
            $segments[] = $query['page'];
            unset($query['page']);
        }

        return $segments;
    }

    public function parse(&$segments) {

        $vars = array();

        // View is always the first element of the array
        $vars['view'] = array_shift($segments);
        if(count($segments) > 0)
            $vars['page'] = array_shift($segments);

        return $vars;
    }
}

EDIT 2

I have a test Joomla 3 site with a simple component named Ola .

Non SEO component URL: http://j3.dev.lytrax.net/index.php?option=com_ola&page=test_page&view=ola

URL generated by JRoute before Router class added to router.php : http://j3.dev.lytrax.net/index.php/component/ola/?page=test_page&view=ola

SEO URL returned by JRoute::_('index.php?option=com_ola&page=test_page&view=ola'); after creating router.php and used the Router class above: http://j3.dev.lytrax.net/index.php/component/ola/ola/test_page

If you visit the links, you'll see that all are working and you can even see the page , view and JRoute results of the calling component Ola .

Unless I've completely misunderstood Joomla (I've been developing with it for four five years now), there is no "sub-view" concept implemented. Trying to use the idea is what's getting you into trouble I think.

I'm astounded that the idea of using a visual debugger is so unpopular. Get yourself something like Netbeans (there are others too), set up a local web and database server, and watch the code run. Very (well, relatively very) quickly you'll start to understand how the structure hangs together.

You may put code in your view that picks up the extra params you've set and displays or hides things accordingly, but there is no "sub-view".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM