Custom GET item without to have to specify id
See original GitHub issueI’m trying to create a custom action which could be called at GET /me
.
I implemented JWT token and now I want to get the user data thanks to the security storage or something else (by Bearer or something else).
My problem is that I can’t create a custom action to get just one item but without giving an ID. It seems ApiPlatform is built to always listen ID parameter for item action, when we use _api_item_operation_name.
Action :
<?php
namespace AppBundle\Action;
use AppBundle\Repository\UserRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Routing\Annotation\Route;
use AppBundle\Entity\User;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
class UserMe
{
/**
* @var UserRepository
*/
private $repository;
/**
* UserMe constructor.
*
* @param UserRepository $repository
*/
public function __construct(UserRepository $repository)
{
$this->repository= $repository;
}
/**
* @Route(
* name="api_users_me",
* path="/me",
* defaults={"_api_resource_class"=User::class, "_api_item_operation_name"="user_me"}
* )
* @Method("GET")
*/
public function __invoke($data)
{
// hard retrieve of an existing user in database to test
return $this->repository->find(5);
}
}
Result :
{
"@context": "/app_dev.php/contexts/Error",
"@type": "hydra:Error",
"hydra:title": "An error occurred",
"hydra:description": "Invalid identifier \"\", \"id\" has not been found.",
...
}
If you see, I don’t need to specify an “id” for my action, but API Plateform is expecting an identifier “id”.
Here my User entity :
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* User
*
* @ApiResource(
* collectionOperations={
* "get"={
* "method"="GET",
* "normalization_context"={"groups"={"get_collection"}}
* },
* },
* itemOperations={
* "get"={
* "method"="GET",
* "normalization_context"={"groups"={"get_item"}}
* },
* "user_me"={
* "route_name"="api_users_me"
* },
* }
* )
* @ORM\Table(name="user")
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User implements AdvancedUserInterface
{
// ...
}
In addition, here a router debug:
------------------------------------------- -------- -------- ------ ---------------------------------------
Name Method Scheme Host Path
------------------------------------------- -------- -------- ------ ---------------------------------------
_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_info ANY ANY ANY /_profiler/info/{about}
_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
_twig_error_test ANY ANY ANY /_error/{code}.{_format}
api_entrypoint ANY ANY ANY /{index}.{_format}
api_doc ANY ANY ANY /docs.{_format}
api_jsonld_context ANY ANY ANY /contexts/{shortName}.{_format}
api_bookmakers_get_collection GET ANY ANY /bookmakers.{_format}
api_bookmakers_get_item GET ANY ANY /bookmakers/{id}.{_format}
api_categories_get_collection GET ANY ANY /categories.{_format}
api_categories_get_item GET ANY ANY /categories/{id}.{_format}
api_comments_get_collection GET ANY ANY /comments.{_format}
api_comments_post_collection POST ANY ANY /comments.{_format}
api_comments_get_item GET ANY ANY /comments/{id}.{_format}
api_feed_items_get_collection GET ANY ANY /feed_items.{_format}
api_feed_items_post_collection POST ANY ANY /feed_items.{_format}
api_feed_items_get_item GET ANY ANY /feed_items/{id}.{_format}
api_feed_items_put_item PUT ANY ANY /feed_items/{id}.{_format}
api_follows_get_collection GET ANY ANY /follows.{_format}
api_follows_post_collection POST ANY ANY /follows.{_format}
api_follows_get_item GET ANY ANY /follows/{id}.{_format}
api_follows_delete_item DELETE ANY ANY /follows/{id}.{_format}
api_moderation_cards_get_collection GET ANY ANY /moderation_cards.{_format}
api_moderation_cards_get_item GET ANY ANY /moderation_cards/{id}.{_format}
api_picks_get_collection GET ANY ANY /picks.{_format}
api_picks_post_collection POST ANY ANY /picks.{_format}
api_picks_get_item GET ANY ANY /picks/{id}.{_format}
api_picks_put_item PUT ANY ANY /picks/{id}.{_format}
api_report_picks_post_collection POST ANY ANY /report_picks.{_format}
api_subpicks_get_collection GET ANY ANY /subpicks.{_format}
api_subpicks_post_collection POST ANY ANY /subpicks.{_format}
api_subpicks_get_item GET ANY ANY /subpicks/{id}.{_format}
api_subpicks_put_item PUT ANY ANY /subpicks/{id}.{_format}
api_subpick_type_events_get_item GET ANY ANY /subpick_type_events/{id}.{_format}
api_subpick_type_frees_get_item GET ANY ANY /subpick_type_frees/{id}.{_format}
api_subscribed_bookmakers_get_collection GET ANY ANY /subscribed_bookmakers.{_format}
api_subscribed_bookmakers_post_collection POST ANY ANY /subscribed_bookmakers.{_format}
api_subscribed_bookmakers_get_item GET ANY ANY /subscribed_bookmakers/{id}.{_format}
api_subscribed_bookmakers_delete_item DELETE ANY ANY /subscribed_bookmakers/{id}.{_format}
api_users_get_collection GET ANY ANY /users.{_format}
api_users_post_collection POST ANY ANY /users.{_format}
api_users_get_item GET ANY ANY /users/{id}.{_format}
api_users_put_item PUT ANY ANY /users/{id}.{_format}
api_user_likes_get_collection GET ANY ANY /user_likes.{_format}
api_user_likes_post_collection POST ANY ANY /user_likes.{_format}
api_user_likes_get_item GET ANY ANY /user_likes/{id}.{_format}
api_user_likes_delete_item DELETE ANY ANY /user_likes/{id}.{_format}
api_login_check ANY ANY ANY /login_check
api_jwt_refresh_token ANY ANY ANY /token/refresh
api_users_me GET ANY ANY /me
------------------------------------------- -------- -------- ------ ---------------------------------------
The route is here.
Documentation also generate a required “id” field, while i don’t want it :
I also tried to “cheat” by using “_api_collection_operation_name”, and redapt User correctly, but i got an “Illegal offset” error even if i return an array containing the User in method __invoke($data)
Do you have a solution ? Anyway, thanks for this useful bundle !
Issue Analytics
- State:
- Created 6 years ago
- Comments:23 (5 by maintainers)
Even if it doesn’t respect the REST philosophy, I paste my solution for the ones who need to implement a similar action like
/me
:Action:
Provider:
Register the provider:
And as a bonus, don’t forget to secure the
/me
route (if you are using LexikJWTAuthenticationBundle for example):You can also just use move your action to the collection_items, since there is no required id attribute there.