当前位置: 移动技术网 > IT编程>开发语言>PHP > ThinkPHP、ZF2、Yaf、Laravel框架路由大比拼

ThinkPHP、ZF2、Yaf、Laravel框架路由大比拼

2018年06月25日  | 移动技术网IT编程  | 我要评论

前言

读过一篇关于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(
  // 开启路由
  '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:

<?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}";
  }
}
?>

创建文件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
下面其他框架,也同样输出以上内容。

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(
  '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:

<?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:

<?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 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:

欢迎你,<?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:

<?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;
  }
}

创建文件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支持参数绑定,是按变量名绑定的。$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:

复制代码 代码如下:

<?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:

复制代码 代码如下:

<?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}";
    }
}

创建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也支持参数绑定,是按变量顺序绑定的,和变量名无关。

后语

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

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

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网