在早起的项目开发中都是先正常开发使用动态地址访问,接近完成时才对链接rewrite处理,这样会有一个坑,那么多页面那么多的链接一个个按照rewrite规则去改真是受够了。自使用Yii框架后这些问题就很容易解决,在控制器中使用 $this->createUrl() 处理也可以覆写父方法重定处理URL方式。
最近使用Yaf开发的项目,于项目启动时就已对URL链接作了规划,使用Yii的方式处理。
由于Yaf中 new Controller 会报Warning,下面这段是在鸟哥的留言板(/guestbook?cp=18)里看到的:
class a extends Yaf_Controller_Abstract{
}
new a();
Warning: Yaf_Controller_Abstract::__construct() expects at least 3 parameters, 0 given in test.php on line 7
虽不规范但Warning是一样的,所以干脆绕开这步:
在 /application/library 目录里添加 CUrl 处理类,其中后面两方法是改的Yii的:
<?php
/**
* Url Generator
*
* @category
* @author Shi Xue
* @date 2017-09
*/
class CUrl
{
/**
* @var string / | http://xxx.com/
*/
private static $baseUrl = '/index.php/';
/**
* @var string .html
*/
private static $urlSuffix = '';
/**
* Create URL
* 当控制器存在 createUrl() 方法时则优先调用控制器内部的,如果没有则调用默认的
* @param string $route
* home (HomeController, Index Action)
* home/index (HomeController, Index Action)
* m/home/index (M Module, HomeController, Index Action)
* @param array $params
* @param string $ampersand
* @return string
*/
public static function createUrl($route, $params=array(), $ampersand='&')
{
$controller = '';
if(strpos($route, '/')){
$routeArr = explode('/', $route);
$controller = count($routeArr) > 2 ? ucfirst($routeArr[1]) .'Controller' : ucfirst($routeArr[0]) .'Controller';
}else{
$controller = ucfirst($route) .'Controller';
}
if(class_exists($controller) && method_exists($controller, 'createUrl'))
return $controller::createUrl($route, $params, $ampersand); //也可配置规则路由实现,避免在多个控制器内添加静态方法
else
return self::createUrlDefault($route, $params, $ampersand);
}
/**
* URL
* @param string $route
* @param array $params
* @param string $ampersand
* @return string
*/
public static function createUrlDefault($route, $params=array(), $ampersand='&')
{
$request = Yaf_Application::app()->getDispatcher()->getRequest();
$route = trim($route,'/');
if($route==='')
$route = $request->controller . '/' . $request->action;
//elseif(strpos($route, '/')===false)
// $route = $request->controller . '/' . $route;
/*
//下面 createPathInfo 中过滤 param=null 的参数,保留参数可用 param=''
foreach($params as $i=>$param)
if($param===null)
$params[$i]='';
*/
if(isset($params['#']))
{
$anchor='#'.$params['#'];
unset($params['#']);
}
else
$anchor='';
$url = self::$baseUrl . $route . self::$urlSuffix;
$pstr = self::createPathInfo($params, '=', $ampersand);
if($pstr || $anchor)
$url .= '?' . $pstr . $anchor;
return $url;
}
/**
* Params
* @return string param1=val1¶m2=val2
*/
private static function createPathInfo($params, $equal, $ampersand)
{
$pairs = array();
foreach($params as $k => $v)
{
if (is_array($v))
$pairs[]=self::createPathInfo($v,$equal,$ampersand);
elseif ($v !== null) //else
$pairs[]=urlencode($k).$equal.urlencode($v);
}
return implode($ampersand,$pairs);
}
}
模板中调用,参数以数组键值对传入:
<a href="<?=CUrl::createUrl('home/index', array('from' => 'listpage')) ?>">首页</a>
如果某个控制器下的链接需要单独处理,可在控制器中添加 createUrl():
class HomeController extends ApplicationController
{
public function indexAction()
{
}
/**
* Create URL
* @return string
* /baojia/bj.html
* /baojia/bj_p1.html
* /baojia/bj_12_r0_p1.html
*/
public static function createUrl($route, $params=array(), $ampersand='_')
{
//默认生成URL方法
//return CUrl::createUrlDefault($route, $params, $ampersand);
//自定义
//...
//设定参数顺序, 同时排除非需要的参数
$setParameter = array('city', 'price', 'sort', 'page');
$curl = '/baojia/';
$strParam = array();
foreach($setParameter as $able)
{
if( isset($params[$able]) && $params[$able] !== null )
{
switch ($able)
{
case 'sort':
$strParam[] = 'r'. $params[$able];
break;
case 'page':
$strParam[] = 'p'. $params[$able];
break;
default:
$strParam[] = $params[$able];
}
}
}
if($strParam)
$curl .= implode($ampersand, $strParam) .'.html';
return $curl;
}
}
控制器内 createUrl() 的参数需与 CUrl 类的参数一致,否则可能会报 PHP Strict Standards。