POST method api custom end point having unnecessary mandatory ID field - php

I have this custom API endpoint call "register". I had added into "ItemOperations" of the User Entity with the declaration of "POST". When I check back to api platform UI, I saw that there is unnecessary ID field is being mandatory to key in as shown in the screenshot attached.
This is my User Entity codes that I have tried
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ApiResource(
* collectionOperations={"get","post"},
* itemOperations={
* "get",
* "put",
* "register"={
* "method"="POST",
* "path"="/register",
* "controller"=User::class,
* }
* },
* normalizationContext={
* "groups"={"user:read"},"swagger_definition_name"="Read"
* },
* denormalizationContext={
* "groups"={"user:write"},"swagger_definition_name"="Write"
* },
* shortName="User"
*
* )
* #UniqueEntity(fields={"email"})
* #UniqueEntity(fields={"contact"})
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=180, unique=true)
* #Groups({"user:read", "user:write"})
* #Assert\Email()
* #Assert\NotBlank()
*/
private $email;
/**
* #ORM\Column(type="json")
*/
private $roles = [];
/**
* #var string The hashed password
* #ORM\Column(type="string")
* #Groups({"user:write"})
* #Assert\NotBlank()
*/
private $password;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"user:read", "user:write"})
* #Assert\NotBlank()
*/
private $firstName;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"user:read", "user:write"})
* #Assert\NotBlank()
*/
private $lastName;
/**
* #var string provide in YYYY-MM-DD (neglect Time)
* #ORM\Column(type="date")
* #Groups({"user:read", "user:write"})
* #Assert\NotBlank()
*/
private $dob;
/**
* #ORM\Column(type="text")
* #Groups({"user:read", "user:write"})
* #Assert\NotBlank()
*/
private $address;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"user:read", "user:write"})
* #Assert\NotBlank()
* #Assert\Length(
* min=8,
* max=8,
* maxMessage="contact number must have 8 character",
* minMessage="contact number must have 8 character"
* )
*/
private $contact;
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* #see UserInterface
*/
public function getUsername(): string
{
return (string) $this->email;
}
/**
* #see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* #see UserInterface
*/
public function getPassword(): string
{
return (string) $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* #see UserInterface
*/
public function getSalt()
{
// not needed when using the "bcrypt" algorithm in security.yaml
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(string $firstName): self
{
$this->firstName = $firstName;
return $this;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(string $lastName): self
{
$this->lastName = $lastName;
return $this;
}
public function getDob(): ?\DateTimeInterface
{
return $this->dob;
}
public function setDob(\DateTimeInterface $dob): self
{
$this->dob = $dob;
return $this;
}
public function getAddress(): ?string
{
return $this->address;
}
public function setAddress(string $address): self
{
$this->address = $address;
return $this;
}
public function getContact(): ?string
{
return $this->contact;
}
public function setContact(string $contact): self
{
$this->contact = $contact;
return $this;
}
}
And this is my AuthController
<?php
namespace App\Controller;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class AuthController extends AbstractController
{
/**
* #param Request $request
* #param UserPasswordEncoderInterface $encoder
* #param EntityManagerInterface $entity_manager
*
* #return JsonResponse
* #throws \Exception
*/
public function register(Request $request, UserPasswordEncoderInterface $encoder, EntityManagerInterface $entity_manager)
{
try{
$contentType = $request->getContentType();
$content = $request->getContent();
$response = new JsonResponse();
if ($contentType != 'json' || !$content) {
$response -> setContent(json_encode(['fail' => 'empty content type or content type is not json format']));
$response ->setStatusCode(Response::HTTP_BAD_REQUEST,'Bad Request');
}else{
$data = json_decode($content, true);
$email = $data['email'];
$hasUser = $entity_manager->getRepository(User::class)->findByEmail($email);
if($hasUser){
$response -> setContent(json_encode(['fail' => 'user already registered']));
$response ->setStatusCode(Response::HTTP_BAD_REQUEST,'Bad Request');
return $response;
}
//Update User
$user = new User();
$user ->setEmail($data['email']);
$user ->setFirstName($data['firstName']);
$user->setLastName($data['lastName']);
$user->setDob(new \DateTime($data['dob']));
$user->setAddress($data['address']);
$user->setContact($data['contact']);
$user->setPassword($encoder->encodePassword($user,
$data['password']
));
$entity_manager->persist($user);
$entity_manager->flush();
$response -> setContent(json_encode(['success' => 'user successfully added']));
$response -> setStatusCode(Response::HTTP_CREATED,'Created');
}
return $response;
}catch (Exception $e){
//TODO: Log Error
$response -> setContent(json_encode(['fail' => 'Internal Server Error']));
$response ->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR,'Bad Request');
}
}
}
I wanted to remove the "Id" mandatory field when I post register. Is there any way that I can do? I am stuck this problem for almost two days. Sorry if I miss out something since I am quite new to API platform

You need to use the POST Action in Collection Operations, ItemOperation are for getting, updating or deleting your resource, thats why the id is mandatory.
And point your Action to the controller, not the Entity
#ApiResource(
* collectionOperations={
* "get",
* "post",
* "register"={
* "method"="POST",
* "path"="/register",
* "controller"= AuthController::class,
* }
* },
* itemOperations={
* "get",
* "put",
* },
* normalizationContext={
* "groups"={"user:read"},"swagger_definition_name"="Read"
* },
* denormalizationContext={
* "groups"={"user:write"},"swagger_definition_name"="Write"
* },
* shortName="User"
* * )

Related

API Platform Many to One not expecting IRI

