New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to use resource identifier #1077
Comments
It can't really work like this:
What you could do is use We don't have a way to match route params to an identifier like you want it to, I have a proposal here though: api-platform/core#2126. You could maybe add this patch in your stack by overriding some services. |
@soyuka Thanks for answering. I have some questions:
And, if it is not asking too much, can you provide an example of how to use API platform with only DTOs and serialization? At the moment I do not want to couple my application with the API platform' way to do things so I only want API Platform to populate a DTO, receive it on a controller and serialize the response. |
If there is only this identifier yes, if not I have a proposal here to do this: api-platform/core#2126.
It can, especially if there are no other metadata that describes a property as identifier. I don't really have the time to offer you a full example but if you check how to declare a custom operation in the documentation you should be able to do so. |
@gnumoksha Have you found a solution? I'm trying to achieve the same, but I'm looking for a full example too. |
@stephanvierkant I had a lot of problems trying to get Api Platform to work thus I stopped trying to use its "magic" and started doing the work by myself, which means I've created some controllers, serializers and a decorator class to override some parts of generated documentation. Below are some classes I think can be useful to you. Entity declare(strict_types=1);
namespace Foo\Bar\Domain\Model\Page;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Foo\Bar\Infrastructure\Symfony\Controller\Page\GetPageController;
/**
* @ORM\Table(name="pages", indexes={@ORM\Index(name="slug_index", columns={"slug"})})
* @ORM\Entity(repositoryClass="Foo\Bar\Infrastructure\Domain\Model\Page\DoctrinePageRepository")
*
* @ApiResource(
* shortName="Pages",
* description="Miscellaneous pages.",
* itemOperations={
* "get"={
* "method"="GET",
* "path"="/pages/{slug}",
* "requirements"={"slug"="\w+"},
* "controller"=GetPageController::class,
* "defaults"={
* "_api_receive"=false
* },
* "swagger_context"= {
* "summary"= "Retrieves a page.",
* "description"= "Retrieves a page (i.e. help, terms, privacy, roles)",
* "parameters"= {
* {
* "in"= "path",
* "name"= "slug",
* "type"= "string",
* "example"="help"
* },
* },
* },
* },
* },
* collectionOperations={
* },
* )
*/
class Page
{
/**
* The unique auto incremented primary key.
*
* @var int|null
*
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue
*/
protected $id;
/**
* The page slug.
*
* @var string
*
* @ORM\Column(type="string", length=255, nullable=false)
*
* @Assert\NotBlank
*
* @ApiProperty(
* identifier=true,
* attributes={
* "swagger_context"={
* "type"="string",
* "description"="The page slug.",
* "example"="help"
* }
* },
*
* )
*/
protected $slug;
/**
* The page text.
*
* @var string
*
* @ORM\Column(type="text", nullable=false)
*
* @Assert\NotBlank
*
* @ApiProperty(
* attributes={
* "swagger_context"={
* "type"="string",
* "description"="The page text.",
* "example"="Foo bar baz",
* },
* }
* )
*/
protected $text;
public function getId() : int
{
return $this->id;
}
public function setSlug(string $slug) : void
{
$this->slug = $slug;
}
public function getSlug() : string
{
return $this->slug;
}
public function setText(string $text) : void
{
$this->text = $text;
}
public function getText() : string
{
return $this->text;
}
} Controller declare(strict_types=1);
namespace Foo\Bar\Infrastructure\Symfony\Controller\Page;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Foo\Bar\Domain\Model\Page\Page;
use Foo\Bar\Domain\Model\Page\PageRepository;
/**
* @see https://api-platform.com/docs/core/operations/#creating-custom-operations-and-controllers
*/
class GetPageController
{
/** @var \Foo\Bar\Domain\Model\Page\PageRepository */
private $pageRepository;
public function __construct(PageRepository $pageRepository)
{
$this->pageRepository = $pageRepository;
}
/**
* Gets a page.
*/
public function __invoke(Request $data) : ?Page
{
$requestedSlug = $data->attributes->get('slug');
if ($requestedSlug === null) {
throw new \InvalidArgumentException('Page not found.');
}
$page = $this->pageRepository->ofSlug($requestedSlug);
if ($page !== null) {
return $page;
}
throw new NotFoundHttpException('Page not found.');
}
} |
The issue
I want to retrieve a resource by its slug thus I'm following the instructions on this page.
I've ended up with the following code:
Unfortunately a request to
api/v0/pages/help
will result in:What did not tell anything useful to me, so after removing the
try catch
fromReadListener
the following exception has occurred:Notes
collectionOperations
but I'm declaring one because of this.iri
annotation like suggested here in order to avoid the errors "No collection route associated with the type" and "Unable to generate an IRI for the item of type"The text was updated successfully, but these errors were encountered: