承接 iltar/http-bundle 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

iltar/http-bundle

最新稳定版本:v1.1.4

Composer 安装命令:

composer require iltar/http-bundle

包简介

Adding extra functionality to Symfony

README 文档

README

This package is now archived. If you wish to keep using it, please fork it.

http-bundle

Provides extra HTTP related functionality in Symfony.

Requirements:

  • PHP 5.5 or higher, including php 7
  • Symfony 2.7 or higher

Recommended installation is via composer: composer require iltar/http-bundle.

Router Enhancements

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

Let's say we have a ParamConverter on this route that would nicely convert the user parameter of your route to an AppUser, but how would you generate the route for this action? Sadly you still need a scalar as parameter for Router::generate():

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

Okay, not really a big problem, but we're passing an id to a parameter which you would expect to have an AppUser if you look at the action. Another problem is that if you want to change the argument passed along, you will have to update every single usage of this URL. A decent IDE can get around this issue, but wait! What about your twig templates?

{{ 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 #}

How nice would it be if you could just pass your user object along?

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

The router decorator is provided to make it easier to resolve arguments required for route generation. They work like a reversed ParamConverter.

A quick Example

You need to do two things to make this work:

  • create a resolver
  • write a service definition for it and tag it accordingly
<?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();
    }
}

And don't forget the service definition.

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

That's too much work!

This is very nice, but a lot of work. Do I really have to write a resolver for each parameter I want to have resolved? The answer is simple: no. This package comes with two resolvers already.

The first resolver is the IdentifyingValueResolver. This resolver functions as a delegator for models implementing the ModelDescriptorInterface. This resolver will attempt to find the identifying value and obtain it. Currently this package ships with the following descriptors:

  • EntityIdDescriptor - Attempts to get the value marked with @Id from a doctrine entity.

The second resolver provided is the MappablePropertyPathResolver. It does two things:

  • Automagically tries to resolve the property required (more on this later), using Symfony's Property Accessor component.
  • Allows you to override or wildcard certain objects via configuration.

The IdentifyingValueResolver with the EntityIdDescriptor is registered with a priority of 100 by default. The MappablePropertyPathResolver is registered with a priority of 200.

So how can I make it resolve my properties?

It follows three checks:

  • Is the object provided mapped in the configuration?
  • Is the name of the argument mapped in the configuration?
  • Is the name of the argument an accessible property in the object?
// let's take this simple example
$router->generate('app.view-user', ['username' => $user]);
$router->generate('app.view-user', ['id' => $user]);

Without any configuration, the first would attempt to call $user->getUsername() and the second $user->getId().

// let's take another example
$router->generate('app.view-user', ['user' => $user]);
Aliasing a property

This serves a bit more problematic, as there is no user property within the AppUser. You can work around this issue by defining the mapping in the configuration. This configuration example would call $user->getUsername() if the key user and the object an AppUser.

iltar_http:
    router:
        mapped_properties:
            App\AppUser.user: username
Wildcards

But my application is a bit messy and I have several different ways of getting the id from a user: user_id, user, id and uid, how do I solve this without writing a lot of configuration? Solution: use the wildcard declaration. The wildcard declaration will make sure that if the AppUser is being passed along, it will always get the id.

iltar_http:
    router:
        mapped_properties:
            App\AppUser: id

But this makes it problematic when I still want to be able to get the username on some pages but the id on the rest, how do I solve this? There's a solution for that as well! Next to a wildcard, you can also specify the username. If a more specific field is configured, it will take that over the wildcard if the name of the parameter matches.

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

The first line tells that all undefined keys match the id. The second line tells that if they key is user, it should get the username. The third line means that it should pick the parameter name as property name.

Power of the Property Accessor Component

I'm lazy though, what if I want link to the first address of my Client, which has a one to many relation?

iltar_http:
    router:
        mapped_properties:
            App\Client.first_address: address[0]
Using the IdentifyingValueResolver Alongside the MappablePropertyPathResolver

If you enable the IdentifyingValueResolver, you can already cover the cases where your parameter is the id. When enabled you can can remove the definitions of the mapped_properties where you would refer to the primary key (usually id). The identifier is not limited to id or getId(), the resolver will dynamically attempt to find which field is the primary key. If the id happens to be another entity, it will try to get the id of that given entity until it finds a scalar. It does not support composite primary keys.

To enable the id resolver you have to enable the configuration:

iltar_http:
    router:
        entity_id_resolver: true

iltar/http-bundle 适用场景与选型建议

iltar/http-bundle 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 20.21k 次下载、GitHub Stars 达 39, 最近一次更新时间为 2015 年 07 月 31 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「symfony」 「http」 「bundle」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 iltar/http-bundle 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 iltar/http-bundle 我们能提供哪些服务?
定制开发 / 二次开发

基于 iltar/http-bundle 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 20.21k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 40
  • 点击次数: 5
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 39
  • Watchers: 7
  • Forks: 4
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2015-07-31