I am using API Platform with Symfony for my backend.
I have 2 entities linked with a ManyToOne relationship, Booking and User.
A user can have one or many bookings.
I also have another entity Service, with a OneToMany relationship with Booking.
When I try to test the POST for Bookings on the Swagger interface I get an error on the IRI format for services but not for the others.
Nothing works as input for the fields related to User (provider, client).
I don't understand why it doesn't work. I only get a 400 error.
Here are my entities :
Booking:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\BookingRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* #ApiResource(
* normalizationContext={"groups"={"booking:read"}},
* denormalizationContext={"groups"={"booking:write"}},
* collectionOperations={
* "get",
* "post"={"security"="is_granted('ROLE_USER')"}
* },
* itemOperations={
* "get",
* "put"={"security"="is_granted('edit', object)"},
* "patch"={"security"="is_granted('edit', object)"},
* "delete"={"security"="is_granted('delete', object)"}
* }
* )
* #ORM\Entity(repositoryClass=BookingRepository::class)
*/
class Booking
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*
* #Groups("booking:read")
*/
private $id;
/**
* #ORM\Column(type="date")
*
* #Groups({"booking:read","booking:write"})
*/
private $bookingDate;
/**
* #ORM\Column(type="datetime_immutable")
*
* #Groups("booking:read")
*/
private $reservedAt;
/**
* #ORM\Column(type="string", length=255)
*
* #Groups({"booking:read","booking:write"})
*/
private $location;
/**
* #ORM\Column(type="time")
*
* #Groups({"booking:read","booking:write"})
*/
private $startTime;
/**
* #ORM\Column(type="time")
*
* #Groups({"booking:read","booking:write"})
*/
private $endTime;
/**
* #ORM\ManyToOne(targetEntity=User::class, inversedBy="bookingsAsProvider")
* #ORM\JoinColumn(nullable=false)
*
* #Groups({"booking:read","booking:write"})
*/
private $provider;
/**
* #ORM\ManyToOne(targetEntity=User::class, inversedBy="bookingsAsClient")
* #ORM\JoinColumn(nullable=false)
*
* #Groups({"booking:read","booking:write"})
*/
private $client;
/**
* #ORM\ManyToOne(targetEntity=Service::class, inversedBy="bookings")
* #ORM\JoinColumn(nullable=false)
* #Groups({"booking:read","booking:write"})
*/
private $service;
/**
* #ORM\Column(type="integer")
* #Groups({"booking:read","booking:write"})
*/
private $state;
/**
* #ORM\Column(type="boolean")
* #Groups({"booking:read","booking:write"})
*/
private $read;
public function getId(): ?int
{
return $this->id;
}
public function getBookingDate(): ?\DateTimeInterface
{
return $this->bookingDate;
}
public function setBookingDate(\DateTimeInterface $bookingDate): self
{
$this->bookingDate = $bookingDate;
return $this;
}
public function getReservedAt(): ?\DateTimeImmutable
{
return $this->reservedAt;
}
public function setReservedAt(\DateTimeImmutable $reservedAt): self
{
$this->reservedAt = $reservedAt;
return $this;
}
public function getLocation(): ?string
{
return $this->location;
}
public function setLocation(string $location): self
{
$this->location = $location;
return $this;
}
public function getStartTime(): ?\DateTimeInterface
{
return $this->startTime;
}
public function setStartTime(\DateTimeInterface $startTime): self
{
$this->startTime = $startTime;
return $this;
}
public function getEndTime(): ?\DateTimeInterface
{
return $this->endTime;
}
public function setEndTime(\DateTimeInterface $endTime): self
{
$this->endTime = $endTime;
return $this;
}
public function getProvider(): ?User
{
return $this->provider;
}
public function setProvider(?User $provider): self
{
$this->provider = $provider;
return $this;
}
public function getClient(): ?User
{
return $this->client;
}
public function setClient(?User $client): self
{
$this->client = $client;
return $this;
}
public function getService(): ?Service
{
return $this->service;
}
public function setService(?Service $service): self
{
$this->service = $service;
return $this;
}
public function getState(): ?int
{
return $this->state;
}
public function setState(int $state): self
{
$this->state = $state;
return $this;
}
public function getRead(): ?bool
{
return $this->read;
}
public function setRead(bool $read): self
{
$this->read = $read;
return $this;
}
}
User:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
/**
* #ORM\Entity(repositoryClass=UserRepository::class)
*
* #ApiResource(
* normalizationContext={"groups"={"user:read"}},
* denormalizationContext={"groups"={"user:write"}},
* collectionOperations={
* "get"={"security"="is_granted('ROLE_ADMIN') or object == user"},
* "post"={"security"="is_granted('ROLE_ADMIN_FRONTEND')"}
* },
* itemOperations={
* "get",
* "put"={"security"="is_granted('ROLE_ADMIN') or object == user"},
* "patch"={"security"="is_granted('ROLE_ADMIN') or object == user"},
* "delete"={"security"="is_granted('ROLE_ADMIN')"},
* "get_by_role" = {
* "method" = "GET",
* "path" = "/user/{role}",
* "controller" = User::class,
* "read"=false,
* "openapi_context" = {
* "parameters" = {
* {
* "name" = "role",
* "in" = "path",
* "description" = "The role of a user",
* "type" = "string",
* "required" = true,
* "example"= "ROLE_PARENT",
* },
* },
* },
* },
* },
* )
*
* #ORM\Table(name="`user`")
*/
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*
* #Groups({"user:read","service:read","booking:read"})
*/
private $id;
/**
* #ORM\Column(type="string", length=180, unique=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $email;
/**
* #ORM\Column(type="json")
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $roles = [];
/**
* #var string The hashed password
* #ORM\Column(type="string")
*/
private $password;
/**
* #Groups("user:write")
*
* #SerializedName("password")
*/
private $plainPassword;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read","booking:read"})
*/
private $name;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read","booking:read"})
*/
private $firstname;
/**
* #ORM\Column(type="string", length=255, unique=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $username;
/**
* #ORM\Column(type="string", length=50, nullable=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $phone;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $facebook;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $instagram;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $linkedin;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $twitter;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $pinterest;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $website;
/**
* #ORM\Column(type="text", nullable=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $tagline;
/**
* #ORM\Column(type="text", nullable=true)
*
* #Groups({"user:read", "user:write","businessRelationship:read","service:read"})
*/
private $description;
/**
* #ORM\OneToMany(targetEntity=Address::class, mappedBy="client",cascade={"persist"})
*
* #Groups({"user:read", "user:write"})
* #ApiSubresource
*/
private $addresses;
/**
* #ORM\ManyToMany(targetEntity=Service::class, mappedBy="performer")
* #ApiSubresource
*/
private $servicesAsPerformer;
/**
* #ORM\OneToMany(targetEntity=Service::class, mappedBy="owner")
* #ApiSubresource
*/
private $servicesAsOwner;
/**
* #ORM\OneToMany(targetEntity=BusinessRelationship::class, mappedBy="partnerA")
* #ApiSubresource
*/
private $businessRelationshipsPartnerA;
/**
* #ORM\OneToMany(targetEntity=BusinessRelationship::class, mappedBy="partnerB")
* #ApiSubresource
*/
private $businessRelationshipsPartnerB;
/**
* #ORM\OneToMany(targetEntity=Booking::class, mappedBy="provider")
* #ApiSubresource
*/
private $bookingsAsProvider;
/**
* #ORM\OneToMany(targetEntity=Booking::class, mappedBy="client")
* #ApiSubresource
*/
private $bookingsAsClient;
/**
* #ORM\OneToMany(targetEntity=Schedule::class, mappedBy="provider")
* #ApiSubresource
*/
private $schedules;
/**
* #ORM\OneToMany(targetEntity=UserCategory::class, mappedBy="provider")
* #ApiSubresource
*
* #Groups({"user:read", "user:write"})
*/
private $userCategories;
/**
* #ORM\Column(type="text", nullable=true)
* #Groups({"user:read", "user:write"})
*/
private $profilePicture;
/**
* #ORM\Column(type="text", length=16777215, nullable=true)
* #Groups({"user:read", "user:write"})
*/
private $gallery;
/**
* #ORM\OneToMany(targetEntity=Notification::class, mappedBy="userOrigin")
* #ApiSubresource
*
* #Groups({"user:read", "user:write"})
*/
private $notificationsUserOrigin;
/**
* #ORM\OneToMany(targetEntity=Notification::class, mappedBy="userTarget")
* #ApiSubresource
*
* #Groups({"user:read", "user:write"})
*/
private $notificationsUserTarget;
/**
* #ORM\Column(type="string", length=100, nullable=true)
*/
private $resetToken;
public function __construct()
{
$this->addresses = new ArrayCollection();
$this->servicesAsPerformer = new ArrayCollection();
$this->servicesAsOwner = new ArrayCollection();
$this->businessRelationshipsPartnerA = new ArrayCollection();
$this->businessRelationshipsPartnerB = new ArrayCollection();
$this->bookingsAsProvider = new ArrayCollection();
$this->bookingsAsClient = new ArrayCollection();
$this->schedules = new ArrayCollection();
$this->userCategories = new ArrayCollection();
$this->notificationsUserOrigin = new ArrayCollection();
$this->notificationsUserTarget = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* #see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->email;
}
/**
* #deprecated since Symfony 5.3, use getUserIdentifier instead
*/
// public function getUsername(): string
// {
// return (string) $this->email;
// }
/**
* #see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* #see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* Returning a salt is only needed, if you are not using a modern
* hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
*
* #see UserInterface
*/
public function getSalt(): ?string
{
return null;
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
$this->plainPassword = null;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getFirstname(): ?string
{
return $this->firstname;
}
public function setFirstname(?string $firstname): self
{
$this->firstname = $firstname;
return $this;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
public function getPhone(): ?string
{
return $this->phone;
}
public function setPhone(?string $phone): self
{
$this->phone = $phone;
return $this;
}
public function getFacebook(): ?string
{
return $this->facebook;
}
public function setFacebook(?string $facebook): self
{
$this->facebook = $facebook;
return $this;
}
public function getInstagram(): ?string
{
return $this->instagram;
}
public function setInstagram(?string $instagram): self
{
$this->instagram = $instagram;
return $this;
}
public function getLinkedin(): ?string
{
return $this->linkedin;
}
public function setLinkedin(?string $linkedin): self
{
$this->linkedin = $linkedin;
return $this;
}
public function getTwitter(): ?string
{
return $this->twitter;
}
public function setTwitter(?string $twitter): self
{
$this->twitter = $twitter;
return $this;
}
public function getPinterest(): ?string
{
return $this->pinterest;
}
public function setPinterest(?string $pinterest): self
{
$this->pinterest = $pinterest;
return $this;
}
public function getWebsite(): ?string
{
return $this->website;
}
public function setWebsite(?string $website): self
{
$this->website = $website;
return $this;
}
public function getTagline(): ?string
{
return $this->tagline;
}
public function setTagline(?string $tagline): self
{
$this->tagline = $tagline;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getPlainPassword(): ?string
{
return $this->plainPassword;
}
public function setPlainPassword(?string $plainPassword): self
{
$this->plainPassword = $plainPassword;
return $this;
}
/**
* #return Collection|Address[]
*/
public function getAddresses(): Collection
{
return $this->addresses;
}
public function addAddress(Address $address): self
{
if (!$this->addresses->contains($address)) {
$this->addresses[] = $address;
$address->setClient($this);
}
return $this;
}
public function removeAddress(Address $address): self
{
if ($this->addresses->removeElement($address)) {
// set the owning side to null (unless already changed)
if ($address->getClient() === $this) {
$address->setClient(null);
}
}
return $this;
}
public function hasRoles(string $roles): bool
{
return in_array($roles, $this->roles);
}
/**
* #return Collection|Service[]
*/
public function getServicesAsPerformer(): Collection
{
return $this->servicesAsPerformer;
}
public function addServicesAsPerformer(Service $servicesAsPerformer): self
{
if (!$this->servicesAsPerformer->contains($servicesAsPerformer)) {
$this->servicesAsPerformer[] = $servicesAsPerformer;
$servicesAsPerformer->addPerformer($this);
}
return $this;
}
public function removeServicesAsPerformer(Service $servicesAsPerformer): self
{
if ($this->servicesAsPerformer->removeElement($servicesAsPerformer)) {
$servicesAsPerformer->removePerformer($this);
}
return $this;
}
/**
* #return Collection|Service[]
*/
public function getServicesAsOwner(): Collection
{
return $this->servicesAsOwner;
}
public function addServicesAsOwner(Service $servicesAsOwner): self
{
if (!$this->servicesAsOwner->contains($servicesAsOwner)) {
$this->servicesAsOwner[] = $servicesAsOwner;
$servicesAsOwner->setOwner($this);
}
return $this;
}
public function removeServicesAsOwner(Service $servicesAsOwner): self
{
if ($this->servicesAsOwner->removeElement($servicesAsOwner)) {
// set the owning side to null (unless already changed)
if ($servicesAsOwner->getOwner() === $this) {
$servicesAsOwner->setOwner(null);
}
}
return $this;
}
/**
* #return Collection|BusinessRelationship[]
*/
public function getBusinessRelationshipsPartnerA(): Collection
{
return $this->businessRelationshipsPartnerA;
}
public function addBusinessRelationshipsPartnerA(BusinessRelationship $businessRelationshipsPartnerA): self
{
if (!$this->businessRelationshipsPartnerA->contains($businessRelationshipsPartnerA)) {
$this->businessRelationshipsPartnerA[] = $businessRelationshipsPartnerA;
$businessRelationshipsPartnerA->setPartnerA($this);
}
return $this;
}
public function removeBusinessRelationshipsPartnerA(BusinessRelationship $businessRelationshipsPartnerA): self
{
if ($this->businessRelationshipsPartnerA->removeElement($businessRelationshipsPartnerA)) {
// set the owning side to null (unless already changed)
if ($businessRelationshipsPartnerA->getPartnerA() === $this) {
$businessRelationshipsPartnerA->setPartnerA(null);
}
}
return $this;
}
/**
* #return Collection|BusinessRelationship[]
*/
public function getBusinessRelationshipsPartnerB(): Collection
{
return $this->businessRelationshipsPartnerB;
}
public function addBusinessRelationshipsPartnerB(BusinessRelationship $businessRelationshipsPartnerB): self
{
if (!$this->businessRelationshipsPartnerB->contains($businessRelationshipsPartnerB)) {
$this->businessRelationshipsPartnerB[] = $businessRelationshipsPartnerB;
$businessRelationshipsPartnerB->setPartnerB($this);
}
return $this;
}
public function removeBusinessRelationshipsPartnerB(BusinessRelationship $businessRelationshipsPartnerB): self
{
if ($this->businessRelationshipsPartnerB->removeElement($businessRelationshipsPartnerB)) {
// set the owning side to null (unless already changed)
if ($businessRelationshipsPartnerB->getPartnerB() === $this) {
$businessRelationshipsPartnerB->setPartnerB(null);
}
}
return $this;
}
/**
* #return Collection|Booking[]
*/
public function getBookingsAsProvider(): Collection
{
return $this->bookingsAsProvider;
}
public function addBookingsAsProvider(Booking $bookingsAsProvider): self
{
if (!$this->bookingsAsProvider->contains($bookingsAsProvider)) {
$this->bookingsAsProvider[] = $bookingsAsProvider;
$bookingsAsProvider->setProvider($this);
}
return $this;
}
public function removeBookingsAsProvider(Booking $bookingsAsProvider): self
{
if ($this->bookingsAsProvider->removeElement($bookingsAsProvider)) {
// set the owning side to null (unless already changed)
if ($bookingsAsProvider->getProvider() === $this) {
$bookingsAsProvider->setProvider(null);
}
}
return $this;
}
/**
* #return Collection|Booking[]
*/
public function getBookingsAsClient(): Collection
{
return $this->bookingsAsClient;
}
public function addBookingsAsClient(Booking $bookingsAsClient): self
{
if (!$this->bookingsAsClient->contains($bookingsAsClient)) {
$this->bookingsAsClient[] = $bookingsAsClient;
$bookingsAsClient->setClient($this);
}
return $this;
}
public function removeBookingsAsClient(Booking $bookingsAsClient): self
{
if ($this->bookingsAsClient->removeElement($bookingsAsClient)) {
// set the owning side to null (unless already changed)
if ($bookingsAsClient->getClient() === $this) {
$bookingsAsClient->setClient(null);
}
}
return $this;
}
[...]
}
Service:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
use App\Repository\ServiceRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* #ApiResource(
* normalizationContext={"groups"={"service:read"}},
* denormalizationContext={"groups"={"service:write"}},
* collectionOperations={
* "get",
* "post"={"security"="is_granted('ROLE_USER')"}
* },
* itemOperations={
* "get",
* "put"={"security"="is_granted('edit', object)"},
* "patch"={"security"="is_granted('edit', object)"},
* "delete"={"security"="is_granted('delete', object)"}
* }
* )
* #ORM\Entity(repositoryClass=ServiceRepository::class)
*/
class Service
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*
* #Groups({"service:read","schedule:read"})
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*
* #Groups({"service:read", "service:write","schedule:read"})
*/
private $name;
/**
* #ORM\Column(type="float")
*
* #Groups({"service:read", "service:write","schedule:read"})
*/
private $price;
/**
* #ORM\Column(type="text", nullable=true)
*
* #Groups({"service:read", "service:write","schedule:read"})
*/
private $description;
/**
* #ORM\ManyToMany(targetEntity=Address::class, inversedBy="services")
*
* #Groups({"service:read", "service:write"})
* #ApiSubresource
*/
private $addresses;
/**
* #ORM\ManyToMany(targetEntity=User::class, inversedBy="servicesAsPerformer")
* #Groups({"service:read", "service:write","schedule:read"})
*/
private $performer;
/**
* #ORM\ManyToOne(targetEntity=User::class, inversedBy="servicesAsOwner")
* #Groups({"service:read", "service:write","schedule:read"})
*/
private $owner;
/**
* #ORM\ManyToMany(targetEntity=Schedule::class, mappedBy="services")
* #Groups({"service:read", "service:write"})
* #ApiSubresource
*/
private $schedules;
/**
* #ORM\OneToMany(targetEntity=Booking::class, mappedBy="service")
*/
private $bookings;
public function __construct()
{
$this->addresses = new ArrayCollection();
$this->performer = new ArrayCollection();
$this->schedules = new ArrayCollection();
$this->bookings = new ArrayCollection();
}
[...]
}
Here are the JSON inputs I tried with the response I get :
Error 400 "Syntax Error"
{
"bookingDate": "2022-11-14T14:59:49.322Z",
"location": "string",
"startTime": "2022-11-14T14:59:49.322Z",
"endTime": "2022-11-14T14:59:49.322Z",
"provider": "string",
"client": "string",
"service": "\api\services\725",
"state": 0,
"read": true
}
Error 400 "Invalid IRI "string"."
{
"bookingDate": "2022-11-14T14:59:49.322Z",
"location": "string",
"startTime": "2022-11-14T14:59:49.322Z",
"endTime": "2022-11-14T14:59:49.322Z",
"provider": "string",
"client": "string",
"service": "string",
"state": 0,
"read": true
}
I really don't see why for service it expects an IRI format, while not for client and provider.

