【问题标题】:Symfony Doctrine Collection get single valueSymfony Doctrine Collection 获得单一值
【发布时间】:2020-04-03 08:29:14
【问题描述】:

我在多对多关系中有两个实体用户和产品。 在投票者内部,如果用户在 $product->getUsers 中,我想授予对产品的删除权限。 到目前为止,我设法做这样的事情

foreach ($user->getProducts() as $userProduct) {
    foreach ($userProduct->getUsers() as $productUser) {
        if($productUser->getId() === $user->getId()) {
            return true;
                break;
        }
   }
}

用户变量是:

$user = $token->getUser();

我检查是否是:

    // if the user is anonymous, do not grant access
    if (!$user instanceof UserInterface) {
        return false;
    }

每个用户都有一个产品集合 -> 此集合中的每个产品都有一个用户集合。
我使用代码检查产品的用户集合的 id 中是否存在当前经过身份验证的用户 ($user->getId()) 的 id:

if($productUser->getId() === $user->getId()) {
        return true;
            break;
    }

然后我退出循环。如果不是,则拒绝访问。

有没有更好、更优雅、更高效的方式来完成这项任务? 我应该为此目的使用任何内置的 Symfony 方法吗?

【问题讨论】:

  • 你得到用户产品,然后你得到产品用户,这意味着这个检查 $productUser->getId() === $user->getId() 最终将返回 true,所以你的代码 sn-p 根本不检查任何东西
  • 我建议你把整个代码贴出来
  • @LuninRoman 我的 === 没有意义?很可能我做错了。
  • 感觉你从错误的角度考虑问题,你应该将一个产品用户与当前登录的用户进行比较。尝试先编写测试并完成场景
  • 不需要循环。你可以像这样检查它if ($product->getUsers()->contains($user)) {...}

标签: arrays symfony foreach collections doctrine


【解决方案1】:

在投票者内部,我避免了这样的双 foreach 循环(传递产品实例)

    class ProductVoter extends Voter
    {
        protected function supports($attribute, $subject) {
            return in_array($attribute, ['PRODUCT_EDIT', 'PRODUCT_DELETE'])
                && $subject instanceof \App\Entity\Product;
        }

        protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
        {
            $user = $token->getUser();

            // if the user is anonymous, do not grant access
            if (!$user instanceof UserInterface) {
                return false;
            }

            $product = $subject;

            // ... (check conditions and return true to grant permission) ...
            switch ($attribute) {
                case 'PRODUCT_EDIT':
                    // logic to determine if the user can EDIT
                    // return true or false
                    return $user === $product->getUsers();
                    break;
                case 'PRODUCT_DELETE':   
                    return $product->getId() === $user->getProducts()->first()->getId();
                    //@Lunin Roman version works too
//return $product->getUsers()->contains($user);
                    break;
            }

            return false;
        }
    }

【讨论】:

    【解决方案2】:

    显然它必须如下所示:

    class ProductVoter extends Voter
    {
        const DELETE = 'PRODUCT_DELETE';
        const EDIT = 'PRODUCT_EDIT';
    
        protected function supports($attribute, $subject) 
        {
            return in_array($attribute, [self::EDIT, self::DELETE]) 
                && $subject instanceof Product;
        }
    
        protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
        {
            $user = $token->getUser();
    
            // if the user is anonymous, do not grant access
            if (!$user instanceof UserInterface) {
                return false;
            }
    
            $product = $subject;
    
            switch ($attribute) {
                case self::EDIT:
                case self::DELETE:
                    return $this->productIsAssignedToUser($product, $user);
            }
    
            return false;
        }
    
        protected function productIsAssignedToUser(Product $product, UserInterface $user): bool 
        {
            return $product->getUsers()->contains($user);    
        }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-30
      • 2016-02-18
      相关资源
      最近更新 更多