iltar/http-bundle

该软件包已被废弃,不再维护。没有建议的替代软件包。

为 Symfony 添加额外功能

安装: 20,203

依赖: 0

建议者: 0

安全: 0

星标: 39

关注者: 7

分支: 4

开放问题: 0

类型:symfony-bundle

v1.1.4 2017-11-18 13:50 UTC

README

该软件包现已存档。如果您希望继续使用它,请将其进行分支。

http-bundle

为 Symfony 提供额外的 HTTP 相关功能。

需求

  • PHP 5.5 或更高版本,包括 php 7
  • Symfony 2.7 或更高版本

推荐通过 composer 安装: composer require iltar/http-bundle

路由增强

    /**
     * @Route("/profile/{user}/", name="app.view-profile")
     */
    public function viewProfileAction(AppUser $user);

假设我们在该路由上有一个 ParamConverter,它可以将路由的 user 参数优雅地转换为 AppUser,但如何生成此操作的路线呢?遗憾的是,您仍然需要将标量作为参数传递给 Router::generate()

$router->generate('app.view-profile', ['user' => $user->getId()]);

好吧,这并不是一个大问题,但我们正在将一个 ID 传递给一个您预期将具有 AppUser 的参数。另一个问题是,如果您想更改传递的参数,您必须更新该 URL 的每个使用实例。一个不错的 IDE 可以解决这个问题,但等等!那您的 twig 模板呢?

{{ path('app.view-profile', { 'user': user.id }) }}
{{ path('app.view-profile', { 'user': user.getid }) }}
{{ path('app.view-profile', { 'user': user.getId() }) }}
{{ path('app.view-profile', { 'user': user[id] }) }}

{# I think you see where I'm going at #}

如果能够直接传递您的用户对象会多么方便。

$router->generate('app.view-profile', ['user' => $user]);

路由装饰器提供了一种更轻松地解决生成路线所需参数的方法。它们就像反向的 ParamConverter

快速示例

为了使此功能生效,您需要做两件事

  • 创建一个解析器
  • 编写一个服务定义,并相应地标记它
<?php
namespace App\Router;

use App\AppUser;
use Iltar\HttpBundle\Router\ParameterResolverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

final class UserParameterResolver implements ParameterResolverInterface
{
    public function supportsParameter($name, $value)
    {
        return 'user' === $name && $value instanceof AppUser
    }

    /**
     * Resolves AppUser for 'user' to AppUser::getUsername().
     *
     * {@inheritdoc}
     */
    public function resolveParameter($name, $value)
    {
        return $value->getUsername();
    }
}

别忘了服务定义。

services:
    app.router.user-param-resolver:
        class: App\AppUser\UserParameterResolver
        tags:
            - { name: router.parameter_resolver, priority: 150 }

这太麻烦了!

这很好,但需要做很多工作。我真的必须为每个要解决的参数编写一个解析器吗?答案是简单的:不。此软件包已经包含了两个解析器。

第一个解析器是 IdentifyingValueResolver。此解析器作为实现 ModelDescriptorInterface 的模型的代理。此解析器将尝试查找识别值并获取它。目前,此软件包附带以下描述符

  • EntityIdDescriptor - 尝试从 doctrine 实体中获取标记为 @Id 的值。

提供的第二个解析器是 MappablePropertyPathResolver。它做两件事

  • 自动尝试使用 Symfony 的 Property Accessor 组件解析所需的属性(关于这一点稍后详细说明)。
  • 允许您通过配置覆盖或通配某些对象。

默认情况下,具有 EntityIdDescriptorIdentifyingValueResolver 以 100 的优先级注册。具有 MappablePropertyPathResolver 的默认优先级为 200。

那么我该如何让它解析我的属性呢?

它遵循三个检查

  • 提供的对象是否在配置中进行了映射?
  • 参数的名称是否在配置中进行了映射?
  • 参数的名称是否在对象中是一个可访问的属性?
// let's take this simple example
$router->generate('app.view-user', ['username' => $user]);
$router->generate('app.view-user', ['id' => $user]);

在没有任何配置的情况下,第一个会尝试调用 $user->getUsername(),第二个调用 $user->getId()

// let's take another example
$router->generate('app.view-user', ['user' => $user]);
属性别名

这有点棘手,因为 AppUser 中没有用户属性。您可以通过在配置中定义映射来解决这个问题。此配置示例会在键 user 和对象是 AppUser 时调用 $user->getUsername()

iltar_http:
    router:
        mapped_properties:
            App\AppUser.user: username
通配符

但我的应用程序有点杂乱,我有几种不同的方式从用户获取 iduser_iduseriduid,如何在不编写大量配置的情况下解决这个问题?解决方案:使用通配符声明。通配符声明将确保如果传递了 AppUser,它总是会获取 id

iltar_http:
    router:
        mapped_properties:
            App\AppUser: id

但这使得我仍然想在某些页面上获取 username 而不是 id 时出现了问题,如何解决这个问题?还有解决方案!在通配符旁边,您也可以指定 username。如果配置了更具体的字段,并且参数名称匹配,它将覆盖通配符。

iltar_http:
    router:
        mapped_properties:
            App\AppUser          : id
            App\AppUser.user     : username
            App\AppUser.username : ~

第一行表示所有未定义的键与 id 匹配。第二行表示如果键是 user,则应获取 username。第三行表示应选择参数名称作为属性名称。

属性访问组件的力量

然而,我很懒,如果我想要链接到我的客户的第一地址,而这个地址有一个多对一的关系呢?

iltar_http:
    router:
        mapped_properties:
            App\Client.first_address: address[0]
使用 IdentifyingValueResolver 与 MappablePropertyPathResolver 一起

如果您启用了 IdentifyingValueResolver,您已经可以覆盖参数是 id 的情况。启用后,您可以删除那些引用主键(通常是 id)的 mapped_properties 定义。标识符不仅限于 idgetId(),解析器将动态尝试找到哪个字段是主键。如果 id 是另一个实体,它将尝试获取该实体的 id,直到找到标量。它不支持复合主键。

要启用 id 解析器,必须启用配置

iltar_http:
    router:
        entity_id_resolver: true