无法为类型的项目生成IRI [英] Unable to generate an IRI for the item of type
问题描述
我实际上是在基于以下条件构建API:
I am actually building an API based on:
- symfony/flex:v1.0.61
- symfony:v4.0.3
- api-platform/api-pack:1.0.1版
- api平台/核心:v2.1.4
CRUD操作易于实现.尽管如此, 自定义操作似乎并不简单
The CRUD operations were easy to implement. Nevertheless, the custom operation does not seem to be straightforward.
我要实现的自定义操作将仅基于给定的$slug
返回一个App\Entity\Product
.
The custom operation I am trying to implement will simply return a App\Entity\Product
based on a given $slug
.
- 路线为:
/api/products/by-slugs/{slug}
- 方法是:
GET
- 操作类型为:
itemOperations
- the route is:
/api/products/by-slugs/{slug}
- the method is:
GET
- the operation type is:
itemOperations
这是做事的方式:
产品资源的声明
<?php
// src/Entity/Product
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Validator\Constraints as Assert;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ORM\Entity
* @ORM\Table(name="product")
* @ORM\Entity(repositoryClass="App\Repository\ProductRepository")
* @ApiResource(attributes={"pagination_client_items_per_page"=true,
* "filters"={"product.search"}
* },
* collectionOperations={
* "get"={
* "method"="GET",
* "normalization_context"={"groups"={"product_gets"}} },
* "post"={
* "method"="POST",
* "denormalization_context"={"groups"={"product_post"}} }
* },
* itemOperations={
* "get"={
* "method"="GET",
* "normalization_context"={"groups"={"product_get"}} },
* "put"={
* "method"="PUT",
* "denormalization_context"={"groups"={"product_put"}} },
* "delete"={
* "method"="DELETE"},
* "product_slug"={"route_name"="route_product_slug"}
* })
* @ORM\HasLifecycleCallbacks()
*/
class Product{
}
ProductLoader的声明
<?php
namespace App\Loader;
use App\Entity\Product;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Psr\Cache\CacheItemPoolInterface;
class ProductLoader {
private $em;
private $logger;
private $cache;
public function __construct(
EntityManagerInterface $em,
LoggerInterface $logger,
CacheItemPoolInterface $cache){
$this->em = $em;
$this->logger = $logger;
$this->cache = $cache;
}
public function findBySlug($slug){
return $this->em->getRepository(Product::class)->findProductBySlug($slug);
}
}
产品存储库的声明
<?php
namespace App\Repository;
use Doctrine\ORM\EntityRepository;
/**
* ProductRepository
*/
class ProductRepository extends EntityRepository {
public function findProductBySlug($slug) {
$qb = $this->createQueryBuilder("b")
->where("b.slug = :slug")
->setParameter('slug', $slug);
return $qb->getQuery()->getOneOrNullResult();
}
}
在Symfony控制器中声明自定义操作
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use App\Loader\ProductLoader;
use App\Entity\Product;
class ProductController extends Controller
{
/**
* @Route(
* name="route_product_slug",
* path="/api/products/by-slug/{slug}",
* defaults={"_api_resource_class"=Product::class,
* "_api_item_operation_name"="product_slug"
* }
* )
* @Method("GET")
*/
public function productsGetBySlugAction(ProductLoader $productLoader, $slug){
return $productLoader->findBySlug($slug);
}
}
快速返回以下命令:
bin/console debug:router
--------------------------------------- -------- -------- ------ ---------------------------------------
Name Method Scheme Host Path
--------------------------------------- -------- -------- ------ ---------------------------------------
app_product_products ANY ANY ANY /
route_product_slug GET ANY ANY /api/products/by-slug/{slug}
api_entrypoint ANY ANY ANY /api/{index}.{_format}
api_doc ANY ANY ANY /api/docs.{_format}
api_jsonld_context ANY ANY ANY /api/contexts/{shortName}.{_format}
api_products_get_collection GET ANY ANY /api/products.{_format}
api_products_post_collection POST ANY ANY /api/products.{_format}
api_products_get_item GET ANY ANY /api/products/{id}.{_format}
api_products_put_item PUT ANY ANY /api/products/{id}.{_format}
api_products_delete_item DELETE ANY ANY /api/products/{id}.{_format}
api_regions_get_collection GET ANY ANY /api/regions.{_format}
api_regions_post_collection POST ANY ANY /api/regions.{_format}
api_regions_get_item GET ANY ANY /api/regions/{id}.{_format}
api_regions_put_item PUT ANY ANY /api/regions/{id}.{_format}
api_regions_delete_item DELETE ANY ANY /api/regions/{id}.{_format}
api_countries_get_collection GET ANY ANY /api/countries.{_format}
api_countries_post_collection POST ANY ANY /api/countries.{_format}
api_countries_get_item GET ANY ANY /api/countries/{id}.{_format}
api_countries_put_item PUT ANY ANY /api/countries/{id}.{_format}
api_countries_delete_item DELETE ANY ANY /api/countries/{id}.{_format}
api_countries_regions_get_subresource GET ANY ANY /api/countries/{id}/regions.{_format}
_twig_error_test ANY ANY ANY /_error/{code}.{_format}
_wdt ANY ANY ANY /_wdt/{token}
_profiler_home ANY ANY ANY /_profiler/
_profiler_search ANY ANY ANY /_profiler/search
_profiler_search_bar ANY ANY ANY /_profiler/search_bar
_profiler_phpinfo ANY ANY ANY /_profiler/phpinfo
_profiler_search_results ANY ANY ANY /_profiler/{token}/search/results
_profiler_open_file ANY ANY ANY /_profiler/open
_profiler ANY ANY ANY /_profiler/{token}
_profiler_router ANY ANY ANY /_profiler/{token}/router
_profiler_exception ANY ANY ANY /_profiler/{token}/exception
_profiler_exception_css ANY ANY ANY /_profiler/{token}/exception.css
--------------------------------------- -------- -------- ------ ---------------------------------------
路线route_product_slug
已经存在,但是我总是遇到以下错误:
The route route_product_slug
is well existing but I am always getting the following error:
无法为App \ Entity \ Product类型的项目生成IRI "
{
"@context": "/sf-flex-40/public/index.php/api/contexts/Error",
"@type": "hydra:Error",
"hydra:title": "An error occurred",
"hydra:description": "Unable to generate an IRI for the item of type \"App\\Entity\\Product\"",
"trace": [
{
"namespace": "",
"short_class": "",
"class": "",
"type": "",
"function": "",
"file": "/home/amine/docker-projects/sf-flex-40/vendor/api-platform/core/src/Bridge/Symfony/Routing/IriConverter.php",
"line": 107,
"args": []
},
{
"namespace": "ApiPlatform\\Core\\Bridge\\Symfony\\Routing",
"short_class": "IriConverter",
"class": "ApiPlatform\\Core\\Bridge\\Symfony\\Routing\\IriConverter",
"type": "->",
"function": "getIriFromItem",
"file": "/home/amine/docker-projects/sf-flex-40/vendor/api-platform/core/src/JsonLd/Serializer/ItemNormalizer.php",
"line": 71,
"args": [
[
"object",
"App\\Entity\\Product"
]
]
},
该错误似乎经常发生.不过,我再次询问是因为问题似乎与我的启用Flex的symfony 4应用程序中的路由顺序不正确有关(请参阅
This error seems to be recurrent. Nevertheless, I am asking again since the problem seems to be related to bad order of routes in my flex-enable symfony 4 application (please refer to https://github.com/api-platform/core/issues/830).
因此,如果我在symfony 4中使用注释,如何设置路由的正确顺序.这些文件中定义了路由:
So, how can set the proper order of the routes if I am using the annotations in symfony 4. The routes are defined in these files:
第一个文件:annotations.yaml
# config/routes/annotations.yaml
controllers:
resource: ../../src/Controller/
type: annotation
第二个文件:api_platform.yaml
# config/routes/api_platform.yaml
api_platform:
resource: .
type: api_platform
prefix: /api
这是否意味着我必须用YAML文件配置我的所有工作来代替注释,以便我可以指定路线的顺序?
Does this mean I have to configure all my work with YAML file in stead of annotations so that I can specify the order of the route?
谢谢
这是什么
推荐答案
只能通过 yaml文件声明自定义操作的路由.实际上,使用注释不会使我们正确的路线顺序.自定义操作的路径必须在声明路径api_platform
之后.
The declaration of the route of the custom operation can only be through yaml file. In fact, the use of annotation will not us to get the correct order of routes. The route of the custom operation must come after the declaration of the route api_platform
.
api_platform:
resource: .
type: api_platform
prefix: /api
api_product_slug:
path: '/api/products/by-slug/{slug}'
methods: ['GET']
defaults:
_controller: App\Controller\ProductController:productsGetBySlugAction
_api_resource_class: 'App\Entity\Product'
_api_collection_operation_name: 'product_slug'
这篇关于无法为类型的项目生成IRI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!