Maison  >  Article  >  php教程  >  ThinkPHP、ZF2、Yaf、Laravel框架路由对比

ThinkPHP、ZF2、Yaf、Laravel框架路由对比

WBOY
WBOYoriginal
2016-06-06 20:05:551850parcourir

这篇文章主要介绍了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:

<?php
return array(
  // 开启路由
  &#39;URL_ROUTER_ON&#39; => true,
  // URL访问模式,可选参数0、1、2、3,代表以下四种模式:
  // 0 (普通模式); 1 (PATHINFO 模式); 2 (REWRITE 模式); 3 (兼容模式) 默认为PATHINFO 模式
  &#39;URL_MODEL&#39; => 2,
  // URL伪静态后缀设置,为空表示可以支持所有的静态后缀
  // 使用U函数生成URL时会不带后缀
  &#39;URL_HTML_SUFFIX&#39; => &#39;&#39;,
  // URL变量绑定到Action方法参数,默认为true
  &#39;URL_PARAMS_BIND&#39; => true,
  // URL变量绑定的类型 0 按变量名绑定 1 按变量顺序绑定,默认为0
  &#39;URL_PARAMS_BIND_TYPE&#39; => 0,
  // 路由配置
  &#39;URL_ROUTE_RULES&#39; => array(
    &#39;/^url$/&#39; => &#39;Home/User/url&#39;,
    &#39;/^user$/&#39; => &#39;Home/User/index&#39;,
    &#39;/^user\/([a-zA-Z0-9_-]+)$/&#39; => &#39;Home/User/show?name=:1&#39;,
    &#39;/^user\/([a-zA-Z0-9_-]+)\/blog$/&#39; => &#39;Home/Blog/index?name=:1&#39;,
    &#39;/^user\/([a-zA-Z0-9_-]+)\/blog\/([0-9]+)$/&#39; => &#39;Home/Blog/show?name=:1&blog_id=:2&#39;,
  ),
);
?>

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

<?php
namespace Home\Controller;
use Think\Controller;
class UserController extends Controller {
  public function url() {
    $name = &#39;jing&#39;;
    $blogId = 1;
    $urls = array(
      U(&#39;/user&#39;),
      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 &#39;我是用户列表^_^&#39;;
  }
  public function show($name) {
    echo "欢迎你,{$name}";
  }
}
?>

创建文件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}";
  }
}
?>

访问:http://127.0.0.1/tp/url

输出:

代码如下:

03fe148e8207f79262eadecda34b5075/tp/user7d01d0a03a49fceb57d12197d8d196cbdf250b2156c434f3390392d09b1c9563
67bf2f201212fe9d2dc93123c985ecbe/tp/user/jing7d01d0a03a49fceb57d12197d8d196cbdf250b2156c434f3390392d09b1c9563
69d2bf2488a461a1fea832134b9f8f35/tp/user/jing/blog7d01d0a03a49fceb57d12197d8d196cbdf250b2156c434f3390392d09b1c9563
8f18cb2f436cfaf3d08bfb6ae8a83986/tp/user/jing/blog/17d01d0a03a49fceb57d12197d8d196cbdf250b2156c434f3390392d09b1c9563

访问上面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:

