2

I'm new to symfony but mostly api-platform. So I looked in the api-platform to learn more about it. I readed it for the big part, overwhelming in information. But I just couldn't find a way to use openAPI in a way to get edit post data. I'm also using doctrine and SQLite

So what I mean by edit post data. I installed api-platform and got it working (it looks like, this). I can POST data with my api-platform at the url www.localhost/api and then select POST under Role and then "try out". I made a small table in doctrine, so the JSON i send to it is;

{
  "role": "string"
}

So that works, it adds the data in my SQLite DB. But I want to edit this data in PHP. But I just can't find out how to retrieve this JSON and edit the data i get from the JSON.

What I have is; A Entity and Repository named Role and RoleRepository. And I readed a controller is not needed to edit the data with api-platform. But I cant find anywhere how to edit the data.

So how do I edit the data I get from the JSON?

Edit: If you are wondering what my entity Role looks like it is;

<?php
namespace App\Entity;

use App\Repository\RoleRepository;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ApiResource()
 * @ORM\Entity(repositoryClass=RoleRepository::class)
 */
class Role
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $role;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getRole(): ?string
    {
        return $this->role;
    }

    public function setRole(string $role): self
    {
        $this->role = $role;

        return $this;
    }
}

And RoleRepository

<?php

namespace App\Repository;

use App\Entity\Role;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

/**
 * @method Role|null find($id, $lockMode = null, $lockVersion = null)
 * @method Role|null findOneBy(array $criteria, array $orderBy = null)
 * @method Role[]    findAll()
 * @method Role[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class RoleRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Role::class);
    }

    // /**
    //  * @return Role[] Returns an array of Role objects
    //  */
    /*
    public function findByExampleField($value)
    {
        return $this->createQueryBuilder('r')
            ->andWhere('r.exampleField = :val')
            ->setParameter('val', $value)
            ->orderBy('r.id', 'ASC')
            ->setMaxResults(10)
            ->getQuery()
            ->getResult()
        ;
    }
    */

    /*
    public function findOneBySomeField($value): ?Role
    {
        return $this->createQueryBuilder('r')
            ->andWhere('r.exampleField = :val')
            ->setParameter('val', $value)
            ->getQuery()
            ->getOneOrNullResult()
        ;
    }
    */
}
4
  • 1
    Just to see if I understand you right, you would like to intercept the POST-ed JSON data before it is stored in the database, e.g. to change the behavior or add some more specific validation? Or are you looking for a way to not just create a new entity, but edit an existing one via the existing api? Commented Mar 10, 2021 at 11:48
  • 2
    Yes! I want to change the behavior or add some more specific validation. :) Commented Mar 10, 2021 at 11:55
  • Please share more details by editing your question Commented Mar 10, 2021 at 14:23
  • What details do you miss? Commented Mar 10, 2021 at 14:49

1 Answer 1

9

Symfony provides so called kernel events, which developers can hook into to handle requests/responses directly without needing to write a specific controller or to add attributes or change something before the data reaches the controller. You can find this in the docs for the HttpKernel component.

API Platform works by hooking into these events. You can see this by using the debug command for the event dispatcher:

bin/console debug:event-dispatcher

This should print out a list of events and what listeners act on the event and with api-platform you should have some new ones. Alternatively, you can look up the list of provided event listeners in the api-platform docs. For you the ReadListener and WriteListener are probably most relevant. You could also look at the DeserializeListener, but that works for all json input, so you have to be careful with that.

The ReadListener will read the existing data from the database using data providers. This is where you get your existing entity from, when you want to edit it. The WriteListener is how the new or edited data will be written to the database. This uses data persisters.

If you want to manually change how editing your entity works, you would probably want to write your own custom data persister or custom data provider.

When you write your own data persister you need to make sure that it supports your entity. You can pretty much copy the example from the docs for this and just change the class name. Then api-platform will call your persister and you can use var_dump or xdebug to check what values you get in your persist method. The first argument $data should be your entity and inside the second argument $context you should get more info, e.g. which http verb was used and I think also the decoded json data.

Writing your own providers and persisters can be a bit tricky and usually don't need to do it for every entity (unless you don't want to have standard getter and setter methods on them). Instead you can also modify how the entity is handled by adding metadata information similar to the @ApiResource annotation, e.g. for validation or for changing how the class is (de-)serialized. Additionally, the persister works on the already modified entity, so your json data is already validated. Nothing stops you from doing additional validation there, but it might be redundant or you might consider it too late. In short, for validation you should write your own validation constraints or use the ones provided by Symfony. For instance using something like the IsTrue constraint on an isX/hasX/getX-method might be a good way to solve your validation needs.

Sign up to request clarification or add additional context in comments.

2 Comments

This did the trick for me! I was reading and playing around with the data persisters. After a while I got it working and understood how it works! Thanks a lot :)
@Henkschipper would you mind sharing your data persister solution, for completeness?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.