php yaf 2.3.5,ThinkPHP、ZF2、Yaf、Laravel框架路由大比拼

前言

读过一篇关于Zend Framework2的技术文章《ZF2多级树形路由Route配置实例》,是介绍路由配置的。我觉得很有意思,这是的需求:

/user对应用户列表页面

/user/:user_id对应用户的个人主页,比如 /user/AlloVince 就对应AlloVince用户的个人主页

/user/:user_id/blog/对应用户的博客列表页面,比如 /user/AlloVince/blog 就会列出AlloVince写过的Blog

/user/:user_id/blog/:blog_id对应用户的一篇博客文章

方案引用自原文:

'router' => array(

'routes' => array(

'user' => array(

'type' => 'Segment',

'options' => array(

'route' => '/user[/]',

'defaults' => array(

'controller' => 'UserController',

'action' => 'index',

),

),

'may_terminate' => true,

'child_routes' => array(

'profile' => array(

'type' => 'Segment',

'options' => array(

'route' => '[:id][/]',

'constraints' => array(

'id' => '[a-zA-Z0-9_-]+'

),

'defaults' => array(

'action' => 'get'

),

),

'may_terminate' => true,

'child_routes' => array(

'blog' => array(

'type' => 'Segment',

'options' => array(

'route' => 'blog[/]',

'constraints' => array(

),

'defaults' => array(

'action' => 'blog'

)

),

'may_terminate' => true,

'child_routes' => array(

'post' => array(

'type' => 'Segment',

'options' => array(

'route' => '[:post_id][/]',

'constraints' => array(

'post_id' => '[a-zA-Z0-9_-]+'

),

'defaults' => array(

'action' => 'post'

)

),

'may_terminate' => true,

),

),

),

), //profile child_routes end

), //profile end

), //user child_routes end

), //user end

),

),

看了这篇文章后,我打算使用我用过的PHP框架来实现这个路由需求。

ThinkPHP

新建一个ThinkPHP项目:

composer create-project topthink/thinkphp tp --prefer-dist

命令行显示我安装的是3.2.2

Installing topthink/thinkphp (3.2.2)

我看ThinkPHP官网最新稳定版本是3.2.3。

我特意去packagist官网查了一下,库中稳定版确实是3.2.2。

我得使用3.2.3。为什么我特别纠结这一点哩?因为:

3.2的路由功能是针对模块设置的,所以URL中的模块名不能被路由,路由定义也通常是放在模块配置文件中。 3.2.3版本开始增加全局路由定义支持,可以在项目的公共配置文件中定义路由。

也就是说,路由重写的部分是Controller和Action部分,Moudle还是存在。

我希望的是/user,而不是home/user。(ThinkPHP中默认Module是Home,'DEFAULT_MODULE' => 'Home',可以修改)

当然,这个问题也可以修改.htaccess文件的解决。但是,我还是决定安装3.2.3。

在ThinkPHP官网下载最新的包,解压。

使用浏览器访问一下项目的入口文件,让ThinkPHP自动生成了一个默认的应用模块Home。

修改公共配置文件tp\Application\Common\Conf\config.php:

return array(

// 开启路由

'URL_ROUTER_ON' => true,

// URL访问模式,可选参数0、1、2、3,代表以下四种模式:

// 0 (普通模式); 1 (PATHINFO 模式); 2 (REWRITE 模式); 3 (兼容模式) 默认为PATHINFO 模式

'URL_MODEL' => 2,

// URL伪静态后缀设置,为空表示可以支持所有的静态后缀

// 使用U函数生成URL时会不带后缀

'URL_HTML_SUFFIX' => '',

// URL变量绑定到Action方法参数,默认为true

'URL_PARAMS_BIND' => true,

// URL变量绑定的类型 0 按变量名绑定 1 按变量顺序绑定,默认为0

'URL_PARAMS_BIND_TYPE' => 0,

// 路由配置

'URL_ROUTE_RULES' => array(

'/^url$/' => 'Home/User/url',

'/^user$/' => 'Home/User/index',

'/^user\/([a-zA-Z0-9_-]+)$/' => 'Home/User/show?name=:1',

'/^user\/([a-zA-Z0-9_-]+)\/blog$/' => 'Home/Blog/index?name=:1',

'/^user\/([a-zA-Z0-9_-]+)\/blog\/([0-9]+)$/' => 'Home/Blog/show?name=:1&blog_id=:2',

),

);

?>

创建文件tp\Application\Home\Controller\UserController.class.php:

namespace Home\Controller;

use Think\Controller;

