ThinkPHP、Zend?Framework2、Yaf、Laravel框架路由大比拼
前言
讀過一篇關(guān)于Zend Framework2的技術(shù)文章《Zend Framework2多級樹形路由Route配置實例》,是介紹路由配置的。我覺得很有意思,這是的需求:
/user對應(yīng)用戶列表頁面
/user/:user_id對應(yīng)用戶的個人主頁,比如 /user/AlloVince 就對應(yīng)AlloVince用戶的個人主頁
/user/:user_id/blog/對應(yīng)用戶的博客列表頁面,比如 /user/AlloVince/blog 就會列出AlloVince寫過的Blog
/user/:user_id/blog/:blog_id對應(yīng)用戶的一篇博客文章
方案引用自原文:
'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框架來實現(xiàn)這個路由需求。
ThinkPHP
新建一個ThinkPHP項目:
composer create-project topthink/thinkphp tp --prefer-dist
命令行顯示我安裝的是3.2.2
Installing topthink/thinkphp (3.2.2)
我看ThinkPHP官網(wǎng)最新穩(wěn)定版本是3.2.3。
我特意去packagist官網(wǎng)查了一下,庫中穩(wěn)定版確實是3.2.2。
我得使用3.2.3。為什么我特別糾結(jié)這一點哩?因為:
3.2的路由功能是針對模塊設(shè)置的,所以URL中的模塊名不能被路由,路由定義也通常是放在模塊配置文件中。 3.2.3版本開始增加全局路由定義支持,可以在項目的公共配置文件中定義路由。
也就是說,路由重寫的部分是Controller和Action部分,Moudle還是存在。
我希望的是/user,而不是home/user。(ThinkPHP中默認(rèn)Module是Home,'DEFAULT_MODULE' => 'Home',可以修改)
當(dāng)然,這個問題也可以修改.htaccess文件的解決。但是,我還是決定安裝3.2.3。
在ThinkPHP官網(wǎng)下載最新的包,解壓。
使用瀏覽器訪問一下項目的入口文件,讓ThinkPHP自動生成了一個默認(rèn)的應(yīng)用模塊Home。
修改公共配置文件tp\Application\Common\Conf\config.php:
<?php
return array(
// 開啟路由
'URL_ROUTER_ON' => true,
// URL訪問模式,可選參數(shù)0、1、2、3,代表以下四種模式:
// 0 (普通模式); 1 (PATHINFO 模式); 2 (REWRITE 模式); 3 (兼容模式) 默認(rèn)為PATHINFO 模式
'URL_MODEL' => 2,
// URL偽靜態(tài)后綴設(shè)置,為空表示可以支持所有的靜態(tài)后綴
// 使用U函數(shù)生成URL時會不帶后綴
'URL_HTML_SUFFIX' => '',
// URL變量綁定到Action方法參數(shù),默認(rèn)為true
'URL_PARAMS_BIND' => true,
// URL變量綁定的類型 0 按變量名綁定 1 按變量順序綁定,默認(rèn)為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',
),
);
?>
創(chuàng)建文件tp\Application\Home\Controller\UserController.class.php:
<?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 "<a href=\"{$url}\">{$url}<a/><br />\n";
}
}
public function index() {
echo '我是用戶列表^_^';
}
public function show($name) {
echo "歡迎你,{$name}";
}
}
?>
創(chuàng)建文件tp\Application\Home\Controller\BlogController.class.php:
<?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}";
}
}
?>
輸出:
<a href="/tp/user">/tp/user<a/><br />
<a href="/tp/user/jing">/tp/user/jing<a/><br />
<a href="/tp/user/jing/blog">/tp/user/jing/blog<a/><br />
<a href="/tp/user/jing/blog/1">/tp/user/jing/blog/1<a/><br />
訪問上面4個鏈接,依次返回:
我是用戶列表^_^
歡迎你,jing
這是jing的博客列表
jing的這篇博客的id為1
下面其他框架,也同樣輸出以上內(nèi)容。
Zend Framework 2
使用Zend Framework2骨架程序創(chuàng)建一個Zend Framework2項目:
composer create-project --stability="dev" zendframework/skeleton-application zf2
修改默認(rèn)模塊Application的配置文件zf2\module\Application\config\module.config.php:
<?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部分。要我寫這么長的文件,那就太為難我了。這也是Zend Framework官方發(fā)布了一個骨架程序的原因。
創(chuàng)建文件zf2\module\Application\src\Application\Controller\UserController.php:
<?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;
}
}
?>
創(chuàng)建文件zf2\module\Application\src\Application\Controller\BlogController.php:
<?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;
}
}
?>
Zend Framework2不支持Action參數(shù)綁定,ThinkPHP不僅支持綁定,還支持2種綁定方式:按變量名綁定和按變量順序綁定。
Zend Framework2中Action必須得返回視圖,除非exit()。如果你知道可以禁用視圖的辦法,請告訴我。
創(chuàng)建文件zf2\module\Application\view\application\user\url.phtml:
<?php foreach ($urls as $url): ?> <a href="<?php echo $url;?>"><?php echo $url;?><a/><br /> <?php endforeach; ?>
創(chuàng)建文件zf2\module\Application\view\application\user\index.phtml:
我是用戶列表^_^
創(chuàng)建文件zf2\module\Application\view\application\user\show.phtml:
歡迎你,<?php echo $username; ?>
創(chuàng)建文件zf2\module\Application\view\application\blog\index.phtml:
這是<?php echo $username; ?>的博客列表
創(chuàng)建文件zf2\module\Application\view\application\blog\show.phtml:
<?php echo $username; ?>的這篇博客的id為<?php echo $blogId; ?>
Yaf
安裝Yaf
使用代碼生成工具創(chuàng)建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有路由功能,但是沒有根據(jù)路由名生成URL的方法。所以我定義了一個項目名,用于拼接URL。
在配置文件中添加配置項yaf\conf\application.ini:
project.name = 'yaf'
創(chuàng)建文件yaf\application\controllers\User.php:
<?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 "<a href=\"{$url}\">{$url}<a/><br />\n";
}
return false;
}
public function indexAction() {
echo '我是用戶列表^_^';
// 禁用視圖模板
return false;
}
public function showAction($name) {
echo "歡迎你,{$name}";
return false;
}
}
創(chuàng)建文件yaf\application\controllers\Blog.php:
<?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支持參數(shù)綁定,是按變量名綁定的。$name、$blogId要和路由中配置的名稱一樣,而和參數(shù)順序無關(guān)。
Laravel
新建Laravel項目:
composer create-project laravel/laravel --prefer-dist
清除合并文件。在目錄laravel\vendor\下有個文件compiled.php,這個文件是為了減少IO提高框架性能,將很多類文件合并到一個文件中而生存的。在開發(fā)環(huán)境下,應(yīng)該刪除該文件,否則修改了一些文件發(fā)現(xiàn)沒有效果,其實是因為文件已經(jīng)合并緩存了。
清除命令:
php artisan clear-compiled
在生產(chǎn)環(huán)境中應(yīng)該開啟,以提升性能:
php artisan optimize --force
修改路由文件laravel\app\Http\routes.php:
<?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);
}
創(chuàng)建UserController控制器:
php artisan make:controller UserController
Laravel幫我們在laravel\app\Http\Controllers目錄下創(chuàng)建了文件UserController.php,文件中已經(jīng)為我們寫好一部分骨架代碼。修改文件laravel\app\Http\Controllers\UserController.php:
<?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 "<a href=\"{$url}\">{$url}<a/><br />\n";
}
}
public function getIndex() {
echo '我是用戶列表^_^';
}
public function getShow($name) {
echo "歡迎你,{$name}";
}
}
創(chuàng)建BlogController控制器:
php artisan make:controller BlogController
修改文件laravel\app\Http\Controllers\BlogController.php:
<?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也支持參數(shù)綁定,是按變量順序綁定的,和變量名無關(guān)。
后語
我是Laravel粉,但是我也沒有想黑其他框架的意思,大家有興趣也可以用自己熟悉的框架來實現(xiàn)這個小例子,寫了記得@我,語言不限。
以上所述就是本文的全部內(nèi)容了,希望大家能夠喜歡。
請您花一點時間將文章分享給您的朋友或者留下評論。我們將會由衷感謝您的支持!
相關(guān)文章
smarty中先strip_tags過濾html標(biāo)簽后truncate截取文章運用
strip_tags() 函數(shù)剝?nèi)?HTML、XML 以及 PHP 的標(biāo)簽。2010-10-10
php中ob_flush函數(shù)和flush函數(shù)用法分析
這篇文章主要介紹了php中ob_flush函數(shù)和flush函數(shù)用法,實例分析了ob_flush函數(shù)和flush函數(shù)的功能及相關(guān)的使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-03-03
PHP大批量數(shù)據(jù)操作時臨時調(diào)整內(nèi)存與執(zhí)行時間的方法
PHP大批量數(shù)據(jù)操作時臨時調(diào)整內(nèi)存與執(zhí)行時間的方法 ,因為運行的程序會很大很慢所以需要臨時設(shè)置下。不用修改php.ini參數(shù)了。2011-04-04

