您的位置:首页 > 编程语言 > PHP开发

[置顶] 简易PHP路由,支持正反向url解析支持

2016-08-25 17:16 281 查看
几年前实现了一个简单的正向路由,那时候不会写反向路由解析,最近通读qee v3的代码,因为其中已经扣除了路由解析这个功能,故自己结合之前的经验,发现写个简单的正反向路由解析还是蛮简单的,见代码:

 

<?php
/*
* 静态页配置文件
*
* key	为 pattern
* 值	为 配置参数
*
* 越上面的优先级越高
*/
return array(

array(
'pattern' => 'core-{id}-{name}.html',

'action'  => 'core/show',
'config'	=> array(
'id'	=> '[0-9]+',
'name'	=> '[a-z][a-z_0-9]+'
),
'default'	=> array(
'id'	=> 2,
'name'	=> 'sfken'
),
),

array(
'pattern' => 'admin.html',

'action'  => 'admin/index',
),

);

上面是配置文件

 

<?php
class Tool_PageStatic {

private $_obj_id;
private $_cache;
private $_accessor;
private $_config = array();

private $_result = array();

function __construct(array $config)
{
if ( empty($config['obj_id']) )
{
# 对象标识 用于缓存配置文件等用,标识系统中的 ps 对象的实例标识
throw BaseError::invalid_parameters_error('key "obj_id" not set');
}
$this->_obj_id = $config['obj_id'];

$this->_accessor = val( $config , 'accessor' , 'page' );
$this->_cache = val( $config , 'cache' , NULL );

$cfopt = val( $config , 'config' , null );
if ( !empty($cfopt) )
{
if ( is_array($cfopt) )
{
$this->loadConfig($cfopt);
}
if ( is_file($cfopt) )
{
# 如果是文件是否需要从缓存中进行读取,还是每次都要读取此处的配置文件

$cfopt = include($cfopt);
$this->loadConfig( (array) $cfopt);
}
}

$cfopt = null;

$this->default = array(
'action' => Config::get('app.default_action','index'),
'nocache' => TRUE,
'params' => array(),
);

}

private function loadConfig( array $config )
{
foreach ( $config as $opts )
{
# 对于 未设置 action & pattern 的配置项 直接忽略
if ( empty($opts['action']) || empty($opts['pattern']) ) continue;

$opts['src_pattern'] = $opts['pattern'];

if ( !empty($opts['config']) )
{
foreach($opts['config'] AS $conf_key => $conf_val)
{
$opts['pattern'] = str_replace('{'.$conf_key.'}', '('.$conf_val.')', $opts['pattern']);
}
}
else
{
$opts['config'] = array();
}
if ( empty($opts['default']) ) $opts['default'] = array();

$this->_config[strtolower($opts['action'])] = $opts;
}

# 解析完成后是否可以存入缓存
}

function getAccessor()
{
return $this->_accessor;
}

/**
* 解析 string 返回对应的action以及相应的参数
*
* @param string $string
*
* @return array
*/
function parsing($string)
{
//		dump($this->_config);

if ( empty($string) || empty($this->_config) ) return $this->default;

if ( empty($this->_result[$string]) )
{
$d = $this->default;

foreach($this->_config AS $opts)
{
if (preg_match('#^'.$opts['pattern'].'/?$#i', $string, $match_result))
{
//					dump($match_result);

# offset 为0 是 原字符串
$offset = 1;
foreach($opts['config'] AS $conf_key => $conf_val)
{
if(isset($match_result[$offset]))
{
$d['params'][$conf_key] = $match_result[$offset++];
}
}

$d['nocache'] = val($opts,'nocache',$d['nocache']);
$d['action'] = $opts['action'];
break;
}
}

$this->_result[$string] = $d;
}

return $this->_result[$string];
}

/**
* 生成静态的 url 地址
*
* @param string $action_name
* @param array $params
*/
function psurl( $action_name , array $params = null )
{
$opts = val( $this->_config , strtolower($action_name) , null );
if ( !empty($opts) )
{
$params = (array) $params;

# 使用源 $opts['src_pattern']
$url = $opts['src_pattern'];
dump($url);
foreach($opts['default'] AS $d_key => $d_val)
{
if ( !empty($params[$d_key]) )
{
$d_val = $params[$d_key];
unset($params[$d_key]);
}
//        		$url = str_replace(':'.$d_key, $d_val, $url);
$url = str_replace('{'.$d_key.'}', $d_val, $url);
}
return $url . '?' . http_build_query($params);
}

# 如果没有找到就生成原始的url
return url($action_name , $params);
}

}

 上面是真正的实现代码

 

下面是调用代码

<?php
/**
* 站点静态化操作
*
* /static/page/article-php-json_encode.html
*
*
*/
class Action_Static extends BaseAction
{

protected function _validate_input()
{
$engine = $this->app->tool('pagestatic');
$accessor = $engine->getAccessor();

$this->pid = $_GET[$accessor];// page 标识

if ( !empty($this->pid) && strlen($this->pid) < 230 )
{
// 为什么不在此处直接读缓存? 目的是实现未在配置文件中定义的过期缓存全部设为失效

$this->pparams = (array) $engine->parsing($this->pid);// page 参数

if ( !empty($this->pparams) )
{
return true;
}

}

return false;
}

/**
* 请求前对数据进行验证失败时调用此方法
*/
protected function _on_validate_input_failed()
{
// 记录错误日志(将 pid 记录到错误日志中)

// 跳转到首页
redirect( url(Config::get('app.default_action','index')) );
}

function execute()
{
$cached = val($this->pparams,'nocache',FALSE);

dump($this->pparams,$this->pid);

dump( $this->app->tool('pagestatic')->psurl('core/show',array(
'id' => '449211678',
'name' => 'kenxu',
'age' => '29',
//			'blog' => 'http://vb2005xu.iteye.com',
)) );
}
}

 

输出结果如下:
http://sfken.xu/static/page/admin.html 写道
admin.html :
Array
(
[action] => admin/index
[nocache] => 1
[params] => Array
(
)

)

core-{id}-{name}.html

core-449211678-kenxu.html?age=29
 
http://sfken.xu/static/page/core-12306-tianchao.html 写道
core-12306-tianchao.html :
Array
(
[action] => core/show
[nocache] => 1
[params] => Array
(
[id] => 12306
[name] => tianchao
)

)

core-{id}-{name}.html

core-449211678-kenxu.html?age=29

 

在我当前的设计中 此路由功能只能算是一个工具类,用于实现 伪静态/或者页缓存用的,功能上只支持指定action的操作,如果诸位有需要,此处就算我 抛砖引玉了....

 

代码很少,也就不一一解释了

qart-dev.rar (13.7 KB)

下载次数: 40
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: