Symfony Doctrine Коллекция получает одно значение - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть две сущности Пользователь и Продукт в отношении ManyToMany. Внутри избирателя я хотел бы дать разрешение на удаление Продукта, если Пользователь находится среди $ 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;
    }

Каждый пользователь имеет коллекцию продуктов -> каждый продукт в этой коллекции имеет коллекцию пользователей. Я проверяю, присутствует ли идентификатор текущего аутентифицированного пользователя ($ user-> getId ()) среди идентификаторов Коллекции пользователей продукта с кодом:

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

, и выхожу из l oop. Если нет, доступ запрещен.

Есть ли лучший, более элегантный и эффективный способ выполнить эту задачу? Любой встроенный Symfony метод, который я должен использовать для этой цели?

Ответы [ 2 ]

0 голосов
/ 03 апреля 2020

Так что, очевидно, это должно быть что-то вроде ниже:

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);    
    }

}

0 голосов
/ 03 апреля 2020

Внутри избирателя я избегаю двойного foreach l oop вот так (передавая экземпляр продукта)

    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;
        }
    }
...