格式化数组输出以显示友好名称

时间:2014-10-10 01:23:43

标签: php arrays symfony

我的这个函数返回一个JSON响应:

public function getUsersAction()
{
    $response = array();
    $em = $this->getDoctrine()->getManager();

    $entities = $em->getRepository("UserBundle:User")->findAll();

    $roles = array(
        "ROLE_PROFILE_ONE" => "Facturación y Entrega",
        "ROLE_PROFILE_TWO" => "Envío",
        "ROLE_ADMIN" => "Administrador",
        "ROLE_USER" => "No posee roles asignados"
    );

    $users = array();
    foreach ($entities as $entity)
    {
        $user = array();

        $user[] = $entity->getUsername();
        $user[] = $entity->getEmailCanonical();
        $user[] = $entity->getRoles();
        $user[] = $entity->getGroupNames() != NULL ? $entity->getGroupNames() : "-";
        $users[] = $user;
    }

    $response[ 'data' ] = $users;
    return new JsonResponse($response);

}

我通过Ajax调用通过Twig模板访问它,这是工作!现在,getRoles()({1}}(FOSUser)模型中的User按照示例返回DB值:ROLE_PROFILE_ONEROLE_ADMINROLE_USER,如何将输出格式化为根据{{​​1}}定义的数组显示友好名称?我尝试在$roles内部进行foreach循环并设置一个新数组,但嵌套调用因为我的Apache失败而变大。有什么帮助吗?

尝试使用输入/输出示例更清晰

嗯,这就是我们输入的内容(函数返回的内容,我创建了一个foreach ($entities as $entity) ...来获取输出):

ladybug_dump($entities)

当我在Twig上访问它时,在模板上,我得到了:

array(6)
   [0]: object(Tanane\UserBundle\Entity\User)
      >> Properties
      ...
      # [roles]: array(1)
         [0]: string (16) "ROLE_PROFILE_ONE"
      ...
   [1]: object(Tanane\UserBundle\Entity\User)
      >> Properties
      ...
      # [roles]: array(2)
         [0]: string (16) "ROLE_PROFILE_TWO"
         [1]: string (16) "ROLE_PROFILE_ONE"
      ...

但我需要这个输出:

User1 ROLE_PROFILE_ONE
User2 ROLE_PROFILE_TWO, ROLE_PROFILE_ONE

现在更清楚了吗?

2 个答案:

答案 0 :(得分:1)

嗯,你已经尝试过一个嵌套循环来创建一个新的数组吗?:

$users = array();
foreach ($entities as $entity)
{
    $user = array();

    $user[] = $entity->getUsername();
    $user[] = $entity->getEmailCanonical();

    $rolearray = [];
    foreach ($entity->getRoles() as $role)
    {
        $rolearray[] = $roles[$role];
    }
    $user[] = $rolearray;

    $user[] = $entity->getGroupNames() != NULL ? $entity->getGroupNames() : "-";
    $users[] = $user;
}

这就是我的所作所为。您可以使用array_map代替,但我不明白为什么会有显着差异。这似乎不太可能是如此耗费资源以至于关闭服务器,如果发生这种情况,我会强烈怀疑其他一些问题。

答案 1 :(得分:1)

如果您的角色总是要转换为那些特定的字符串,那么您可以将它们添加到您的用户模型中,并在getTransformedRoles()方法中构建角色列表,如...

user.php的

class User extends BaseUser implements UserInterface
{
    const ROLE_PROFILE_ONE = 'Facturación y Entrega';
    const ROLE_PROFILE_TWO = 'Envío';
    const ROLE_ADMIN       = 'Administrador';
    const ROLE_USER        = 'No posee roles asignados';
    ...
    public function getTransformedRoles()
    {
        $transformed = array();

        foreach ($this->getRoles() as $role) {
            $role = strtoupper($role);
            $const = sprintf('self::%s', $role);

            // Do not add if is $role === ROLE_USER
            if (FOS\UserBundle\Model\UserInterface::ROLE_DEFAULT === $role) {
                continue;
            }

            if (!defined($const)) {
                throw \Exception(sprintf('User does not have the role constant "%s" set', $role));
            }

            $transformed[] = constant($const);
        )

        // If no roles add self::ROLE_USER
        if (empty($transformed)) {
            $transformed[] = self::ROLE_USER;
        }

        return $transformed;
    }
    ....
}

然后,这将返回完全转换的角色数组(使用$user->getTransformedRoles()),您可能需要它们而不是单个用例。

或者你可以使用一个服务进行相同类型的转换,但是可以通过config.yml设置一组不同的角色和转换。

<强>更新

要将此作为服务使用app/config/config中指定的角色转换,您可以执行以下操作。

的Acme / SomethingBundle / DependencyInjection /配置

$rootNode
    ->children()
        ->arrayNode('role_transformations')
            ->defaultValue(array())
            ->useAttributeAsKey('name')
                ->prototype('scalar')->cannotBeEmpty()->end()
            ->end()
        ->end()
    ->end();

的Acme / SomethingBundle / DependencyInjection / AcmeSomethingExtension

$container->setParameter(
    'acme.something.role_transformations', 
    $config['role_transformations']
);

然后在 app / config / config.yml

// For an empty array
role_transformations: ~ // Or not even at all, it defaults to an empty array
// For transformation
role_transformations:
    ROLE_PROFILE_ONE: 'Facturación y Entrega'
    ROLE_PROFILE_TWO: 'Envío'
    ROLE_ADMIN: 'Administrador'
    ROLE_USER: 'No posee roles asignados'

创建您的服务并注入role_transformations

parameters:
    acme.something.role_transformer.class: Acme/SomethingBundle/Transformer/RoleTransformer

services:
    acme.something.role_transformer:
        class: %acme.something.role_transformer.class%
        arguments:
            - %acme.something.role_transformations%

然后在您的服务文件中( Acme / SomethingBundle / Transformer / RoleTransformer

class RoleTransformer implements RoleTransformerInterface
{
    const ROLE_DEFAULT = 'ROLE_USER';
    protected $rolesTransformations;

    public function __construct(array $roleTransformations)
    {
        $this->roleTransformations = $roleTransformations;
    }

    public function getTransformedRolesForUser($user)
    {
        if (!method_exists($user, 'getRoles')) {
            throw new \Exception('User object has no "getRoles" method');
            // Alternatively you could add an interface to you user object specifying 
            // the getRoles method or depend on the Symfony security bundle and 
            // type hint Symfony\Component\Security\Core\User\UserInterface
        }

        return $this->getTransformedRoles($user->getRoles();
    }

    public function getTransformedRoles(array $roles)
    {
        $transformedRoles = array()

        foreach ($roles as $role) {
            $role = strtoupper($role);

            if (null !== $transformedRole = $this->getTransformedRole($role)) {
                $transformedRoles[] = $transformedRole;
            }
        }

        return $transformedRoles;
    }

    public function getTransformedRole($role)
    {
        if (self::ROLE_USER === $role) {
            return null;
        }

        if (!array_key_exists($role, $this->roleTransformations)) {
            throw \Exception(sprintf(
                'Role "%s" not found in acme.something.role_transformations', $role)
            );
        }

        return $this->roleTransformations[$role];
    }
}

然后可以将其注入服务或控制器并像

一样使用
$transformer = $this->container->get('acme.something.role_transformer');
// Or injected via the DI

$roles = $transformer->getTransformedRolesForUser($user);
// For all of a users roles
$roles = $transformer->getTransformedRoles($user->getRoles());
// For an array of roles
$role = $transformer->getTransformedRole('ROLE_PROFILE_ONE');
// For a single role, or null if ROLE_USER