Api plateform denormalization custom operation with relation

I have 2 entities Voucher and Client (which extend User entity) with a OneToOne relation, I have a custom operation in the voucher entity, I want to denormalize the the client entity in this operation ( to be able to validate the properties later) but it won't show in the swagger documentation
Voucher Entity :
<?php
/**
* #ApiResource(
* collectionOperations={
* "add_voucher"={
* "access_control"="is_granted('ROLE_COMMERCIAL')",
* "method"="POST",
* "path"="/vouchers/add-new",
* "controller"=AddVoucherAction::class,
* "security_post_denormalize_message"="Sorry, Only Commercials can Generate Vouchers",
* "denormalization_context"={
* "groups"={"add_new_voucher"}
* },
* "validation_groups"={"Default", "add_voucher_validation"}
* },
* }
* )
* #ORM\Entity(repositoryClass="App\Repository\VoucherRepository", repositoryClass=VoucherRepository::class)
*/
class Voucher
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #Groups("add_new_voucher")
* #ORM\Column(type="string", length=255, unique=true)
*/
private $code;
/**
* #Groups("add_new_voucher")
* #ORM\Column(type="integer")
*/
private $discount;
/**
* #Groups("add_new_voucher")
* #OneToOne(targetEntity="App\Entity\Client")
* #JoinColumn(name="client_id", referencedColumnName="id")
*/
private $client;
public function getDiscount()
{
return $this->discount;
}
public function setDiscount($discount): void
{
$this->discount = $discount;
}
public function getClient()
{
return $this->client;
}
public function setClient($client): void
{
$this->client = $client;
}
public function getId(): ?int
{
return $this->id;
}
public function getCode(): ?string
{
return $this->code;
}
public function setCode(string $code): self
{
$this->code = $code;
return $this;
}
}
Client Entity :
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\ClientRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use App\Entity\Language;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ApiResource(
* collectionOperations={
* "post"={
* "method"="POST",
* "validation_groups"={"registerValidation"},
* }
* },
* denormalizationContext={"groups"={"register"}}
* )
* #ORM\Entity(repositoryClass=ClientRepository::class)
*/
class Client extends User
{
/**
* #Groups("register")
* #ORM\ManyToOne(targetEntity=Language::class, inversedBy="client")
*/
private $language;
/**
* #Groups({"register","add_new_voucher"})
* #Assert\NotBlank(groups="registerValidation")
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $country;
/**
* #Groups("register")
* #Assert\NotBlank(groups="registerValidation")
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $currency;
/**
* #Groups("register")
* #Assert\NotBlank(groups="registerValidation")
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $timezone;
/**
* #Groups("register")
* #Assert\NotBlank(groups="registerValidation")
* #ORM\Column(type="integer", nullable=true)
*/
private $phone;
/**
* Client constructor.
* #param $language
* #param $country
* #param $currency
* #param $timezone
* #param $phone
*/
public function __construct($language, $country, $currency, $timezone, $phone)
{
parent:: __construct();
$this->language = $language;
$this->country = $country;
$this->currency = $currency;
$this->timezone = $timezone;
$this->phone = $phone;
}
public function getLanguage()
{
return $this->language;
}
public function setLanguage($language): void
{
$this->language = $language;
}
public function getCountry(): ?string
{
return $this->country;
}
public function setCountry(?string $country): self
{
$this->country = $country;
return $this;
}
public function getCurrency(): ?string
{
return $this->currency;
}
public function setCurrency(?string $currency): self
{
$this->currency = $currency;
return $this;
}
public function getTimezone(): ?string
{
return $this->timezone;
}
public function setTimezone(?string $timezone): self
{
$this->timezone = $timezone;
return $this;
}
public function getPhone(): ?int
{
return $this->phone;
}
public function setPhone(?int $phone): self
{
$this->phone = $phone;
return $this;
}
}
I tried to add the denormalization group to the client relation and to the country property in client entity but in swagger the operation show only the code and discount property