class UserController extends Controller {

public function url() {

$name = 'jing';

$blogId = 1;

$urls = array(

U('/user'),

U("/user/{$name}"),

U("/user/{$name}/blog"),

U("/user/{$name}/blog/{$blogId}"),

);

foreach ($urls as $url) {

echo "{$url}
\n";

}

}

public function index() {

echo '我是用户列表^_^';

}

public function show($name) {

echo "欢迎你,{$name}";

}

}

?>

创建文件tp\Application\Home\Controller\BlogController.class.php:

namespace Home\Controller;

use Think\Controller;

class BlogController extends Controller {

public function index($name) {

echo "这是{$name}的博客列表";

}

public function show($blog_id, $name) {

echo "{$name}的这篇博客的id为{$blog_id}";

}

}

?>

输出:

/tp/user

/tp/user/jing

/tp/user/jing/blog

/tp/user/jing/blog/1

访问上面4个链接,依次返回:

我是用户列表^_^

欢迎你,jing

这是jing的博客列表

jing的这篇博客的id为1

下面其他框架,也同样输出以上内容。

Zend Framework 2

使用ZF2骨架程序创建一个ZF2项目:

composer create-project --stability="dev" zendframework/skeleton-application zf2

修改默认模块Application的配置文件zf2\module\Application\config\module.config.php:

/**

* Zend Framework (http://framework.zend.com/)

*

* @link http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository

* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)

* @license http://framework.zend.com/license/new-bsd New BSD License

*/

return array(

'router' => array(

'routes' => array(

'home' => array(

'type' => 'Zend\Mvc\Router\Http\Literal',

'options' => array(

'route' => '/url',

'defaults' => array(

'controller' => 'Application\Controller\User',

'action' => 'url',

),

),

),

// The following is a route to simplify getting started creating

// new controllers and actions without needing to create a new

// module. Simply drop new controllers in, and you can access them

// using the path /application/:controller/:action

'application' => array(

'type' => 'Literal',

'options' => array(

'route' => '/application',

'defaults' => array(

'__NAMESPACE__' => 'Application\Controller',

'controller' => 'Index',

'action' => 'index',

),

),

'may_terminate' => true,

'child_routes' => array(

'default' => array(

'type' => 'Segment',

'options' => array(

'route' => '/[:controller[/:action]]',

'constraints' => array(

'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',

'action' => '[a-zA-Z][a-zA-Z0-9_-]*',

),

'defaults' => array(

),

),

),

),

),

'user_list' => array(

'type' => 'Segment',

'options' => array(

'route' => '/user[/]',

'defaults' => array(

'__NAMESPACE__' => 'Application\Controller',

'controller' => 'User',

'action' => 'index',

),

),

'may_terminate' => true,

'child_routes' => array(

'user' => array(

'type' => 'Segment',

'options' => array(

'route' => '[:name][/]',

'constraints' => array(

'name' => '[a-zA-Z0-9_-]+',

),

'defaults' => array(

'action' => 'show',

),

),

'may_terminate' => true,

'child_routes' => array(

'blog_list' => array(

'type' => 'Segment',

'options' => array(

'route' => 'blog[/]',

'constraints' => array(

),

'defaults' => array(

'controller' => 'Blog',

'action' => 'index',

)

),

'may_terminate' => true,

'child_routes' => array(

'blog' => array(

'type' => 'Segment',

'options' => array(

'route' => '[:blog_id]',

'constraints' => array(

'blog_id' => '[0-9]+',

),

'defaults' => array(

'action' => 'show',

)

),

'may_terminate' => true,

),

),

),

),

),

),

),

),

),

'service_manager' => array(

'abstract_factories' => array(

'Zend\Cache\Service\StorageCacheAbstractServiceFactory',

'Zend\Log\LoggerAbstractServiceFactory',

),

'aliases' => array(

'translator' => 'MvcTranslator',

),

),

'translator' => array(

'locale' => 'en_US',

'translation_file_patterns' => array(

array(

'type' => 'gettext',

'base_dir' => __DIR__ . '/../language',

'pattern' => '%s.mo',

),

),

),

'controllers' => array(

'invokables' => array(

'Application\Controller\Index' => 'Application\Controller\IndexController',

'Application\Controller\User' => 'Application\Controller\UserController',

'Application\Controller\Blog' => 'Application\Controller\BlogController',

),

),

'view_manager' => array(

'display_not_found_reason' => true,

'display_exceptions' => true,

'doctype' => 'HTML5',

'not_found_template' => 'error/404',

'exception_template' => 'error/index',

'template_map' => array(

'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',

'application/index/index' => __DIR__ . '/../view/application/index/index.phtml',

'error/404' => __DIR__ . '/../view/error/404.phtml',

'error/index' => __DIR__ . '/../view/error/index.phtml',

),

'template_path_stack' => array(

__DIR__ . '/../view',

),

),

// Placeholder for console routes

'console' => array(

'router' => array(

'routes' => array(

),

),

),

);

