I am trying to understand how the "DataPersister" but after two days I still cannot get the tutorial to work.
I created a simple entity for articles.
<?php
// src/Entity/Article.php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ApiResource
* @ORM\Entity
*/
class Article
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="string")
*/
public $origId;
public function getId(): ?int
{
return $this->id;
}
}
Until this point everything works fine. I would like to run additional code when an entry is created, so I added a DataPersister class.
<?php
// src/DataPersister/ArticleDataPersister.php
namespace App\DataPersister;
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use App\Entity\Article;
final class ArticleDataPersister implements ContextAwareDataPersisterInterface
{
public function supports($data, array $context = []): bool
{
return $data instanceof Article;
}
public function persist($data, array $context = [])
{
return $data;
}
public function remove($data, array $context = [])
{
}
}
Autowiring and autoconfiguration is enabled and so the documentation says: "If service autowiring and autoconfiguration are enabled (they are by default), you are done!"
https://api-platform.com/docs/core/data-persisters/
But when I try to create an entry I get the following error now.
{
"@context": "/contexts/Error",
"@type": "hydra:Error",
"hydra:title": "An error occurred",
"hydra:description": "Unable to generate an IRI for \"App\\Entity\\Article\".",
"trace": [
{
"namespace": "",
"short_class": "",
"class": "",
"type": "",
"function": "",
"file": "/usr/www/users/test/api.test.com/vendor/api-platform/core/src/Bridge/Symfony/Routing/IriConverter.php",
"line": 155,
"args": []
},
{
"namespace": "ApiPlatform\\Core\\Bridge\\Symfony\\Routing",
"short_class": "IriConverter",
"class": "ApiPlatform\\Core\\Bridge\\Symfony\\Routing\\IriConverter",
"type": "->",
"function": "getItemIriFromResourceClass",
"file": "/usr/www/users/test/api.test.com/vendor/api-platform/core/src/Bridge/Symfony/Routing/IriConverter.php",
"line": 128,
"args": [
[
"string",
"App\\Entity\\Article"
],
[
"array",
[
[
"string",
""
]
]
],
[
"integer",
1
]
]
},
{
"namespace": "ApiPlatform\\Core\\Bridge\\Symfony\\Routing",
"short_class": "IriConverter",
"class": "ApiPlatform\\Core\\Bridge\\Symfony\\Routing\\IriConverter",
"type": "->",
"function": "getIriFromItem",
"file": "/usr/www/users/test/api.test.com/vendor/api-platform/core/src/EventListener/WriteListener.php",
"line": 104,
"args": [
[
"object",
"App\\Entity\\Article"
]
]
},
{
"namespace": "ApiPlatform\\Core\\EventListener",
"short_class": "WriteListener",
"class": "ApiPlatform\\Core\\EventListener\\WriteListener",
"type": "->",
"function": "onKernelView",
"file": "/usr/www/users/test/api.test.com/vendor/symfony/event-dispatcher/Debug/WrappedListener.php",
"line": 117,
"args": [
[
"object",
"Symfony\\Component\\HttpKernel\\Event\\ViewEvent"
],
[
"string",
"kernel.view"
],
[
"object",
"Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher"
]
]
},
{
"namespace": "Symfony\\Component\\EventDispatcher\\Debug",
"short_class": "WrappedListener",
"class": "Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener",
"type": "->",
"function": "__invoke",
"file": "/usr/www/users/test/api.test.com/vendor/symfony/event-dispatcher/EventDispatcher.php",
"line": 230,
"args": [
[
"object",
"Symfony\\Component\\HttpKernel\\Event\\ViewEvent"
],
[
"string",
"kernel.view"
],
[
"object",
"Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher"
]
]
},
{
"namespace": "Symfony\\Component\\EventDispatcher",
"short_class": "EventDispatcher",
"class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
"type": "->",
"function": "callListeners",
"file": "/usr/www/users/test/api.test.com/vendor/symfony/event-dispatcher/EventDispatcher.php",
"line": 59,
"args": [
[
"array",
[
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
]
]
],
[
"string",
"kernel.view"
],
[
"object",
"Symfony\\Component\\HttpKernel\\Event\\ViewEvent"
]
]
},
{
"namespace": "Symfony\\Component\\EventDispatcher",
"short_class": "EventDispatcher",
"class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
"type": "->",
"function": "dispatch",
"file": "/usr/www/users/test/api.test.com/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php",
"line": 151,
"args": [
[
"object",
"Symfony\\Component\\HttpKernel\\Event\\ViewEvent"
],
[
"string",
"kernel.view"
]
]
},
{
"namespace": "Symfony\\Component\\EventDispatcher\\Debug",
"short_class": "TraceableEventDispatcher",
"class": "Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher",
"type": "->",
"function": "dispatch",
"file": "/usr/www/users/test/api.test.com/vendor/symfony/http-kernel/HttpKernel.php",
"line": 150,
"args": [
[
"object",
"Symfony\\Component\\HttpKernel\\Event\\ViewEvent"
],
[
"string",
"kernel.view"
]
]
},
{
"namespace": "Symfony\\Component\\HttpKernel",
"short_class": "HttpKernel",
"class": "Symfony\\Component\\HttpKernel\\HttpKernel",
"type": "->",
"function": "handleRaw",
"file": "/usr/www/users/test/api.test.com/vendor/symfony/http-kernel/HttpKernel.php",
"line": 67,
"args": [
[
"object",
"Symfony\\Component\\HttpFoundation\\Request"
],
[
"integer",
1
]
]
},
{
"namespace": "Symfony\\Component\\HttpKernel",
"short_class": "HttpKernel",
"class": "Symfony\\Component\\HttpKernel\\HttpKernel",
"type": "->",
"function": "handle",
"file": "/usr/www/users/test/api.test.com/vendor/symfony/http-kernel/Kernel.php",
"line": 191,
"args": [
[
"object",
"Symfony\\Component\\HttpFoundation\\Request"
],
[
"integer",
1
],
[
"boolean",
true
]
]
},
{
"namespace": "Symfony\\Component\\HttpKernel",
"short_class": "Kernel",
"class": "Symfony\\Component\\HttpKernel\\Kernel",
"type": "->",
"function": "handle",
"file": "/usr/www/users/test/api.test.com/public/index.php",
"line": 25,
"args": [
[
"object",
"Symfony\\Component\\HttpFoundation\\Request"
]
]
}
]
}
The cache was cleared.
I still try to understand how everything works together, but I cannot see any difference to the example in the tutorial.
Article doesn't have any id in the value returned by the persist method. You should have persisted the Article and the identifier should be valid, for example:
public function persist($data, array $context = [])
{
$data->id = 'foo';
return $data;
}
Our doctrine data persister does save the entity in database, setting automatically the identifier.
That hint helped me a lot.
The basic ArticleDataPersister is now working now.
// src/DataPersister/ArticleDataPersister.php
namespace App\DataPersister;
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use App\Entity\Article;
final class ArticleDataPersister implements ContextAwareDataPersisterInterface
{
private $decorated;
public function __construct(DataPersisterInterface $decorated)
{
$this->decorated = $decorated;
}
public function supports($data, array $context = []): bool
{
return $data instanceof Article;
}
public function persist($data, array $context = [])
{
$result = $this->decorated->persist($data, $context);
return $result;
}
public function remove($data, array $context = [])
{
return $this->decorated->remove($data, $context);
}
}
Had to add the following lines to the services.yaml
App\DataPersister\ArticleDataPersister:
decorates: 'api_platform.doctrine.orm.data_persister'
Thanks!!!
Most helpful comment
That hint helped me a lot.
The basic ArticleDataPersister is now working now.
Had to add the following lines to the services.yaml
Thanks!!!