Solution found, thank you all for your help
I found that a new file (ComponentnameComponent.php) is require as I understand. I don't know is the "best pratice" for J4 but it's work.
To summerize all what I need to create a routing in J4 (with same behavior that J3) :
/com_componentname/src/Service/Router.php
Code: Select all
<?php
namespace Componentname\Component\Componentname\Site\Service;
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\MenuRules;
//use Joomla\CMS\Component\Router\Rules\NomenuRules;
use Componentname\Component\Componentname\Site\Service\ComponentnameNomenuRules as NomenuRules;
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;
class Router extends RouterView
{
protected $noIDs = false;
private $categoryFactory;
private $categoryCache = [];
private $db;
public function __construct(SiteApplication $app, AbstractMenu $menu, CategoryFactoryInterface $categoryFactory, DatabaseInterface $db)
{
$params = Factory::getApplication()->getParams('com_componentname');
$this->noIDs = (bool) $params->get('sef_ids');
$this->categoryFactory = $categoryFactory;
$this->db = $db;
$viewname = new RouterViewConfiguration('viewname');
$this->registerView($viewname);
parent::__construct($app, $menu);
$this->attachRule(new MenuRules($this));
$this->attachRule(new StandardRules($this));
$this->attachRule(new NomenuRules($this));
}
/**
* @param array A named array
* @return array
*/
function ViewnameBuildRoute(&$query) {
$segments = array();
if (isset($query['task'])) {
$segments[] = implode('/', explode('.', $query['task']));
unset($query['task']);
}
if (isset($query['view'])) {
$segments[] = $query['view'];
unset($query['view']);
}
if (isset($query['id'])) {
$segments[] = $query['id'];
unset($query['id']);
}
return $segments;
}
function ViewnameParseRoute($segments) {
$vars = array();
// view is always the first element of the array
$vars['view'] = array_shift($segments);
while(!empty($segments)) {
$segment = array_pop($segments);
if (is_numeric($segment)) {
$vars['id'] = $segment;
} else {
$vars['task'] = $vars['view'] . '.' . $segment;
}
}
return $vars;
}
}
/com_componentname/src/Service/ComponentnameNomenuRules.php
Code: Select all
<?php
namespace Componentname\Component\Componentname\Site\Service;
defined('_JEXEC') or die;
use Joomla\CMS\Component\Router\RouterView;
use Joomla\CMS\Component\Router\Rules\RulesInterface;
/**
* Rule to process URLs without a menu item
*
* @since 3.4
*/
class ComponentnameNomenuRules implements RulesInterface
{
protected $router;
public function __construct(RouterView $router)
{
$this->router = $router;
}
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'] = 'viewname';
$vars['id'] = substr($segments[0], strpos($segments[0], '-') + 1);
array_shift($segments);
array_shift($segments);
return;
}
public function build(&$query, &$segments)
{
if (!isset($query['view']) || (isset($query['view']) && $query['view'] !== 'viewname') || 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']);
}
}
/administrator/components/com_componentname/services/provider.php
Code: Select all
<?php
// no direct access
defined('_JEXEC') or die;
use Joomla\CMS\Extension\MVCComponent;
use Componentname\Component\Componentname\Administrator\Extension\ComponentnameComponent;
use Joomla\CMS\Categories\CategoryFactoryInterface;
use Joomla\CMS\Component\Router\RouterFactoryInterface;
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
use Joomla\CMS\Extension\ComponentInterface;
use Joomla\CMS\Extension\Service\Provider\CategoryFactory;
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
use Joomla\CMS\Extension\Service\Provider\RouterFactory;
use Joomla\CMS\HTML\Registry;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
return new class implements ServiceProviderInterface
{
public function register(Container $container)
{
$container->registerServiceProvider(new CategoryFactory('\\Componentname\\Component\\Componentname'));
$container->registerServiceProvider(new MVCFactory('\\Componentname\\Component\\Componentname'));
$container->registerServiceProvider(new ComponentDispatcherFactory('\\Componentname\\Component\\Componentname'));
$container->registerServiceProvider(new RouterFactory('\\Componentname\\Component\\Componentname'));
$container->set(
ComponentInterface::class,
function (Container $container)
{
$component = new ComponentnameComponent($container->get(ComponentDispatcherFactoryInterface::class));
$component->setRegistry($container->get(Registry::class));
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
$component->setCategoryFactory($container->get(CategoryFactoryInterface::class));
$component->setRouterFactory($container->get(RouterFactoryInterface::class));
return $component;
}
);
}
};
/administrator/components/com_componentname/src/Extension/ComponentnameComponent.php
Code: Select all
<?php
namespace Componentname\Component\Componentname\Administrator\Extension;
defined('_JEXEC') or die;
use Joomla\CMS\Application\SiteApplication;
use Joomla\CMS\Association\AssociationServiceInterface;
use Joomla\CMS\Association\AssociationServiceTrait;
use Joomla\CMS\Categories\CategoryServiceInterface;
use Joomla\CMS\Categories\CategoryServiceTrait;
use Joomla\CMS\Extension\BootableExtensionInterface;
use Joomla\CMS\Extension\MVCComponent;
use Joomla\CMS\HTML\HTMLRegistryAwareTrait;
use FooNamespace\Component\Foos\Administrator\Service\HTML\AdministratorService;
use FooNamespace\Component\Foos\Administrator\Service\HTML\Icon;
use Psr\Container\ContainerInterface;
use Joomla\CMS\Helper\ContentHelper;
use Joomla\CMS\Component\Router\RouterServiceInterface;
use Joomla\CMS\Component\Router\RouterServiceTrait;
/**
* Component class for com_foos
*
* @since __BUMP_VERSION__
*/
class ComponentnameComponent extends MVCComponent implements BootableExtensionInterface, CategoryServiceInterface, AssociationServiceInterface, RouterServiceInterface
{
use CategoryServiceTrait;
use AssociationServiceTrait;
use HTMLRegistryAwareTrait;
use RouterServiceTrait;
/**
* Booting the extension. This is the function to set up the environment of the extension like
* registering new class loaders, etc.
*
* If required, some initial set up can be done from services of the container, eg.
* registering HTML services.
*
* @param ContainerInterface $container The container
*
* @return void
*
* @since __BUMP_VERSION__
*/
public function boot(ContainerInterface $container)
{
//$this->getRegistry()->register('foosadministrator', new AdministratorService);
//$this->getRegistry()->register('fooicon', new Icon($container->get(SiteApplication::class)));
}
/**
* Adds Count Items for Category Manager.
*
* @param \stdClass[] $items The category objects
* @param string $section The section
*
* @return void
*
* @since __BUMP_VERSION__
*/
public function countItems(array $items, string $section)
{
/*try {
$config = (object) [
'related_tbl' => $this->getTableNameForSection($section),
'state_col' => 'published',
'group_col' => 'catid',
'relation_type' => 'category_or_group',
];
ContentHelper::countRelations($items, $config);
} catch (\Exception $e) {
// Ignore it
}*/
}
/**
* Returns the table for the count items functions for the given section.
*
* @param string $section The section
*
* @return string|null
*
* @since __BUMP_VERSION__
*/
protected function getTableNameForSection(string $section = null)
{
//return ($section === 'category' ? 'categories' : 'foos_details');
}
/**
* Returns the state column for the count items functions for the given section.
*
* @param string $section The section
*
* @return string|null
*
* @since __BUMP_VERSION__
*/
protected function getStateColumnForSection(string $section = null)
{
//return 'published';
}
}