?>

这个文件是骨架程序中自带的,我只是修改了router部分和controllers部分。要我写这么长的文件,那就太为难我了。这也是ZF官方发布了一个骨架程序的原因。

创建文件zf2\module\Application\src\Application\Controller\UserController.php:

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;

use Zend\View\Model\ViewModel;

class UserController extends AbstractActionController {

public function urlAction() {

$name = 'jing';

$blogId = 1;

$urls = array(

$this->url()->fromRoute('user_list'),

$this->url()->fromRoute('user_list/user', array('name' => $name)),

$this->url()->fromRoute('user_list/user/blog_list', array('name' => $name)),

$this->url()->fromRoute('user_list/user/blog_list/blog', array('name' => $name, 'blog_id' => $blogId)),

);

$view = new ViewModel(compact('urls'));

$view->setTerminal(true);

return $view;

}

public function indexAction() {

$view = new ViewModel();

// 禁用布局模板

$view->setTerminal(true);

return $view;

}

public function showAction() {

$username = $this->params()->fromRoute('name');

$view = new ViewModel(compact('username'));

$view->setTerminal(true);

return $view;

}

}

?>

创建文件zf2\module\Application\src\Application\Controller\BlogController.php:

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;

use Zend\View\Model\ViewModel;

class BlogController extends AbstractActionController {

public function indexAction() {

$username = $this->params()->fromRoute('name');

$view = new ViewModel(compact('username'));

$view->setTerminal(true);

return $view;

}

public function showAction() {

$username = $this->params()->fromRoute('name');

$blogId = $this->params()->fromRoute('blog_id');

$view = new ViewModel(compact('username', 'blogId'));

$view->setTerminal(true);

return $view;

}

}

?>

zf2不支持Action参数绑定,ThinkPHP不仅支持绑定,还支持2种绑定方式:按变量名绑定和按变量顺序绑定。

zf2中Action必须得返回视图,除非exit()。如果你知道可以禁用视图的办法,请告诉我。

创建文件zf2\module\Application\view\application\user\url.phtml:

<?php echo $url;?>

创建文件zf2\module\Application\view\application\user\index.phtml:

我是用户列表^_^

创建文件zf2\module\Application\view\application\user\show.phtml:

欢迎你,<?php echo $username; ?>

创建文件zf2\module\Application\view\application\blog\index.phtml:

这是<?php echo $username; ?>的博客列表

创建文件zf2\module\Application\view\application\blog\show.phtml:

<?php echo $username; ?>的这篇博客的id为<?php echo $blogId; ?>

Yaf

安装Yaf

使用代码生成工具创建Yaf项目

修改启动文件yaf\application\Bootstrap.php,修改其中的_initRoute方法:

$router = Yaf_Dispatcher::getInstance()->getRouter();

$route0 = new Yaf_Route_Rewrite('url', array(

'controller' => 'User',

'action' => 'url',

), array()

);

$route1 = new Yaf_Route_Rewrite('user', array(

'controller' => 'User',

'action' => 'index',

), array()

);

$route2 = new Yaf_Route_Regex('#user/([a-zA-Z0-9_-]+)#', array(

'controller' => 'User',

'action' => 'show',

), array(1 => 'name',)

);

$route3 = new Yaf_Route_Regex('#user/([a-zA-Z0-9_-]+)/blog#', array(

'controller' => 'Blog',

'action' => 'index',

), array(1 => 'name',)

);

$route4 = new Yaf_Route_Regex('#user/([a-zA-Z0-9_-]+)/blog/([0-9]+)#', array(

'controller' => 'Blog',

'action' => 'show',

), array(1 => 'name', 2 => 'blogId',)

);

$router->addRoute('url', $route0);

$router->addRoute('user_list', $route1);

$router->addRoute('user', $route2);

$router->addRoute("blog_list", $route3);

$router->addRoute("blog", $route4);

Yaf有路由功能,但是没有根据路由名生成URL的方法。所以我定义了一个项目名,用于拼接URL。

在配置文件中添加配置项yaf\conf\application.ini:

project.name = 'yaf'

创建文件yaf\application\controllers\User.php:

