`
superjavason
  • 浏览: 109864 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

More with symfony 1.3 & 1.4-高级路由 (第二部分)

阅读更多

终于又翻玩了一篇,果然翻译也是需要锻炼的,好比,这篇还没校对,欢迎指正

高级路由 (第二部分)

作者:Ryan Weaver 翻译:豆派

路由集合(Route Collections)

要完成Sympal Builder应用,我们需要创建一个管理平台,使得每个 Client 能管理他们的页面。 要做到这一点,我们需要一系列的action让我们能够创建,更新和删除 Page 对象。 由于这些类型的模块(module)非常通用,symfony可以自动生存这些模块。从命令行执行下面的任务(task)在backend应用中生成一个 pageAdmin 模块:

$ php symfony doctrine:generate-module backend pageAdmin Page --with-doctrine-route --with-show

上面的命令产生一个包含action和templates的管理模块,它能完成所有对Page对象的修改需求。有很多自定义选项可以修改自动生存的CRUD,但这超出了本章要讨论的范围。

虽然上述命令为我们准备了需要的module,但是我们还是需要为每个action创建路由。 通过附加给命令的--with-doctrine-route 选项,每个action都会有生存一个相应的对象路由。这样减少了在每个action中的代码。比如在 edit action 中只有简单的一行:

public function executeEdit(sfWebRequest $request)
{
  $this->form = new PageForm($this->getRoute()->getObject());
}

总共,我们需要给index , new , create , edit , updatedelete actions都分配一个路由。一般创建这些具有RESTful 风格的路由需要在routing.yml做非常多的配置。

pageAdmin:
  url:         /pages
  class:       sfDoctrineRoute
  options:     { model: Page, type: list }
  params:      { module: page, action: index }
  requirements:
    sf_method: [get]
pageAdmin_new:
  url:        /pages/new
  class:      sfDoctrineRoute
  options:    { model: Page, type: object }
  params:     { module: page, action: new }
  requirements:
    sf_method: [get]
pageAdmin_create:
  url:        /pages
  class:      sfDoctrineRoute
  options:    { model: Page, type: object }
  params:     { module: page, action: create }
  requirements:
    sf_method: [post]
pageAdmin_edit:
  url:        /pages/:id/edit
  class:      sfDoctrineRoute
  options:    { model: Page, type: object }
  params:     { module: page, action: edit }
  requirements:
    sf_method: [get]
pageAdmin_update:
  url:        /pages/:id
  class:      sfDoctrineRoute
  options:    { model: Page, type: object }
  params:     { module: page, action: update }
  requirements:
    sf_method: [put]
pageAdmin_delete:
  url:        /pages/:id
  class:      sfDoctrineRoute
  options:    { model: Page, type: object }
  params:     { module: page, action: delete }
  requirements:
    sf_method: [delete]
pageAdmin_show:
  url:        /pages/:id
  class:      sfDoctrineRoute
  options:    { model: Page, type: object }
  params:     { module: page, action: show }
  requirements:
    sf_method: [get]

想要查看这些路由,可以使用 app:routes 命令, 它能展示一个特定应用程序的所有路由的摘要。

$ php symfony app:routes backend

>> app       Current routes for application "backend"
Name             Method Pattern
pageAdmin        GET    /pages
pageAdmin_new    GET    /pages/new
pageAdmin_create POST   /pages
pageAdmin_edit   GET    /pages/:id/edit
pageAdmin_update PUT    /pages/:id
pageAdmin_delete DELETE /pages/:id
pageAdmin_show   GET    /pages/:id

使用路由集合代替路由

幸运的是,symfony提供了一个更加方便的方法来指定包含传统的CRUD功能的所有路由。在routing.yml中用一个简单的路由替换上面所有的内容。

pageAdmin:
  class:   sfDoctrineRouteCollection
  options:
    model:        Page
    prefix_path:  /pages
    module:       pageAdmin

我们再次运行app:routes命令来查看所有的路由, 正如你所看到的,前面的七个路由仍然存在。

$ php symfony app:routes backend

>> app       Current routes for application "backend"
Name             Method Pattern
pageAdmin        GET    /pages.:sf_format
pageAdmin_new    GET    /pages/new.:sf_format
pageAdmin_create POST   /pages.:sf_format
pageAdmin_edit   GET    /pages/:id/edit.:sf_format
pageAdmin_update PUT    /pages/:id.:sf_format
pageAdmin_delete DELETE /pages/:id.:sf_format
pageAdmin_show   GET    /pages/:id.:sf_format

路由集合是一种特殊类型的路由对象,它内部包含了许多个路由。 比如, sfDoctrineRouteCollection 路由自动生成做CRUD操作时七个最常用的路由。  sfDoctrineRouteCollection 幕后所做的无非就是创建我们先前在routing.yml 配置的七个路由。路由集合主要是为创建一个通过路由组合而存在的快捷方式。

创建一个自定义的路由集合

在这点上,每个Client 能够通过URL/pages在他的Page对象上做正常CRUD 修改。 不幸的是,现在每个Client 能够看到和修改所有的Page 对象-包括属于和不属于他的。比如,如,http://pete.sympalbuilder.com/backend.php/pages 会展现所有在fixtures.yml定义的Page的列表- Pete's Pet Shop的 location 页面和City Pub的 menu 页面。

要解决这个问题,我们需要重用在frontend创建的acClientObjectRoute。 sfDoctrineRouteCollection 类将生成一组sfDoctrineRoute 对象。但在这个应用中,我们需要生成一组 acClientObjectRoute 对象。

要做到这一点,我们将需要使用一个自定义的路由集合类。创建一个文件 acClientObjectRouteCollection.class.php ,并把它放到 lib/routing 目录。它的内容是难以置信的简单:

// lib/routing/acClientObjectRouteCollection.class.php
class acClientObjectRouteCollection extends sfObjectRouteCollection
{
  protected
    $routeClass = 'acClientObjectRoute';
}

$routeClass 属性定义了创建每个基本路由时使用的类型。现在每个基本路由都是使用acClientObjectRoute了 ,工作实际已经完成了。比如 , http://pete.sympalbuilder.com/backend.php/pages 现在指挥展现一个页面:Pete's Pet Shop的 location 页面。 感谢自定义路由类型,index action才能根据请求中的子域名展现只与正确的Client相关的Page对象。 只用了几行代码,我们就已经创建了整个可以被多个用户安全的使用的后台模块。

遗漏的部分:创建新页面

现在,当创建或编辑一个Page对象时会显示一个Client 选择框。替换允许用户选择Client(存在安全隐患)的功能,让我们根据请求中的子域名自动设置Client,

首先, 更新在 lib/form/PageForm.class.php 文件中的PageForm对象

public function configure()
{
  $this->useFields(array(
    'title',
    'content',
  ));
}

现在这个选择框已经从Page的表单中消失了。但是,当创建了一个新的Page对象后,其client_id 从没被设置过。为了解决这个问题,手动在new和create action中设置关联的 Client 信息。

public function executeNew(sfWebRequest $request)
{
  $page = new Page();
  $page->Client = $this->getRoute()->getClient();
  $this->form = new PageForm($page);
}

这里引入了的新方法getClient() ,现在在acClientObjectRoute 类型中还没有 。 让我们通过一点小小的修改来把它加到类型中:

// lib/routing/acClientObjectRoute.class.php
class acClientObjectRoute extends sfDoctrineRoute
{
  // ...
 
  protected $client = null;
 
  public function matchesUrl($url, $context = array())
  {
    // ...
 
    $this->client = $client;
 
    return array_merge(array('client_id' => $client->id), $parameters);
  }
 
  public function getClient()
  {
    return $this->client;
  }
}

通过添加 $clien类属性,并在 matchesUrl() 方法中初始化,我们可以通过路由简单的获得这个Client对象。 现在新Page对象的client_id 列会根据现在host中的子域名被自动正确的初始化。

自定义一个对象路由集合

通过使用路由框架,我们现在已经轻松的解决了创建Sympal Builder应用时提出的问题。随着应用的增长,  开发者能够在管理后台给其他模块重用自定义的路由(例如, 每个 Client 可以管理自己的图片相册).

创建自定义路由集合的另一个常见原因是添加额外的,常用的路由。比如,假设一个项目使用了很多model,每个model都有一个 is_active 列。 在管理方面,需要有一个简单的方法来切换任何特定对象的is_active值。首先,修改 acClientObjectRouteCollection 指示它添加一个新的路由到集合中:

// lib/routing/acClientObjectRouteCollection.class.php
protected function generateRoutes()
{
  parent::generateRoutes();
 
  if (isset($this->options['with_is_active']) && $this->options['with_is_active'])
  {
    $routeName = $this->options['name'].'_toggleActive';
 
    $this->routes[$routeName] = $this->getRouteForToggleActive();
  }
}

当集合对象被初始化时调用sfObjectRouteCollection::generateRoutes() 方法,该方法负责创建所有需要的路由并把它们添加到$routes类属性中。在这个例子中,我们把实际创建路由的工作放到了新创建的 getRouteForToggleActive() 方法中:

protected function getRouteForToggleActive()
{
  $url = sprintf(
    '%s/:%s/toggleActive.:sf_format',
    $this->options['prefix_path'],
    $this->options['column']
  );
 
  $params = array(
    'module' => $this->options['module'],
    'action' => 'toggleActive',
    'sf_format' => 'html'
  );
 
  $requirements = array('sf_method' => 'put');
 
  $options = array(
    'model' => $this->options['model'],
    'type' => 'object',
    'method' => $this->options['model_methods']['object']
  );
 
  return new $this->routeClass(
    $url,
    $params,
    $requirements,
    $options
  );
}

唯一剩下的步骤是在routing.yml 中设定这个路由集合。注意generateRoutes() 在添加新的路由前需要查看 lwith_is_active 参数。 添加这样的逻辑让我们在以后使用acClientObjectRouteCollection但不需要 toggleActive 的情况下 有更多的控制能力:

# apps/frontend/config/routing.yml
pageAdmin:
  class:   acClientObjectRouteCollection
  options:
    model:          Page
    prefix_path:    /pages
    module:         pageAdmin
    with_is_active: true

运行app:routes 命令,验证新的 toggleActive路由已经存在 。唯一剩下要做的是创建一个action来完成实际的工作。因为你可能需要在多个模块中使用这个路由集合和相应的action。在apps/backend/lib/action(你需要创建这个目录)目录中新建 backendActions.class.php :

# apps/backend/lib/action/backendActions.class.php
class backendActions extends sfActions
{
  public function executeToggleActive(sfWebRequest $request)
  {
    $obj = $this->getRoute()->getObject();
 
    $obj->is_active = !$obj->is_active;
 
    $obj->save();
 
    $this->redirect($this->getModuleName().'/index');
  }
}

最后,把pageAdminActions类的基类换成 backendActions 类。

class pageAdminActions extends backendActions
{
  // ...
}

我们刚才完成了什么呢? 通过添加路由到路由集合和一个关联的基类action,任何新的模块只要使用acClientObjectRouteCollection和扩展 backendActions类就 可以自动使用这些功能。这样,通用的功能可以很容易地在许多模块共享。

路由集合的配置选项

对象路由包含了一系列的选项,允许它可以高度自定义。在很多情况下,开发人员可以使用这些选项配置路由集合而不需要创建一个新的自定义路由集合类。一份详细的路由集合选项列表可以在《symfony参考指南 》中查到。

Action路由

每个对象路由集合接收三个不同的选项,它们决定在集合中需要生成的正确的路由。不做深入的探讨,下面配置的集合会生成7个默认的路由以及一个额外的集合路由和对象路由:

pageAdmin:
  class:   acClientObjectRouteCollection
  options:
    # ...
    actions:      [list, new, create, edit, update, delete, show]
    collection_actions:
      indexAlt:   [get]
    object_actions:
      toggle:     [put]

默认情况下,使用model的主健来生成所有的url和查询对象。这个,当然,也可以简单的改变。 比如,下面的代码会使用slug列而不是主健:

pageAdmin:
  class:   acClientObjectRouteCollection
  options:
    # ...
    column: slug

Model方法

默认情况下,路由会获取集合路由中所有关联的对象和查询对象路由中指定的列。如果你需要重写这些,在路由上添加 model_methods 选项。在这个例子中,fetchAll()findForRoute() 方法 需要被添加到PageTable 类中。两个方法都会接收一个request参数数组作为参数。

pageAdmin:
  class:   acClientObjectRouteCollection
  options:
    # ...
    model_methods:
      list:       fetchAll
      object:     findForRoute

默认参数

最后,假设你需要在请求中添加特定参数,并在集合中的每个路由可用。这个可以通过default_params 选项简单的实现:

pageAdmin:
  class:   acClientObjectRouteCollection
  options:
    # ...
    default_params:
      foo:   bar

最后的思考

传统的路由框架功能是-匹配和生成url- 已发展成为一个完全可定制的,能满足项目最复杂的URL需求的能力的系统。通过控制路由对象,特定的URL结构能够从业务逻辑中抽象出来,并完全独立存在在路由框架中。最终的结果是更可控制,更灵活和更易于管理的代码。

0
0
分享到:
评论

相关推荐

    symfony14-di-support:为 symfony 1.4 项目支持 Composer 和 SymfonyDependencyInjection

    symfony 1.4 DI 支持 这里解释了如何在 symfony 1.4 项目中使用 Composer 的 Symfony/DependencyInjection。 (!) 注意 不建议将 symfony 1.4 用作创建新项目。 如果你想创建一个新项目,你应该使用 Symfony2 框架。 ...

    Building PHP Applications with Symfony, CakePHP, and Zend Framework.pdf.rar

    解压密码在:http://www.pin5i.com/showtopic-building-php-applications-with-symfony-cakephp-zend-framework.html

    symfony-i18n-routing:Symfony <= 4.1的过时i18n路由

    Symfony 4的国际化路由 该捆绑包为Symfony 4提供了i18n路由。 目的 该捆绑包提供了一种路线定义国际化的方法。 这意味着您可以为每个语言环境定义路径,并且仍然让它们路由到相同的控制器操作。 安装 composer req ...

    symfony1.4安装文档

    这个是在百度的文档里面找到的一篇技术文档,其实是翻译的网上的symfony1.4的英文文档的第三篇。那个网址是:http://symfony.com/legacy/doc/gentle-introduction/1_4/en/08-Inside-the-Model-Layer-Doctrine

    该软件包提供了在 symfony 上启动 json-rpc 服务器的简便方法

    该软件包提供了在 symfony 上启动 json-rpc 服务器的简便方法,具有参数验证功能,并且可在方法内部将参数作为 DTO 对象获取.zip

    symfony-demo-mater

    **Symfony 框架简介** Symfony 是一个基于 PHP 的开源 Web 开发框架,它提供了一套强大、高效且可扩展的工具,用于构建高质量的 Web 应用程序。该框架以其模块化、灵活性和高性能而受到全球开发者的青睐。Symfony ...

    该软件包提供了在 symfony 上启动 json-rpc 服务器的简便方法,具有参数验证功能

    该软件包提供了在 symfony 上启动 json-rpc 服务器的简便方法,具有参数验证功能,并且可在方法内部将参数作为 DTO 对象获取.zip

    symfony实战doctrine版-中文版

    symfony 实战 for doctrine 中文版

    symfony5-api-platform

    `symfony5-api-platform` 是一个基于 Symfony 5 框架构建的高级 API 开发平台。它专为快速开发 RESTful 和 GraphQL API 而设计,提供了一套完整的工具链,使开发者能够高效地创建、管理和维护数据驱动的 API。该平台...

    symfony-json-request-transformer, 用于解码JSON编码请求内容的Symfony 2事件侦听器.zip

    symfony-json-request-transformer, 用于解码JSON编码请求内容的Symfony 2事件侦听器 symfony-json-request-transformer用于解码JSON编码请求内容的Symfony事件侦听器。 请阅读关于这里知识库的博客文章,位于 /...

    Practical Symfony

    本实例使用的是Symfony 1.3和1.4版本。这些版本虽然不是最新的,但依然具有很高的教育价值。文档提到在安装前需要准备一系列先决条件,包括: - 第三方软件的配置,如PHP环境的搭建。 - 命令行界面的设置。 - PHP...

    symfony1:[已弃用-改用Symfony] Symfony 1.4的DIC叉,表单增强功能,最新的Swiftmailer,更佳的性能,与Composer兼容以及对PHP 7的支持

    这是symfony 1的社区驱动分支,因为官方支持已 。 不要将其用于新项目:此版本对于改进现有的symfony1应用程序非常有用,但是是今天的理想之选。 所有增强功能和BC中断都列在文件中,其中包括: 作曲家支持 ...

    Symfony4-REST-API

    2. 初始化项目:运行`symfony new --full project_name`创建一个全新的Symfony 4项目。 3. 创建实体和数据库表:使用 Doctrine ORM,定义数据模型并生成数据库表结构。 4. 编写控制器:实现API的业务逻辑,处理HTTP...

    Ajax-Symfony-3.4-Blog.zip

    Ajax-Symfony-3.4-Blog.zip,symfony 3.4博客,带有管理仪表板ajax和许多其他功能!,ajax代表异步javascript和xml。它是多种web技术的集合,包括html、css、json、xml和javascript。它用于创建动态网页,其中网页的小...

    将Symfony的VarDumpServer引入Laravel

    首先,`VarDumpServer`是Symfony组件提供的一种更高级的调试工具,它允许开发者在一个独立的进程中运行`var_dump`,并通过浏览器控制台查看结果,这样不仅可以避免在生产环境中意外输出调试信息,还能提供更友好的...

    Gestion-de-Banque-with-Symfony-PHP-In-Windows

    穆罕默德·阿里·贾齐里(Mohamed Ali Jaziri)进行的银行管理这个项目是由symfony框架执行的。您可以在linux上运行该项目,并且可以通过链接进行链接 。 Symfony框架中的银行管理 介绍: 我们想要创建一个应用程序...

    sf2-profiler-exploit:Symfony2 <2.5.4漏洞利用探查器

    Symfony2 <2.5.4探查器漏洞 此漏洞利用了Symfony2的Web事件探查器的功能,该功能允许任何人注入和解释SQL查询。 例子: $ python sf2-profiler-sqli.py --url ...

    symfony4-embedsocial-project

    10. **事件调度(Event Dispatcher)**:Symfony的事件系统允许在应用程序的不同部分之间进行通信,项目可能使用此功能来响应某些特定行为。 总的来说,"symfony4-embedsocial-project"涵盖了Symfony 4框架的基础...

Global site tag (gtag.js) - Google Analytics