iltar / http-bundle
为 Symfony 添加额外功能
Requires
- php: ^5.5||^7.0
- symfony/config: ^2.7||^3.0||^4.0
- symfony/dependency-injection: ^2.7||^3.0||^4.0
- symfony/framework-bundle: ^2.7||^3.0||^4.0
- symfony/http-kernel: ^2.7||^3.0||^4.0
- symfony/property-access: ^2.7||^3.0||^4.0
- symfony/routing: ^2.7||^3.0||^4.0
Requires (Dev)
- doctrine/doctrine-bundle: ^1.5.0
- doctrine/orm: ^2.5
- phpunit/phpunit: ^4.7||^5.0
- symfony/finder: ^2.7||^3.0||^4.0
- symfony/phpunit-bridge: ^2.8||^3.0||^4.0
- symfony/security-http: ^2.7||^3.0||^4.0
- symfony/var-dumper: ^2.7||^3.0||^4.0
This package is auto-updated.
Last update: 2022-01-07 20:59:40 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 组件解析所需的属性(关于这一点稍后详细说明)。
- 允许您通过配置覆盖或通配某些对象。
默认情况下,具有 EntityIdDescriptor 的 IdentifyingValueResolver 以 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
通配符
但我的应用程序有点杂乱,我有几种不同的方式从用户获取 id: user_id、user、id 和 uid,如何在不编写大量配置的情况下解决这个问题?解决方案:使用通配符声明。通配符声明将确保如果传递了 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 定义。标识符不仅限于 id 或 getId(),解析器将动态尝试找到哪个字段是主键。如果 id 是另一个实体,它将尝试获取该实体的 id,直到找到标量。它不支持复合主键。
要启用 id 解析器,必须启用配置
iltar_http: router: entity_id_resolver: true