Joomla自定义URL的规范和实现

Joomla! 1.5生成部分已经彻底重构了.Joomla!可以生成和解析任何格式的url,包括那些可读性的url。

本文翻译了关于自定义URL的规范和实现过程。

简介

Joomla! 1.5生成部分已经彻底重构了.Joomla!可以生成和解析任何格式的url,包括那些可读性的url。另一项改进是即使在不是apache的mod_rewrite服务器上,Joomla的这部分功能仍然可以运行。

Joomla! is now capable of creating and parsing URLs in any format, including human readable URL‘s. Another improvement is that this still works even if Joomla! runs a server other than Apache with the mod_rewrite module.

下面是一个例子,第一个是没有mod_rewrite的情况下生成的,第二个是采用mod_write生成的。

http://www.example.com/index.php/the-news/1-latest-news/1-welcome-to-joomla
http://www.example.com/the-news/1-latest-news/1-welcome-to-joomla


别名(短名称)


首先要生成alias,这个alias用在URL中,这个alias是符合URI规范的,也就是说相应的UTF-8字符被替换为ASCII-7 ,空格用连词符替代,等等。

The alias 也可以由用户定义,但是必须保证符合uri的规范,最好是在保存的时候采用 JTable::check()进行检查。请看下面的例子:

function check()
{
       jimport( 'joomla.filter.output' );
       $alias = JOutputFilter::stringURLSafe( $this?->title );
       if(empty( $this?->alias ) || $this?->alias === $alias ) {
               $this?->alias = $alias;
       }
       /* All your other checks */
       return true;
}

如果alias字段为空或者符合uri规范,才能使用这个alias.



The Slug(how to translate)

回过来看我们的例子“slug” - “1-welcome-to-joomla”有两部分,第一部分是文章的唯一编号,第二部分是alias,中间是连词符,这两个部分通常在查询的时候被组合在一起。


$query = 'SELECT a.*'.
        ' CASE WHEN CHAR_LENGTH (a.alias) THEN CONCAT_WS(/':/', a.id, a.alias) ELSE a.id END as slug,'.
        [...];After this step the slug is used instead of the id.

JRoute


The JRoute::_() 转换内部的Joomla URL为一个自定义的URL,有三个参数

JRoute::_( $url, $xhtml = true, $ssl=0 );

$url是Joomal的内部相对或者绝对的路径,$xhtml是否XHTML格式输出,默认为真。$ssl表示是否采用https协议,0代表采用$url中默认的状态,而1强制采用https,-1强制采用http

应该这样使用:

JRoute::_( 'index.php?view=article&id='.$row?->slug );

row->slug 前文提到的,文章id和alias的组合

采用JRoute的另一个好处是router现在处理$option和$Itemid(菜单项编号),这样component就不必管理$option或者活动菜单项。而以前的版本必须这样做。

URL参数的顺序是非常重要的,这一点在以后我们深入到router.php内部的时候就非常清楚了。


JRouter生成URL的过程分为两个步骤

创建application route:

appliction route 完全由JRouter处理,组件开发者不必做任何事情。

创建component route

为了创建component route, JRouter查找组件目录中 router.php,router.php负责构造组件的route.


router.php

router.php中通常有两个函数。一个负责构造URL,另一个负责解析,接下来请看两个例子:假设有单个views,其中一是view=categories,第二个是view=category,第三个是view=article。


简单例子,这个例子简单实现了组件的自定义URL

function [Componentname]BuildRoute( &$query )
{
       $segments = array();
       if(isset($query['view']))
       {
                $segments[] = $query['view'];
                unset( $query['view'] );
       }
       if(isset($query['id']))
       {
                $segments[] = $query['id'];
                unset( $query['id'] );
       };
       return $segments;
}

JRouter 传递$query数组到[Componentname]BuildRoute函数中,这个函数将$query的对应内容按一定的顺序填 充$segments数组,而$query数组的相应内容被清空,其余$query为被清除的部分将作为query字串传递给router.

router.php中另一个函数解析URL

function [Componentname]ParseRoute( $segments )
{
       $vars = array();
       switch($segments[0])
       {
               case 'categories':
                       $vars['view'] = 'categories';
                       break;
               case 'category':
                       $vars['view'] = 'category';
                       $id = explode( ':', $segments[1] );
                       $vars['id'] = (int) $id[0];
                       break;
               case 'article':
                       $vars['view'] = 'article';
                       $id = explode( ':', $segments[1] );
                       $vars['id'] = (int) $id[0];
                       break;
       }
       return $vars;
}

[Componentname]BuildRoute函数以指定的顺序组织$query中的项,也就是说在这个例子中第一是view,第二是catid,第三是id
,$vars数组返回给JRouter,$var一定程度上与传递给BuildRoute的数组是相似的。

上一个简单例子中并没能体现出内容分类的层级关系

下面我们来看一个更复杂一些的例子,这个例子中我们尽可能的展示内容分类的层级关系,并去掉关于url中的view部分。

来看看以下这些我们将要构造的URL

When viewing an article: http://www.example.com/[menualias]/[category]/[article]
When viewing a category: http://www.example.com/[menualias]/[category]
When viewing the categories overview: http://www.example.com/[menualias]

我们直接来将是router.php,假设文章link的Joomla内部地址如下:

JRoute::_( 'index.php?view=article&catid='.$row?->catslug .'&id='.$row?->slug );

假设文章的分类的URL地址如下:

JRoute::_( 'index.php?view=category&id='.$row?->catslug );The corresponding router.php:

function [Componentname]BuildRoute(&$query)
{
       $segments = array();
       if(isset( $query['catid'] ))
       {
                $segments[] = $query['catid'];
                unset( $query['catid'] );
       };
       if( isset($query['id']) )
       {
                $segments[] = $query['id'];
                unset( $query['id'] );
       };
       unset( $query['view'] );
       return $segments;
}

与前例不同的是,并没有将view添加到$segments数组中,并且将$view清空。另一件事情是将catid添加到$segments中。

function [Componentname]ParseRoute($segments)
{
       $vars = array();
       $menu =& JMenu::getInstance();
       $item =& $menu?->getActive();
       // Count segments
       $count = count( $segments );
       //Handle View and Identifier
       switch( $item?->query['view'] )
       {
               case 'categories':
                       if($count == 1) {
                               $vars['view'] = 'category';
                       }
                       if($count == 2) {
                               $vars['view'] = 'article';
                       }
                       $id = explode( ':', $segments[$count?-1] );
                       $vars['id'] = (int) $id[0];
                       break;
               case 'category':
                       $id   = explode( ':', $segments[$count?-1] );
                       $vars['id']   = (int) $id[0];
                       $vars['view'] = 'article';
                       break;
       }
       return $vars;
}

ParseRoute 和前例有很多不同,原因很简单,因为我们没有view的名字,那么就必须通过其他方式来确定,目前我们可以通过活动菜单的view来觉得当前请求是那个级 别的内容。而通过$count = count( $segments )获得参数的个数,就可以决定是指向一个category的链接还是文章的链接。

由此,实现了可以自定义URL,并且URL的可读性很强

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值