<?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(
  &#39;router&#39; => array(
    &#39;routes&#39; => array(
      &#39;home&#39; => array(
        &#39;type&#39; => &#39;Zend\Mvc\Router\Http\Literal&#39;,
        &#39;options&#39; => array(
          &#39;route&#39; => &#39;/url&#39;,
          &#39;defaults&#39; => array(
            &#39;controller&#39; => &#39;Application\Controller\User&#39;,
            &#39;action&#39; => &#39;url&#39;,
          ),
        ),
      ),
      // 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
      &#39;application&#39; => array(
        &#39;type&#39; => &#39;Literal&#39;,
        &#39;options&#39; => array(
          &#39;route&#39; => &#39;/application&#39;,
          &#39;defaults&#39; => array(
            &#39;__NAMESPACE__&#39; => &#39;Application\Controller&#39;,
            &#39;controller&#39; => &#39;Index&#39;,
            &#39;action&#39; => &#39;index&#39;,
          ),
        ),
        &#39;may_terminate&#39; => true,
        &#39;child_routes&#39; => array(
          &#39;default&#39; => array(
            &#39;type&#39; => &#39;Segment&#39;,
            &#39;options&#39; => array(
              &#39;route&#39; => &#39;/[:controller[/:action]]&#39;,
              &#39;constraints&#39; => array(
                &#39;controller&#39; => &#39;[a-zA-Z][a-zA-Z0-9_-]*&#39;,
                &#39;action&#39; => &#39;[a-zA-Z][a-zA-Z0-9_-]*&#39;,
              ),
              &#39;defaults&#39; => array(
              ),
            ),
          ),
        ),
      ),
      &#39;user_list&#39; => array(
        &#39;type&#39; => &#39;Segment&#39;,
        &#39;options&#39; => array(
          &#39;route&#39; => &#39;/user[/]&#39;,
          &#39;defaults&#39; => array(
            &#39;__NAMESPACE__&#39; => &#39;Application\Controller&#39;,
            &#39;controller&#39; => &#39;User&#39;,
            &#39;action&#39; => &#39;index&#39;,
          ),
        ),
        &#39;may_terminate&#39; => true,
        &#39;child_routes&#39; => array(
          &#39;user&#39; => array(
            &#39;type&#39; => &#39;Segment&#39;,
            &#39;options&#39; => array(
              &#39;route&#39; => &#39;[:name][/]&#39;,
              &#39;constraints&#39; => array(
                &#39;name&#39; => &#39;[a-zA-Z0-9_-]+&#39;,
              ),
              &#39;defaults&#39; => array(
                &#39;action&#39; => &#39;show&#39;,
              ),
            ),
            &#39;may_terminate&#39; => true,
            &#39;child_routes&#39; => array(
              &#39;blog_list&#39; => array(
                &#39;type&#39; => &#39;Segment&#39;,
                &#39;options&#39; => array(
                  &#39;route&#39; => &#39;blog[/]&#39;,
                  &#39;constraints&#39; => array(
                  ),
                  &#39;defaults&#39; => array(
                    &#39;controller&#39; => &#39;Blog&#39;,
                    &#39;action&#39; => &#39;index&#39;,
                  )
                ),
                &#39;may_terminate&#39; => true,
                &#39;child_routes&#39; => array(
                  &#39;blog&#39; => array(
                    &#39;type&#39; => &#39;Segment&#39;,
                    &#39;options&#39; => array(
                      &#39;route&#39; => &#39;[:blog_id]&#39;,
                      &#39;constraints&#39; => array(
                        &#39;blog_id&#39; => &#39;[0-9]+&#39;,
                      ),
                      &#39;defaults&#39; => array(
                        &#39;action&#39; => &#39;show&#39;,
                      )
                    ),
                    &#39;may_terminate&#39; => true,
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    ),
  ),
  &#39;service_manager&#39; => array(
    &#39;abstract_factories&#39; => array(
      &#39;Zend\Cache\Service\StorageCacheAbstractServiceFactory&#39;,
      &#39;Zend\Log\LoggerAbstractServiceFactory&#39;,
    ),
    &#39;aliases&#39; => array(
      &#39;translator&#39; => &#39;MvcTranslator&#39;,
    ),
  ),
  &#39;translator&#39; => array(
    &#39;locale&#39; => &#39;en_US&#39;,
    &#39;translation_file_patterns&#39; => array(
      array(
        &#39;type&#39; => &#39;gettext&#39;,
        &#39;base_dir&#39; => __DIR__ . &#39;/../language&#39;,
        &#39;pattern&#39; => &#39;%s.mo&#39;,
      ),
    ),
  ),
  &#39;controllers&#39; => array(
    &#39;invokables&#39; => array(
      &#39;Application\Controller\Index&#39; => &#39;Application\Controller\IndexController&#39;,
      &#39;Application\Controller\User&#39; => &#39;Application\Controller\UserController&#39;,
      &#39;Application\Controller\Blog&#39; => &#39;Application\Controller\BlogController&#39;,
    ),
  ),
  &#39;view_manager&#39; => array(
    &#39;display_not_found_reason&#39; => true,
    &#39;display_exceptions&#39; => true,
    &#39;doctype&#39; => &#39;HTML5&#39;,
    &#39;not_found_template&#39; => &#39;error/404&#39;,
    &#39;exception_template&#39; => &#39;error/index&#39;,
    &#39;template_map&#39; => array(
      &#39;layout/layout&#39; => __DIR__ . &#39;/../view/layout/layout.phtml&#39;,
      &#39;application/index/index&#39; => __DIR__ . &#39;/../view/application/index/index.phtml&#39;,
      &#39;error/404&#39; => __DIR__ . &#39;/../view/error/404.phtml&#39;,
      &#39;error/index&#39; => __DIR__ . &#39;/../view/error/index.phtml&#39;,
    ),
    &#39;template_path_stack&#39; => array(
      __DIR__ . &#39;/../view&#39;,
    ),
  ),
  // Placeholder for console routes
  &#39;console&#39; => array(
    &#39;router&#39; => array(
      &#39;routes&#39; => array(
      ),
    ),
  ),
);
?>

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