class UserController extends Yaf_Controller_Abstract {

public function urlAction() {

$name = 'jing';

$blogId = 1;

$app = Yaf_Application::app();

$projectName = $app->getConfig()->project->name;

$urls = array(

"/{$projectName}/user",

"/{$projectName}/user/{$name}",

"/{$projectName}/user/{$name}/blog",

"/{$projectName}/user/{$name}/blog/{$blogId}",

);

foreach ($urls as $url) {

echo "{$url}
\n";

}

return false;

}

public function indexAction() {

echo '我是用户列表^_^';

// 禁用视图模板

return false;

}

public function showAction($name) {

echo "欢迎你,{$name}";

return false;

}

}

创建文件yaf\application\controllers\Blog.php:

class BlogController extends Yaf_Controller_Abstract {

public function indexAction($name) {

echo "这是{$name}的博客列表";

return false;

}

public function showAction($blogId, $name) {

echo "{$name}的这篇博客的id为{$blogId}";

return false;

}

}

Yaf的Action支持参数绑定,是按变量名绑定的。$name、$blogId要和路由中配置的名称一样,而和参数顺序无关。

Laravel

新建Laravel项目:

composer create-project laravel/laravel --prefer-dist

清除合并文件。在目录laravel\vendor\下有个文件compiled.php,这个文件是为了减少IO提高框架性能,将很多类文件合并到一个文件中而生存的。在开发环境下,应该删除该文件,否则修改了一些文件发现没有效果,其实是因为文件已经合并缓存了。

清除命令:

php artisan clear-compiled

在生产环境中应该开启,以提升性能:

php artisan optimize --force

修改路由文件laravel\app\Http\routes.php:

Route::get('/url', array('uses' => 'UserController@getUrl'));

Route::get('/user', array('uses' => 'UserController@getIndex'));

Route::get('/user/{username}', array('uses' => 'UserController@getShow'));

Route::get('/user/{username}/blog', array(

'as' => 'blog_list',

'uses' => 'BlogController@getIndex',

));

Route::get('/user/{username}/blog/{blogId}', array(

'as' => 'blog',

'uses' => 'BlogController@getShow',

))->where(array('blogId' => '[0-9]+'));

查看路由定义情况:

php artisan route:list

输出:

+--------+----------+-------------------------------+-----------+----------------------------------------------+------------+

| Domain | Method   | URI                           | Name      | Action                                       | Middleware |

+--------+----------+-------------------------------+-----------+----------------------------------------------+------------+

|        | GET|HEAD | url                           |           | App\Http\Controllers\UserController@getUrl   |            |

|        | GET|HEAD | user                          |           | App\Http\Controllers\UserController@getIndex |            |

|        | GET|HEAD | user/{username}               |           | App\Http\Controllers\UserController@getShow  |            |

|        | GET|HEAD | user/{username}/blog          | blog_list | App\Http\Controllers\BlogController@getIndex |            |

|        | GET|HEAD | user/{username}/blog/{blogId} | blog      | App\Http\Controllers\BlogController@getShow  |            |

+--------+----------+-------------------------------+-----------+----------------------------------------------+------------+

定义路由变量全局模式,修改文件laravel\app\Providers\RouteServiceProvider.php中的boot方法:

public function boot(Router $router) {

$router->pattern('username', '[a-zA-Z0-9_-]+');

parent::boot($router);

}

创建UserController控制器:

php artisan make:controller UserController

Laravel帮我们在laravel\app\Http\Controllers目录下创建了文件UserController.php,文件中已经为我们写好一部分骨架代码。修改文件laravel\app\Http\Controllers\UserController.php:

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class UserController extends Controller {

public function getUrl() {

$name = 'jing';

$blogId = 1;

$urls = array(

url('/user'),

action('UserController@getShow', array($name)),

route('blog_list', array($name)),

route('blog', array($name, $blogId)),

);

foreach ($urls as $url) {

echo "{$url}
\n";

}

}

public function getIndex() {

echo '我是用户列表^_^';

}

public function getShow($name) {

echo "欢迎你,{$name}";

}

}

创建BlogController控制器:

php artisan make:controller BlogController

修改文件laravel\app\Http\Controllers\BlogController.php:

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class BlogController extends Controller {

public function getIndex($name) {

echo "这是{$name}的博客列表";

}

public function getShow($name, $blogId) {

echo "{$name}的这篇博客的id为{$blogId}";

}

}

Laravel的Action也支持参数绑定,是按变量顺序绑定的,和变量名无关。

后语

我是Laravel粉,但是我也没有想黑其他框架的意思,大家有兴趣也可以用自己熟悉的框架来实现这个小例子,写了记得@我,语言不限。

以上所述就是本文的全部内容了,希望大家能够喜欢。

请您花一点时间将文章分享给您的朋友或者留下评论。我们将会由衷感谢您的支持!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值