PDA

Zobacz pełną wersję : Własny komponent plik ROUTER i linki SEF



krzys1985b
29-12-2023, 10:24
Witam

Proszę o pomoc, nakierowanie na właściwe tory.

Mam komponent jego głównym zadaniem jest wyświetlanie ofert (hoteli), nie potrafię sobie poradzić ze stworzeniem odpowiedniego routera aby adresy wyglądały następująco: www.nazwastrony.pl/kraj/region/miasto/ID-nazwa-hotelu (http://www.nazwastrony.pl/kraj/region/miasto/ID-nazwa-hotelu)

Mój plik Router: com_hotels\src\Service\Router.php


<?php


namespace kb\Component\Hotels\Site\Service;


defined('_JEXEC') or die;


use Joomla\CMS\Application\SiteApplication;
use Joomla\CMS\Categories\CategoryFactoryInterface;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Component\Router\RouterView;
use Joomla\CMS\Component\Router\RouterViewConfiguratio n;
use Joomla\CMS\Component\Router\Rules\MenuRules;
//use Joomla\CMS\Component\Router\Rules\NomenuRules;
use kb\Component\Hotels\Site\Service\HotelsNomenuRules as NomenuRules;
use Joomla\CMS\Component\Router\Rules\StandardRules;
use Joomla\CMS\Menu\AbstractMenu;
use Joomla\Database\DatabaseInterface;


/**
* Routing class of
*
* @since 3.3
*/
class Router extends RouterView
{
protected $noIDs = false;


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


/**
* The db
*
* @var DatabaseInterface
*
* @since 4.0.0
*/
private $db;


/**
* Component router constructor
*
* @param SiteApplication $app The application object
* @param AbstractMenu $menu The menu object to work with
* @param CategoryFactoryInterface $categoryFactory The category object
* @param DatabaseInterface $db The database object
*/
public function __construct(SiteApplication $app, AbstractMenu $menu,
CategoryFactoryInterface $categoryFactory, DatabaseInterface $db)
{
$this->categoryFactory = $categoryFactory;
$this->db = $db;


$params = ComponentHelper::getParams('com_hotels');
$this->noIDs = (bool) $params->get('sef_ids');


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

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


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


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

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


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


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


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


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


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


Do tego mam jeszcze pliki:
com_hotels\src\Service\HotelsNomenuRules.php


* Router this rule belongs to *
* @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)
{


$vars['view'] = 'hotel';
$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)
{
if (!isset($query['view']) || (isset($query['view']) && $query['view'] !== 'hotel') || isset($query['format']))
{
return;
}
$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']);
}
}
oraz com_hotels\src\Helper\RouteHelper.php

<?php/**
* @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/


namespace kb\Component\Hotels\Site\Helper;


defined('_JEXEC') or die;


use Joomla\CMS\Categories\CategoryNode;
use Joomla\CMS\Language\Multilanguage;


/**
* Component Route Helper.
*
* @since 1.5
*/
abstract class RouteHelper
{
/**
* Get the article route.
*
* @param integer $id The route of the content item.
* @param integer $language The language code.
* @param string $layout The layout value.
*
* @return string The article route.
*
* @since 1.5
*/
public static function getHotelRoute($id, $alias, $language = 0, $layout = null)
{
// Create the link
$link = 'index.php?option=com_hotels&view=hotel&id=' . $id . '&slug=' . $alias;




if ($layout)
{
$link .= '&layout=' . $layout;
}


return $link;
}
public static function getCountryRoute($id, $slug, $language = 0, $layout = null)
{
// Create the link
$link = 'index.php?option=com_hotels&view=country&id=' . $id . '&slug=' . $slug;




if ($layout)
{
$link .= '&layout=' . $layout;
}


return $link;
}


public static function getStateRoute($id, $alias, $language = 0, $layout = null)
{
// Create the link
$link = 'index.php?option=com_hotels&view=state&id=' . $id . '&alias=' . $alias;




if ($layout)
{
$link .= '&layout=' . $layout;
}


return $link;
}



public static function getCityRoute($id, $alias, $language = 0, $layout = null)
{
// Create the link
$link = 'index.php?option=com_hotels&view=city&id=' . $id . '&alias=' . $alias;




if ($layout)
{
$link .= '&layout=' . $layout;
}


return $link;
}


/**
* Get the category route.
*
* @param integer $catid The category ID.
* @param integer $language The language code.
* @param string $layout The layout value.
*
* @return string The article route.
*
* @since 1.5
*/
public static function getHotelsRoute($language = 0, $layout = null)
{


$link = 'index.php?option=com_hotels&view=hotels';


if ($language && $language !== '*' && Multilanguage::isEnabled())
{
$link .= '&lang=' . $language;
}


if ($layout)
{
$link .= '&layout=' . $layout;
}


return $link;
}
}

W momencie jeśli utworzę w Menu odnośnik do kraju wyświetla mi stronę z listą przypisanych regionów z linkami do regionu które tworzy RouteHelper.php


<a href="<?php echo Route::_(HotelsHelperRoute::getStateRoute($item->id, $item->alias)); ?>"><?php echo $item->name; ?></a>

ale link wygląda następująco:
http://localhost/joomla5/austria?view=state&id=369&alias=burgenland

W momencie jak utworze podmenu burgenland czyli Austria->burgenland i po kliknięciu w menu kraju generuje mi błąd:



Illegal offset type in isset or empty

Home Page (http://localhost/joomla5/index.php)
Call Stack



#
Function
Location


1
()
JROOT\libraries\src\Menu\AbstractMenu.php:164


2
Joomla\CMS\Menu\AbstractMenu->getItem()
JROOT\libraries\src\Router\SiteRouter.php:439


3
Joomla\CMS\Router\SiteRouter->buildSefRoute()
JROOT\libraries\src\Router\Router.php:407


4
Joomla\CMS\Router\Router->processBuildRules()
JROOT\libraries\src\Router\Router.php:194


5
Joomla\CMS\Router\Router->build()
JROOT\libraries\src\Router\Route.php:150


6
Joomla\CMS\Router\Route::link()
JROOT\libraries\src\Router\Route.php:99


7
Joomla\CMS\Router\Route::_()
JROOT\components\com_hotels\tmpl\country\default.p hp:46


8
include()
JROOT\libraries\src\MVC\View\HtmlView.php:416


9
Joomla\CMS\MVC\View\HtmlView->loadTemplate()
JROOT\libraries\src\MVC\View\HtmlView.php:204


10
Joomla\CMS\MVC\View\HtmlView->display()
JROOT\components\com_hotels\src\View\Country\HtmlV iew.php:67


11
kb\Component\Hotels\Site\View\Country\HtmlView->display()
JROOT\libraries\src\MVC\Controller\BaseController. php:697


12
Joomla\CMS\MVC\Controller\BaseController->display()
JROOT\components\com_hotels\src\Controller\Display Controller.php:35


13
kb\Component\Hotels\Site\Controller\DisplayControl ler->display()
JROOT\libraries\src\MVC\Controller\BaseController. php:730


14
Joomla\CMS\MVC\Controller\BaseController->execute()
JROOT\libraries\src\Dispatcher\ComponentDispatcher .php:143


15
Joomla\CMS\Dispatcher\ComponentDispatcher->dispatch()
JROOT\libraries\src\Component\ComponentHelper.php: 361


16
Joomla\CMS\Component\ComponentHelper::renderCompon ent()
JROOT\libraries\src\Application\SiteApplication.ph p:218


17
Joomla\CMS\Application\SiteApplication->dispatch()
JROOT\libraries\src\Application\SiteApplication.ph p:261


18
Joomla\CMS\Application\SiteApplication->doExecute()
JROOT\libraries\src\Application\CMSApplication.php :306


19
Joomla\CMS\Application\CMSApplication->execute()
JROOT\includes\app.php:58


20
require_once()
JROOT\index.php:32





Niestety dla mnie to czarna magia i nie wiem nawet co ten błąd może oznaczać...

Wzorowałem się na komponencie mywalks (https://docs.joomla.org/J4.x:J4_Component_example_-_Mywalks).

Ogólnie zamysł jest taki ze z menu głównego po kliknięciu w kraj otwiera się strona z listą regionów, po kliknięciu w region lista miast, analogicznie po kliknięciu w miasto lista hoteli.

Czy idę w dobrym kierunku czy może ten plik routera się nie nadaje do takiej struktury strony?