Ссылки в CMS Joomla 3 давно уже не выглядят как /index.php?option=com_name&Itemid=14§ion=items&task=..., но ссылки на самописный компонент легко сделать в виде /blig/10, но часто этого недостаточно.
Ниже покажу как можно сделать настоящие ЧПУ ссылки.
Итак, дальше мы будем говорить о содержимом файла /components/com_NAME/router.php. Также нужно чтобы в таблице комопнента, например, в #__COM_NAME_items было поле cpu_name - собственно сама ЧПУ ссылка.
Основные моменты:
Минимум, без обработки ситуации, когда, к примеру, чпу не заполнено.
<?php
defined('_JEXEC') or die;
class SoShopRouter extends JComponentRouterBase
{
public function build(&$aQuery)
{
$db = JFactory::getDBO();
$id = (int) isset($aQuery['id'])?$aQuery['id']:0;
$sSql = 'SELECT id, cpu_name FROM #__COM_NAME_items WHERE id = ' . $id;
$db->setQuery($sSql);
$oRes = $db->loadObject();
$sUrl = $oRes->cpu_name;
$aSegments = [];
unset($aQuery['id']);
unset($aQuery['view']);
$aSegments[] = $sUrl;
return $aSegments;
}
public function parse(&$aSegments)
{
$aRet = array();
$sUrlPattern = '([\da-z\.-]+)';
$sUrl = $aSegments[0];
if (preg_match($sUrlPattern, $sUrl)) {
$db = JFactory::getDBO();
$sSql = 'SELECT id, cpu_name FROM #__COM_NAME_items WHERE cpu_name = "' . $sUrl . '"';
$db->setQuery($sSql);
$oRes = $db->loadObject();
$aRet['view'] = 'item';
$aRet['id'] = $oRes->id;
}
return $aRet;
}
}
Полный код:
<?php
defined('_JEXEC') or die;
/**
* Routing class
*
* @since 3.3
*/
class SoShopRouter extends JComponentRouterBase
{
/**
* Разбирает запись вида /category2 на category и 2
*
* @param array $aSegments - массив вхождений
* @param array $iCount - количество элементов в массиве
* @param string $sName
*
* @return string
*/
protected function _getValue(&$aSegments, &$iCount, $sName)
{
$sRet = '';
if(count($aSegments))
{
if(strpos($aSegments[0], $sName) === 0)
{
$sSegment = array_shift($aSegments); // Убирем 'category'
$iCount--;
$sRet = str_replace($sName, '', $sSegment);
}
}
return $sRet;
}
/**
* Build the route for the com_soblog component
*
* @param array &$aQuery An array of URL arguments
*
* @return array The URL arguments to use to assemble the subsequent URL.
*
* @since 3.3
*/
public function build(&$aQuery)
{
$db = JFactory::getDBO();
$id = (int) isset($aQuery['id'])?$aQuery['id']:0;
$id_category = (int) isset($aQuery['id_category'])?$aQuery['id_category']:0;
$sView = isset($aQuery['view'])?$aQuery['view']:'item';
$sSql = '';
switch ($sView) {
case 'item':
$sSql = 'SELECT id, cpu_name FROM #__COM_NAME_items WHERE id = ' . $id;
break;
case 'items':
$sSql = 'SELECT id, cpu_name FROM #__COM_NAME_categories WHERE id = ' . $id_category;
break;
}
$sUrl = '';
if ($sSql) {
$db->setQuery($sSql);
$oRes = $db->loadObject();
if ($oRes && $oRes->cpu_name) {
$sUrl = $oRes->cpu_name;
}
}
$aSegments = [];
if ($sUrl) {
unset($aQuery['id']);
unset($aQuery['id_category']);
unset($aQuery['view']);
$aSegments[] = $sUrl;
} else {
// view=item&id=2
$id = 0;
if (isset($aQuery['id']))
{
//$aSegments[] = $aQuery['id'];
$id = $aQuery['id'];
unset($aQuery['id']);
}
if (isset($aQuery['view']))
{
if($aQuery['view'] == 'item')
{
$aSegments[] = 'i'.$id;
}
else if($aQuery['view'] == 'items')
{
//$aSegments[] = 'c'.$id;
}
else
{
$aSegments[] = $aQuery['view'];
}
unset($aQuery['view']);
}
// Категории
if (isset($aQuery['id_category']))
{
$aSegments[] = 'category'.$aQuery['id_category'];
unset($aQuery['id_category']);
}
// Пагинация
// -- ?limitstart=0 - возвращение на 1ю страницу
if (isset($aQuery['limitstart']))
{
unset($aQuery['limitstart']);
}
// Пагинация
// -- ?start=10
if (isset($aQuery['start']))
{
$aSegments[] = 'start'.$aQuery['start'];
unset($aQuery['start']);
}
/*
if (isset($aQuery['task']))
{
$aSegments[] = $aQuery['task'];
unset($aQuery['task']);
}
*/
}
return $aSegments;
}
/**
* Parse the segments of a URL.
*
* @param array &$aSegments The segments of the URL to parse.
*
* @return array The URL attributes to be used by the application.
*
* @since 3.3
*/
public function parse(&$aSegments)
{
$aRet = array();
$sUrlPattern = '([\da-z\.-]+)';
$sUrl = $aSegments[0];
$bCpu = false;
if (preg_match($sUrlPattern, $sUrl)) {
$db = JFactory::getDBO();
$sSql = 'SELECT id, cpu_name FROM #__COM_NAME_items WHERE cpu_name = "/' . $sUrl . '/"';
$db->setQuery($sSql);
$oRes = $db->loadObject();
if ($oRes && $oRes->id) {
$aRet['view'] = 'item';
$aRet['id'] = $oRes->id;
$bCpu = true;
} else {
$sSql = 'SELECT id, cpu_name FROM #__COM_NAME_categories WHERE cpu_name = "/' . $sUrl . '/"';
$db->setQuery($sSql);
$oRes = $db->loadObject();
if ($oRes && $oRes->id) {
$aRet['view'] = 'items';
$aRet['id_category'] = $oRes->id;
$bCpu = true;
}
}
}
if (!$bCpu) {
$iCount = count($aSegments);
// Категории
$sVal = $this->_getValue($aSegments, $iCount, 'category');
if($sVal)
{
$aRet['view'] = 'items';
$aRet['id_category'] = (int) $sVal;
}
// Элементы
$sVal = $this->_getValue($aSegments, $iCount, 'i');
if($sVal)
{
$aRet['view'] = 'item';
$aRet['id'] = (int) $sVal;
}
// Пагинация
// -- ?start=10
$sVal = $this->_getValue($aSegments, $iCount, 'start');
if($sVal)
{
$aRet['limitstart'] = (int) $sVal;
}
/*echo '<pre>';
print_r($aRet);
echo '</pre>';*/
}
return $aRet;
}
}