baloo
baloo

Reputation: 169

API Plateform custom get operation

I am trying to build an ecommerce site using API plateform.

Since I am using JWT authentication with LexikJWTAuthenticationBundle I am having a hard time to get the user with the token.

I would like to access the cart of the user.

I managed to add to the cart through a custom post operation.

<?php

namespace App\Controller;

use App\Entity\Article;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;


class AddToCart extends AbstractController
{
    private $em;

    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    public function __invoke(Article $data)
    {
        $user = $this->getUser();
        $user->addCart($data);
        $this->em->flush();
        return $user->getCart();
    }
}

I am trying to use the same way but with a get request

namespace App\Controller;


use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;


class GetCart extends AbstractController
{
    public function getCart()
    {
        $user = $this->getUser();
        return $user->getCart();
    }
}

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Entity(repositoryClass=UserRepository::class)
 * @ApiResource(
 *     itemOperations={
 *          "get",
 *          "put",
 *          "get_cart"={
 *               "method"="GET",
 *               "path"="/cart",
 *               "controller"=App\Controller\GetCart,
 *          },
 *     }
 * )
 */
class User implements UserInterface
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     */
    private $username;

    /**
     * @ORM\Column(type="json")
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     */
    private $password;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $email;

    /**
     * @ORM\ManyToMany(targetEntity=Article::class)
     */
    private $cart;


    /**
     * @return Collection|Article[]
     */
    public function getCart(): Collection
    {
        return $this->cart;
    }

    public function addCart(Article $cart): self
    {
        if (!$this->cart->contains($cart)) {
            $this->cart[] = $cart;
        }

        return $this;
    }

    public function removeCart(Article $cart): self
    {
        $this->cart->removeElement($cart);

        return $this;
    }
}

Any idea what I am doing wrong?

Upvotes: 0

Views: 1179

Answers (2)

MetaClass
MetaClass

Reputation: 1428

Using a custom controller does not switch off the built in services (DataProvider, (De)Serializer, DataPersister) of api plaftorm. With the built in DataProvider you can not have an item operation without an id. Your GetCart controller does not need the built in DataProvider so you can switch it off:

 * @ORM\Entity(repositoryClass=UserRepository::class)
 * @ApiResource(
 *     itemOperations={
 *          "get",
 *          "put",
 *          "get_cart"={
 *               "method"="GET",
 *               "path"="/cart",
 *               "controller"=App\Controller\GetCart,
 *               "read"=false,
 *          },
 *     }
 * )
 */
class User implements UserInterface
// ...

Upvotes: 1

Astro-Otter
Astro-Otter

Reputation: 873

Instead using a controller, have you try to use custom DataProvider and inject Security ?


use Symfony\Component\Security\Core\Security;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use ApiPlatform\Core\DataProvider\SerializerAwareDataProviderInterface;
use ApiPlatform\Core\DataProvider\SerializerAwareDataProviderTrait;

class UserDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface, SerializerAwareDataProviderInterface
{
    use SerializerAwareDataProviderTrait;
    public const OPERATION_NAME = "get_cart";
    private $security;

    public function __construct(Security $security)
    {
        $this->security = $security;
    }

    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
    {
        return User::class === $resourceClass && self::OPERATION_NAME === $operationName;
    }

    public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?TableDuplication
    {
        dump($this->security->getUser(), $this->security->getToken()); die();
        // Do what you need
    }
}

$this->security->getUser() will return your user and $this->security->getToken() will return all about your token

Here's the documentation: https://api-platform.com/docs/core/data-providers/#custom-item-data-provider

Upvotes: 0

Related Questions