API Platform - Data persister - Can't create new user

I'm currently trying out API Platform & I'm currently having a problem with my Data Persister when I try to create (post) a new user.
This is my User entity :
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Carbon\Carbon;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
/**
* #ApiResource(
* collectionOperations={
* "get",
* "post"={
* "security"="is_granted('ROLE_ADMIN')"
* },
* },
* itemOperations={
* "get",
* "put"={"security"="is_granted('ROLE_ADMIN') and object == user"},
* "delete"={"security"="is_granted('ROLE_ADMIN')"}
* },
* attributes={
* "fetchEager": false,
* "normalization_context"={"groups"={"user.read"}},
* "denormalization_context"={"groups"={"user.write"}}
* }
* )
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
* #ORM\HasLifecycleCallbacks()
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
* #Groups({
* "user.read"
* })
*/
private $id;
/**
* #ORM\Column(type="string", length=180, unique=true)
* #Groups({
* "user.read",
* "user.write"
* })
*/
private $email;
/**
* #ORM\Column(type="json")
* #Groups({
* "user.read",
* "user.write"
* })
*/
private $roles = [];
/**
* #Groups({
* "user.write"
* })
*/
private $plainPassword;
/**
* #var string The hashed password
* #ORM\Column(type="string")
*/
private $password;
/**
* #ORM\Column(type="datetime")
*/
private $createdAt;
/**
* #ORM\Column(type="datetime")
*/
private $updatedAt;
/**
* User constructor.
*/
public function __construct()
{
$this->roles = [];
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* #see UserInterface
*/
public function getUsername(): string
{
return (string) $this->email;
}
/**
* #see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
public function getPlainPassword()
{
return $this->plainPassword;
}
public function setPlainPassword($password)
{
$this->plainPassword = $password;
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
$this->password = $password;
}
/**
* #see UserInterface
*/
public function getSalt()
{
// not needed when using the "bcrypt" algorithm in security.yaml
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
$this->plainPassword = null;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
/**
* #ORM\PrePersist()
*/
public function setCreatedAt(): void
{
$this->createdAt = Carbon::now();
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function setUpdatedAt(): void
{
$this->updatedAt = Carbon::now();
}
}
And here's my Data Persister :
<?php
namespace App\DataPersister;
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class UserDataPersister implements DataPersisterInterface
{
private $userPasswordEncoder;
private $entityManager;
public function __construct(EntityManagerInterface $entityManager, UserPasswordEncoderInterface $userPasswordEncoder)
{
$this->userPasswordEncoder = $userPasswordEncoder;
$this->entityManager = $entityManager;
}
public function supports($data): bool
{
return $data instanceof User;
}
/**
* #param User $data
*/
public function persist($data)
{
if ($data->getPlainPassword()) {
$data->setPassword(
$this->userPasswordEncoder->encodePassword($data, $data->getPlainPassword())
);
}
$this->entityManager->persist($data);
$this->entityManager->flush();
}
public function remove($data)
{
$this->entityManager->remove($data);
$this->entityManager->flush();
}
}
When I try to update (put) a user or delete (delete) one, my Data Persister does it's job correctly.
However, when I try to create a new user, I get this error :
"password: this value should not be null."
Also, here's the content of my request
{"email":"new.user#domain.com","plainPassword":"abcdefg","password":"abcdefg","roles":["ROLE_USER"]}
What am I doing wrong?
Thank you !

DataPersister not adding up amount upon "PUT" Action

I am new to API platform. and currently, I am facing the problem with "PUT" action from API platform.
I have two entity. One is a user entity and another one is the credit entity. And their relationship is one-to-many relationship. And i have a DataPersister which i refer and follow by this documentation( https://api-platform.com/docs/core/data-persisters/). So upon, persist, I want to do some business logic. So right now the problem is when i update the credit. It should add current value + credit amount requested, Instead, it straightly adds the credit amount that is requested. For example, let say I have an amount of 100 dollars inside the credit table. When I try to add another 50 dollars, it should be 150, but instead, it stored as 50 dollars only.
Below is my User Entity
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* #ApiResource(
* collectionOperations={
* "get" ,
* "post",
* "app_login"={
* "route_name"="app_login",
* "method"="POST",
* "swagger_context" = {
* "parameters" = {
* {
* "name" = "User Login",
* "in" = "body",
* "type" = "object",
* "schema"= {
* "email" = {"type": "string"},
* "password" = {"type" : "string"},
* "example" ={
* "email" = "string",
* "password" ="string"
* }
* }
* }
* },
* "responses" = {
* "200" = {
* "description" = "You will get User IRI and PHPSESSID",
* "schema" = {
* "type" = "object",
* "required" = {
* "email",
* "password"
* },
* "properties" = {
* "user" = {
* "type" = "string"
* },
* "PHPSESSID" = {
* "type" = "string"
* },
*
* }
* }
* },
* "400" = {
* "description" = "Bad Requests"
* }
* },
* "summary" = "User Login",
* "description" = "Set User session to api platform by email and password",
* "consumes" = {
* "application/json",
* "text/html",
* },
* "produces" = {
* "application/json",
* "application/ld+json"
* }
* }
* }
* },
* itemOperations={
* "get" ={
* "normalization_context"={"groups"={"user:item:get"}}
* },
* "put" = {
* "swagger_context" ={
* "summary" = "Update username details and credit items"
* }
*
* }
* },
* normalizationContext={"groups"={"user:read"}},
* denormalizationContext={"groups"={"user:write"}},
* shortName="User"
*
* )
* #UniqueEntity(fields={"email"})
* #UniqueEntity(fields={"contact"})
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #Groups({"user:read", "user:write"})
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=180, unique=true)
* #Groups({"user:read", "user:write", "user:item:get", "credit:item:get"})
* #Assert\Email()
* #Assert\NotBlank()
*/
private $email;
/**
* #ORM\Column(type="json")
*/
private $roles = [];
/**
* #var string The hashed password
* #ORM\Column(type="string")
*/
private $password;
/**
* #Groups("user:write")
* #SerializedName("password")
* #Assert\NotBlank(groups={"create"})
*/
private $plainPassword;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"user:read", "user:write"})
* #Assert\NotBlank()
*/
private $firstName;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"user:read", "user:write"})
* #Assert\NotBlank()
*/
private $lastName;
/**
* #var string provide in YYYY-MM-DD (neglect Time)
* #ORM\Column(type="date")
* #Groups({"user:read", "user:write"})
* #Assert\NotBlank()
*/
private $dob;
/**
* #ORM\Column(type="text")
* #Groups({"user:read", "user:write"})
* #Assert\NotBlank()
*/
private $address;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"user:read", "user:write"})
* #Assert\NotBlank()
* #Assert\Length(
* min=8,
* max=8,
* maxMessage="contact number must have 8 character",
* minMessage="contact number must have 8 character"
* )
*/
private $contact;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Credit", mappedBy="user", cascade={"persist"}, orphanRemoval=true)
* #Groups({"user:read", "user:write"})
* #Assert\Valid()
*/
private $credits;
/**
* #var \DateTime $created
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(type="datetime")
*/
private $created_at;
/**
* #var \DateTime $updated
*
* #Gedmo\Timestampable(on="update")
* #ORM\Column(type="datetime")
*/
private $updated_at;
public function __construct()
{
$this->credits = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* #see UserInterface
*/
public function getUsername(): string
{
return (string) $this->email;
}
/**
* #see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* #see UserInterface
*/
public function getPassword(): string
{
return (string) $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* #see UserInterface
*/
public function getSalt()
{
// not needed when using the "bcrypt" algorithm in security.yaml
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(string $firstName): self
{
$this->firstName = $firstName;
return $this;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(string $lastName): self
{
$this->lastName = $lastName;
return $this;
}
public function getDob(): ?\DateTimeInterface
{
return $this->dob;
}
public function setDob(\DateTimeInterface $dob): self
{
$this->dob = $dob;
return $this;
}
public function getAddress(): ?string
{
return $this->address;
}
public function setAddress(string $address): self
{
$this->address = $address;
return $this;
}
public function getContact(): ?string
{
return $this->contact;
}
public function setContact(string $contact): self
{
$this->contact = $contact;
return $this;
}
/**
* #return Collection|Credit[]
*/
public function getCredits(): Collection
{
return $this->credits;
}
public function addCredit(Credit $credit): self
{
if (!$this->credits->contains($credit)) {
$this->credits[] = $credit;
$credit->setUser($this);
}
return $this;
}
public function removeCredit(Credit $credit): self
{
if ($this->credits->contains($credit)) {
$this->credits->removeElement($credit);
// set the owning side to null (unless already changed)
if ($credit->getUser() === $this) {
$credit->setUser(null);
}
}
return $this;
}
public function getPlainPassword(): ?string
{
return $this->plainPassword;
}
public function setPlainPassword(string $plainPassword): self
{
$this->plainPassword = $plainPassword;
return $this;
}
public function getCreated()
{
return $this->created_at;
}
public function getUpdated()
{
return $this->updated_at;
}
}
This is my credit entity
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ApiResource(
* collectionOperations={
* "get" ={
* "normalization_context"={"groups"={"credit:read", "credit:item:get"}},
* }
* },
* itemOperations={
* "get"
* },
* shortName="credits",
* normalizationContext={"groups"={"credit:read"}, "swagger_definition_name"="Read"},
* denormalizationContext={"groups"={"credit:write"}, "swagger_definition_name"="Write"},
* )
* #ORM\Entity(repositoryClass="App\Repository\CreditRepository")
*/
class Credit
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="credits")
* #ORM\JoinColumn(nullable=false)
* #Groups({"credit:read", "credit:write"})
* #Assert\Valid()
*/
private $user;
/**
* #ORM\Column(type="string", length=255)
* #Groups({ "user:read", "user:write", "credit:read", "credit:write"})
*/
private $amount;
/**
* #var \DateTime $created
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(type="datetime")
*/
private $created_at;
/**
* #var \DateTime $updated
*
* #Gedmo\Timestampable(on="update")
* #ORM\Column(type="datetime")
*/
private $updated_at;
public function getId(): ?int
{
return $this->id;
}
public function getAmount(): ?string
{
return $this->amount;
}
public function setAmount(string $amount): self
{
$this->amount = $amount;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function getCreated()
{
return $this->created_at;
}
public function getUpdated()
{
return $this->updated_at;
}
}
this is my UserDataPersister
<?php
namespace App\DataPersister;
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
use App\Entity\Credit;
use App\Entity\User;
use App\Managers\EmailManager;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class UserDataPersister implements DataPersisterInterface
{
private $entityManager;
private $userPasswordEncoder;
private $emailManager;
public function __construct(EntityManagerInterface $entityManager, UserPasswordEncoderInterface $userPasswordEncoder, EmailManager $emailManager )
{
$this->entityManager = $entityManager;
$this->userPasswordEncoder = $userPasswordEncoder;
$this->emailManager = $emailManager;
}
public function supports($data): bool
{
return $data instanceof User;
}
/**
* #param User $data
*/
public function persist($data)
{
//encrypt password
if ($data->getPlainPassword()) {
$data->setPassword(
$this->userPasswordEncoder->encodePassword($data, $data->getPlainPassword())
);
$data->eraseCredentials();
}
$creditArray = $data->getCredits();
$creditAmt = 0;
foreach ( $creditArray as $credit ) {
$creditAmt = $credit->getAmount();
}
//credit top up detection
if($creditAmt !==0){
$creditRepo = $this->entityManager->getRepository(Credit::class);
$currentCredit = $creditRepo->findAmountByUserId($data->getId());
$currentCreditAmt = $currentCredit->getAmount();
$topupAmt = $currentCreditAmt + $creditAmt;
$currentCredit -> setAmount($topupAmt);
//update entity
$this->entityManager->persist($currentCredit);
//send email
//$this->emailManager->sendCreditTopupNotification($data);
}else{
//set credit to zero
$creditEntity = new Credit();
$creditEntity ->setAmount(0);
$data->addCredit($creditEntity);
//send registration email
//$this->emailManager->sendRegisterNotification($data);
}
$this->entityManager->persist($data);
$this->entityManager->flush();
}
public function remove($data)
{
$this->entityManager->remove($data);
$this->entityManager->flush();
}
}
I believe the problem come from this session of UserDataPersister
//credit top up detection
if($creditAmt !==0){
$creditRepo = $this->entityManager->getRepository(Credit::class);
$currentCredit = $creditRepo->findAmountByUserId($data->getId());
$currentCreditAmt = $currentCredit->getAmount();
$topupAmt = $currentCreditAmt + $creditAmt;
$currentCredit -> setAmount($topupAmt);
//update entity
$this->entityManager->persist($currentCredit);
//send email
//$this->emailManager->sendCreditTopupNotification($data);
}else{
//set credit to zero
$creditEntity = new Credit();
$creditEntity ->setAmount(0);
$data->addCredit($creditEntity);
//send registration email
//$this->emailManager->sendRegisterNotification($data);
}
$this->entityManager->persist($data);
$this->entityManager->flush();
How can I achieve when API is called "PUT" action with amount include for credits,( which is already implemented ) and add the current amount + amount that is requested from API? Thanks in advance.
I'm pretty sure you're trying to sum all the credits in the array but instead you're just using the last element's value for $creditAmt here:
$creditAmt = 0;
foreach ( $creditArray as $credit ) {
$creditAmt = $credit->getAmount();
}
This should probably be:
$creditAmt = 0;
foreach ( $creditArray as $credit ) {
$creditAmt = $creditAmt + $credit->getAmount();
}
Further if your $creditArray is empty you will have $creditAmt = 0; which explains why you're not seeing any credit added. Ensure $data->getCredits() really holds the "credits" you're trying to sum up!

The Doctrine repository "Doctrine\ORM\EntityRepository" must implement UserProviderInterface in symfony2

I am getting above error when login. With property option in security.yml it is working. I have added the #ORM\Entity(repositoryClass="versionR\userBundle\Entity\UserRepository") line on my entity class, dobule checked path, cleared cache but no luck.
User entity class
<?php
namespace versionR\userBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
//use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="versionR\userBundle\Entity\UserRepository")
*/
class User implements UserInterface, \Serializable
{
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=40, nullable=false)
*/
private $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255, nullable=false)
*/
private $password;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255, nullable=false)
*/
private $email;
/**
* #var string
*
* #ORM\Column(name="address", type="string", length=255, nullable=false)
*/
private $address;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="versionR\userBundle\Entity\Role", inversedBy="user")
* #ORM\JoinTable(name="user_role",
* joinColumns={
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="role_id", referencedColumnName="id")
* }
* )
*/
private $role;
/**
* Constructor
*/
public function __construct()
{
$this->role = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #param string $address
*/
public function setAddress($address)
{
$this->address = $address;
}
/**
* #return string
*/
public function getAddress()
{
return $this->address;
}
/**
* #param string $email
*/
public function setEmail($email)
{
$this->email = $email;
}
/**
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* #param int $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param string $password
*/
public function setPassword($password)
{
$this->password = $password;
}
/**
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* #param string $username
*/
public function setUsername($username)
{
$this->username = $username;
}
/**
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* #param \Doctrine\Common\Collections\Collection $role
*/
public function setRole($role)
{
$this->role->add($role);
}
/**
* #return \Doctrine\Common\Collections\Collection
*/
public function getRole()
{
return $this->role;
}
/**
*/
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password,
// see section on salt below
// $this->salt,
));
}
/**
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
// see section on salt below
// $this->salt
) = unserialize($serialized);
}
/**
* Returns the roles granted to the user.
*/
public function getRoles()
{
return $this->role->toArray();
}
/**
*/
public function getSalt()
{
return null;
}
/**
*/
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
}
User repository class
<?php
namespace versionR\userBundle\Entity;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
/**
* UserRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class UserRepository extends EntityRepository implements UserProviderInterface
{
/**
* #param string $username
* #return \versionR\userBundle\Entity\User
*/
public function loadUserByUsername($username)
{
return $this->findOneBy(array('username' => $username));
}
public function refreshUser(UserInterface $user)
{
$class = get_class($user);
if (!$this->supportsClass($class)) {
throw new UnsupportedUserException(
sprintf(
'Instances of "%s" are not supported.',
$class
)
);
}
return $this->find($user->getId());
}
public function supportsClass($class)
{
return $this->getEntityName() === $class
|| is_subclass_of($class, $this->getEntityName());
}
}
Both classes are in Entity directory. Any suggestions to solve this problem. I am using symfony 2.5.2

Categories