创建文件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 = &#39;jing&#39;;
    $blogId = 1;
    $urls = array(
      $this->url()->fromRoute(&#39;user_list&#39;),
      $this->url()->fromRoute(&#39;user_list/user&#39;, array(&#39;name&#39; => $name)),
      $this->url()->fromRoute(&#39;user_list/user/blog_list&#39;, array(&#39;name&#39; => $name)),
      $this->url()->fromRoute(&#39;user_list/user/blog_list/blog&#39;, array(&#39;name&#39; => $name, &#39;blog_id&#39; => $blogId)),
    );
    $view = new ViewModel(compact(&#39;urls&#39;));
    $view->setTerminal(true);
    return $view;
  }
  public function indexAction() {
    $view = new ViewModel();
    // 禁用布局模板
    $view->setTerminal(true);
    return $view;
  }
  public function showAction() {
    $username = $this->params()->fromRoute(&#39;name&#39;);
    $view = new ViewModel(compact(&#39;username&#39;));
    $view->setTerminal(true);
    return $view;
  }
}
?>

创建文件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(&#39;name&#39;);
    $view = new ViewModel(compact(&#39;username&#39;));
    $view->setTerminal(true);
    return $view;
  }
  public function showAction() {
    $username = $this->params()->fromRoute(&#39;name&#39;);
    $blogId = $this->params()->fromRoute(&#39;blog_id&#39;);
    $view = new ViewModel(compact(&#39;username&#39;, &#39;blogId&#39;));
    $view->setTerminal(true);
    return $view;
  }
}
?>

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

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

创建文件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; ?>

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

我是用户列表^_^
创建文件zf2\module\Application\view\application\user\show.phtml:

欢迎你,720b36365a2096d271439392c84df50c
创建文件zf2\module\Application\view\application\blog\index.phtml:

这是720b36365a2096d271439392c84df50c的博客列表
创建文件zf2\module\Application\view\application\blog\show.phtml:

代码如下:

720b36365a2096d271439392c84df50c的这篇博客的id为07e70966292c2609f4715c219818d54c

Yaf

安装Yaf

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

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

    $router = Yaf_Dispatcher::getInstance()->getRouter();
    $route0 = new Yaf_Route_Rewrite(&#39;url&#39;, array(
      &#39;controller&#39; => &#39;User&#39;,
      &#39;action&#39; => &#39;url&#39;,
        ), array()
    );
    $route1 = new Yaf_Route_Rewrite(&#39;user&#39;, array(
      &#39;controller&#39; => &#39;User&#39;,
      &#39;action&#39; => &#39;index&#39;,
        ), array()
    );
    $route2 = new Yaf_Route_Regex(&#39;#user/([a-zA-Z0-9_-]+)#&#39;, array(
      &#39;controller&#39; => &#39;User&#39;,
      &#39;action&#39; => &#39;show&#39;,
        ), array(1 => &#39;name&#39;,)
    );
    $route3 = new Yaf_Route_Regex(&#39;#user/([a-zA-Z0-9_-]+)/blog#&#39;, array(
      &#39;controller&#39; => &#39;Blog&#39;,
      &#39;action&#39; => &#39;index&#39;,
        ), array(1 => &#39;name&#39;,)
    );
    $route4 = new Yaf_Route_Regex(&#39;#user/([a-zA-Z0-9_-]+)/blog/([0-9]+)#&#39;, array(
      &#39;controller&#39; => &#39;Blog&#39;,
      &#39;action&#39; => &#39;show&#39;,
        ), array(1 => &#39;name&#39;, 2 => &#39;blogId&#39;,)
    );
    $router->addRoute(&#39;url&#39;, $route0);
    $router->addRoute(&#39;user_list&#39;, $route1);
    $router->addRoute(&#39;user&#39;, $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:

<?php
class UserController extends Yaf_Controller_Abstract {
  public function urlAction() {
    $name = &#39;jing&#39;;
    $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 &#39;我是用户列表^_^&#39;;
    // 禁用视图模板
    return false;
  }
  public function showAction($name) {
    echo "欢迎你,{$name}";
    return false;
  }
}

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

代码如下:

50686e0996c5bf95b61ca1c1cf75685f '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:

代码如下:

532de6610843b347c1c34ef47912eebc{$url}7d01d0a03a49fceb57d12197d8d196cbdf250b2156c434f3390392d09b1c9563\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粉,但是我也没有想黑其他框架的意思,大家有兴趣也可以用自己熟悉的框架来实现这个小例子,写了记得@我,语言不限。

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

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

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn