Joomla 3 для разработчиков: как сделать ЧПУ ссылки для своего компонента

13.10.2021

Ссылки в 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;
    }
}


Категории: CMS Joomla 3.X, Joomla
Яндекс.Метрика