私は実際に以下に基づいてAPIを構築しています:
- symfony/フレックス: v1.0.61
- symfony: v4.0.3
- API プラットフォーム/API パック: v1.0.1
- API プラットフォーム/コア: v2.1.4
CRUD 操作は簡単に実装できました。それにもかかわらず、 カスタム操作は単純ではないようです。
App\Entity\Product
実装しようとしているカスタム操作は、指定された に基づいて を返すだけ$slug
です。
- ルートは次のとおりです。
/api/products/by-slugs/{slug}
- メソッドは次のとおりです。
GET
- 操作タイプは次のとおりです。
itemOperations
これは物事が行われている方法です:
Product リソースの宣言
<?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);
}
}
ProductRepository の宣言
<?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
は十分に存在しますが、常に次のエラーが発生します。
タイプ 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"
]
]
},
このエラーは繰り返されるようです。それにもかかわらず、この問題は symfony 4 アプリケーションの flex-enable でのルートの順序の誤りに関連しているように思われるため、再度質問します ( https://github.com/api-platform/core/issues/830を参照してください)。
では、symfony 4 でアノテーションを使用している場合、ルートの適切な順序を設定するにはどうすればよいでしょうか。ルートはこれらのファイルで定義されています。
最初のファイル: annotations.yaml
# config/routes/annotations.yaml
controllers:
resource: ../../src/Controller/
type: annotation
2 番目のファイル: api_platform.yaml
# config/routes/api_platform.yaml
api_platform:
resource: .
type: api_platform
prefix: /api
これは、ルートの順序を指定できるように、注釈の代わりに YAML ファイルを使用してすべての作業を構成する必要があるということですか?
ありがとう
ここで何