Related
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.
I have a problem on Symfony5 - apiPlatform, when I request a subresource I have an answer in Json but with an error.
Symfony \ Component \ VarDumper \ Cloner \ Data objects are immutable
my code:
entity\Customer
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM; use
App\Repository\CustomerRepository; use
ApiPlatform\Core\Annotation\ApiFilter; use
Doctrine\Common\Collections\Collection; use
ApiPlatform\Core\Annotation\ApiResource; use
ApiPlatform\Core\Annotation\ApiSubresource; use
Doctrine\Common\Collections\ArrayCollection; use
Symfony\Component\Serializer\Annotation\Groups;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter; use
ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
/** * #ORM\Entity(repositoryClass=CustomerRepository::class) *
#ApiResource( * normalizationContext={ *
"groups"={"customers_read"} * }, * collectionOperations={"GET",
"POST"}, * itemOperations={"GET","PUT","DELETE","PATCH"}, *
subresourceOperations={ *
"invoices_get_subresource"={"path"="/customers/{id}/invoices"} * }
* ) * #ApiFilter(SearchFilter::class, properties={"firstName":"partial","lastName","company"}) *
#ApiFilter(OrderFilter::class) */ class Customer {
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #Groups({"customers_read","invoices_read"})
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"customers_read","invoices_read"})
*/
private $firstName;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"customers_read","invoices_read"})
*/
private $lastName;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"customers_read","invoices_read"})
*/
private $email;
/**
* #ORM\Column(type="string", length=255, nullable=true)
* #Groups({"customers_read","invoices_read"})
*/
private $company;
/**
* #ORM\OneToMany(targetEntity=Invoice::class, mappedBy="customer")
* #Groups({"customers_read"})
* #ApiSubresource
*/
private $invoices;
/**
* #ORM\ManyToOne(targetEntity=User::class, inversedBy="customers")
* #ORM\JoinColumn(nullable=false)
* #Groups({"customers_read"})
*/
private $user;
public function __construct()
{
$this->invoices = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
/**
* #Groups({"customers_read"})
*
* #return float|null
*/
public function getTotalAmount(): ?float
{
return array_reduce($this->invoices->toArray(), function($total,$invoice){
return $total + $invoice->getAmount();
}, 0);
}
/**
* #Groups({"customers_read"})
*
* #return float|null
*/
public function getUnpaidAmount(): ?float
{
return array_reduce($this->invoices->toArray(), function($total,$invoice){
return $total + ($invoice->getStatus() === "PAID" || $invoice->getStatus() === "CANCELLED" ? 0 : $invoice->getAmount());
} , 0);
}
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 getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getCompany(): ?string
{
return $this->company;
}
public function setCompany(?string $company): self
{
$this->company = $company;
return $this;
}
/**
* #return Collection|Invoice[]
*/
public function getInvoices(): Collection
{
return $this->invoices;
}
public function addInvoice(Invoice $invoice): self
{
if (!$this->invoices->contains($invoice)) {
$this->invoices[] = $invoice;
$invoice->setCustomer($this);
}
return $this;
}
public function removeInvoice(Invoice $invoice): self
{
if ($this->invoices->removeElement($invoice)) {
// set the owning side to null (unless already changed)
if ($invoice->getCustomer() === $this) {
$invoice->setCustomer(null);
}
}
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
} }
entity\invoice
<?php
namespace App\Entity;
use App\Entity\User; use Doctrine\ORM\Mapping as ORM; use
App\Repository\InvoiceRepository; use
ApiPlatform\Core\Annotation\ApiFilter; use
ApiPlatform\Core\Annotation\ApiResource; use
Symfony\Component\Serializer\Annotation\Groups; use
ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
/** * #ORM\Entity(repositoryClass=InvoiceRepository::class) *
#ApiResource( * subresourceOperations={ *
"api_customers_invoices_get_subresource"={ *
"normalization_context"={"groups"={"invoices_subresource"}} * }
* }, * itemOperations={"GET","PUT","DELETE","increment"={ * "method"="post", * "path"="/invoices/{id}/increment", *
"controller"="App\Controller\InvoiceIncrementationController", *
"openapi_context"={ * "summary"="Incrémente une
facture", * "description"="Incrémente le chrono d'une
facture donnée" * } * }}, * attributes={ *
"pagination_enabled"=true, * "pagination_items_per_page"=20, *
"order": {"sentAt":"desc"} * }, *
normalizationContext={"groups"={"invoices_read"}} * ) *
#ApiFilter(OrderFilter::class, properties={"amount","sentAt"}) */
class Invoice {
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #Groups({"invoices_read","customers_read","invoices_subresource"})
*/
private $id;
/**
* #ORM\Column(type="float")
* #Groups({"invoices_read","customers_read","invoices_subresource"})
*/
private $amount;
/**
* #ORM\Column(type="datetime")
* #Groups({"invoices_read","customers_read","invoices_subresource"})
*/
private $sentAt;
/**
* #ORM\Column(type="string", length=255)
* #Groups({"invoices_read","customers_read","invoices_subresource"})
*/
private $status;
/**
* #ORM\ManyToOne(targetEntity=Customer::class, inversedBy="invoices")
* #ORM\JoinColumn(nullable=false)
* #Groups({"invoices_read"})
*/
private $customer;
/**
* #ORM\Column(type="integer")
* #Groups({"invoices_read"})
* #Groups({"invoices_read","customers_read","invoices_subresource"})
*/
private $chrono;
public function getId(): ?int
{
return $this->id;
}
/**
* Permet de récupérer le User à qui appartient finalement la facture
* #Groups({"invoices_read","invoices_subresource"})
*
* #return User
*/
public function getUser(): ?User
{
return $this->customer->getUser();
}
public function getAmount(): ?float
{
return $this->amount;
}
public function setAmount(float $amount): self
{
$this->amount = $amount;
return $this;
}
public function getSentAt(): ?\DateTimeInterface
{
return $this->sentAt;
}
public function setSentAt(\DateTimeInterface $sentAt): self
{
$this->sentAt = $sentAt;
return $this;
}
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(string $status): self
{
$this->status = $status;
return $this;
}
public function getCustomer(): ?Customer
{
return $this->customer;
}
public function setCustomer(?Customer $customer): self
{
$this->customer = $customer;
return $this;
}
public function getChrono(): ?int
{
return $this->chrono;
}
public function setChrono(int $chrono): self
{
$this->chrono = $chrono;
return $this;
} }
Thank you for your help
The line $groupement[] = null === $secteurs ? null : $secteurs->getSecteurid();
in the Eleveurtype.php is not working Please i need Some help
The work i wanted to do is to select one Secteur and then i want to get all groupements belong to the Secteur
This is The EleveurType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('secteurid',EntityType::class, [
'label'=>'Nom du secteur :',
'class' => Secteurs::class,
'choice_label' => 'secteurfr',
'attr'=>[
'class'=>'form-control',
]
])
;
$formModifier = function (FormInterface $form, Secteurs $secteurs = null) {
//$secteurs = null === $secteurs ? [] : $secteurs->getSecteurid();
$groupement[] = null === $secteurs ? null : $secteurs->getSecteurid();
$form->add('groupementid', EntityType::class, [
'class' => Groupements::class,
'placeholder' => '',
'choices' => $groupement,
'attr'=>[
'class'=>'form-control',
]
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. SportMeetup
$data = $event->getData();
$formModifier($event->getForm(), $data->getSecteurid());
}
);
$builder->get('secteurid')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$secteur = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $secteur);
}
);
}
This is The _form.html.twig Eleveur
{{ form_start(form, {'attr': {'id': 'newform', 'nam': nam } }) }}
{{ form_widget(form) }}
<button type="button" class="{{ classBtnAddEdit|default('btn btnAED btn-success waves-effect waves-light m-1') }} " id="btnAddEdit"><i class="fa fa-check-square-o"></i> Enregistrer</button>
{{ form_end(form) }}
<script>
var $secteur = $('#eleveurs_secteurid');
// When sport gets selected ...
$secteur.change(function() {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
// Simulate form data, but only include the selected sport value.
var data = {};
data[$secteur.attr('name')] = $secteur.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url : $form.attr('nam'), //= $form.attr('action'),
type: $form.attr('method'),
data : data,
success: function(html) {
// Replace current position field ...
$('#eleveurs_groupementid').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('#eleveurs_groupementid')
);
// Position field now displays the appropriate positions.
}
});
});
</script>
** this is the Eleveur Class Eleveur **
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* Eleveurs
*
* #ORM\Table(name="eleveurs", indexes={#ORM\Index(name="fk_relationship_47", columns={"groupementid"}), #ORM\Index(name="fk_relationship_53", columns={"douarid"}), #ORM\Index(name="fk_relationship_16", columns={"secteurid"}), #ORM\Index(name="fk_relationship_49", columns={"villeid"})})
* #ORM\Entity
*/
class Eleveurs
{
/**
* #var int
*
* #ORM\Column(name="eleveurid", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $eleveurid;
/**
* #var string|null
*
* #ORM\Column(name="codeeleveur", type="text", length=65535, nullable=true)
*/
private $codeeleveur;
/**
* #var string|null
*
* #ORM\Column(name="numcin", type="text", length=65535, nullable=true)
*/
private $numcin;
/**
* #var \DateTime|null
*
* #ORM\Column(name="datecin", type="date", nullable=true)
*/
private $datecin;
/**
* #var \DateTime|null
*
* #ORM\Column(name="validitecin", type="date", nullable=true)
*/
private $validitecin;
/**
* #var string|null
*
* #ORM\Column(name="nomfr", type="text", length=65535, nullable=true)
*/
private $nomfr;
/**
* #var string|null
*
* #ORM\Column(name="prenomfr", type="text", length=65535, nullable=true)
*/
private $prenomfr;
/**
* #var string|null
*
* #ORM\Column(name="nomar", type="text", length=65535, nullable=true)
*/
private $nomar;
/**
* #var string|null
*
* #ORM\Column(name="prenomar", type="text", length=65535, nullable=true)
*/
private $prenomar;
/**
* #var \DateTime|null
*
* #ORM\Column(name="dateadhesion", type="date", nullable=true)
*/
private $dateadhesion;
/**
* #var string|null
*
* #ORM\Column(name="adressefr", type="text", length=65535, nullable=true)
*/
private $adressefr;
/**
* #var string|null
*
* #ORM\Column(name="adressear", type="text", length=65535, nullable=true)
*/
private $adressear;
/**
* #var int|null
*
* #ORM\Column(name="effectifovin", type="integer", nullable=true)
*/
private $effectifovin;
/**
* #var int|null
*
* #ORM\Column(name="effectifcaprin", type="integer", nullable=true)
*/
private $effectifcaprin;
/**
* #var \Secteurs
*
* #ORM\ManyToOne(targetEntity="Secteurs")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="secteurid", referencedColumnName="secteurid")
* })
*/
private $secteurid;
/**
* #var \Groupements
*
* #ORM\ManyToOne(targetEntity="Groupements")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="groupementid", referencedColumnName="groupementid")
* })
*/
private $groupementid;
/**
* #var \Villes
*
* #ORM\ManyToOne(targetEntity="Villes")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="villeid", referencedColumnName="villeid")
* })
*/
private $villeid;
/**
* #var \Douars
*
* #ORM\ManyToOne(targetEntity="Douars")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="douarid", referencedColumnName="douarid")
* })
*/
private $douarid;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Conseilgroupement", mappedBy="eleveurid")
*/
private $conseilgroupementid;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Droitfonctionement", inversedBy="eleveurid")
* #ORM\JoinTable(name="relationship_32",
* joinColumns={
* #ORM\JoinColumn(name="eleveurid", referencedColumnName="eleveurid")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="droitfonctionementid", referencedColumnName="droitfonctionementid")
* }
* )
*/
private $droitfonctionementid;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Conseilanoc", mappedBy="eleveurid")
*/
private $conseilanocid;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Superviseurs", mappedBy="eleveurid")
*/
private $histosuperviseurid;
/**
* Constructor
*/
public function __construct()
{
$this->conseilgroupementid = new \Doctrine\Common\Collections\ArrayCollection();
$this->droitfonctionementid = new \Doctrine\Common\Collections\ArrayCollection();
$this->conseilanocid = new \Doctrine\Common\Collections\ArrayCollection();
$this->histosuperviseurid = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getEleveurid(): ?int
{
return $this->eleveurid;
}
public function getCodeeleveur(): ?string
{
return $this->codeeleveur;
}
public function setCodeeleveur(?string $codeeleveur): self
{
$this->codeeleveur = $codeeleveur;
return $this;
}
public function getNumcin(): ?string
{
return $this->numcin;
}
public function setNumcin(?string $numcin): self
{
$this->numcin = $numcin;
return $this;
}
public function getDatecin(): ?\DateTimeInterface
{
return $this->datecin;
}
public function setDatecin(?\DateTimeInterface $datecin): self
{
$this->datecin = $datecin;
return $this;
}
public function getValiditecin(): ?\DateTimeInterface
{
return $this->validitecin;
}
public function setValiditecin(?\DateTimeInterface $validitecin): self
{
$this->validitecin = $validitecin;
return $this;
}
public function getNomfr(): ?string
{
return $this->nomfr;
}
public function setNomfr(?string $nomfr): self
{
$this->nomfr = $nomfr;
return $this;
}
public function getPrenomfr(): ?string
{
return $this->prenomfr;
}
public function setPrenomfr(?string $prenomfr): self
{
$this->prenomfr = $prenomfr;
return $this;
}
public function getNomar(): ?string
{
return $this->nomar;
}
public function setNomar(?string $nomar): self
{
$this->nomar = $nomar;
return $this;
}
public function getPrenomar(): ?string
{
return $this->prenomar;
}
public function setPrenomar(?string $prenomar): self
{
$this->prenomar = $prenomar;
return $this;
}
public function getDateadhesion(): ?\DateTimeInterface
{
return $this->dateadhesion;
}
public function setDateadhesion(?\DateTimeInterface $dateadhesion): self
{
$this->dateadhesion = $dateadhesion;
return $this;
}
public function getAdressefr(): ?string
{
return $this->adressefr;
}
public function setAdressefr(?string $adressefr): self
{
$this->adressefr = $adressefr;
return $this;
}
public function getAdressear(): ?string
{
return $this->adressear;
}
public function setAdressear(?string $adressear): self
{
$this->adressear = $adressear;
return $this;
}
public function getEffectifovin(): ?int
{
return $this->effectifovin;
}
public function setEffectifovin(?int $effectifovin): self
{
$this->effectifovin = $effectifovin;
return $this;
}
public function getEffectifcaprin(): ?int
{
return $this->effectifcaprin;
}
public function setEffectifcaprin(?int $effectifcaprin): self
{
$this->effectifcaprin = $effectifcaprin;
return $this;
}
public function getSecteurid(): ?Secteurs
{
return $this->secteurid;
}
public function setSecteurid(?Secteurs $secteurid): self
{
$this->secteurid = $secteurid;
return $this;
}
public function getGroupementid(): ?Groupements
{
return $this->groupementid;
}
public function setGroupementid(?Groupements $groupementid): self
{
$this->groupementid = $groupementid;
return $this;
}
public function getVilleid(): ?Villes
{
return $this->villeid;
}
public function setVilleid(?Villes $villeid): self
{
$this->villeid = $villeid;
return $this;
}
public function getDouarid(): ?Douars
{
return $this->douarid;
}
public function setDouarid(?Douars $douarid): self
{
$this->douarid = $douarid;
return $this;
}
/**
* #return Collection|Conseilgroupement[]
*/
public function getConseilgroupementid(): Collection
{
return $this->conseilgroupementid;
}
public function addConseilgroupementid(Conseilgroupement $conseilgroupementid): self
{
if (!$this->conseilgroupementid->contains($conseilgroupementid)) {
$this->conseilgroupementid[] = $conseilgroupementid;
$conseilgroupementid->addEleveurid($this);
}
return $this;
}
public function removeConseilgroupementid(Conseilgroupement $conseilgroupementid): self
{
if ($this->conseilgroupementid->contains($conseilgroupementid)) {
$this->conseilgroupementid->removeElement($conseilgroupementid);
$conseilgroupementid->removeEleveurid($this);
<
** This is the Secteur class **
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Secteurs
*
* #ORM\Table(name="secteurs")
* #ORM\Entity
*/
class Secteurs
{
/**
* #var int
*
* #ORM\Column(name="secteurid", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $secteurid;
/**
* #var string|null
*
* #ORM\Column(name="secteurfr", type="text", length=65535, nullable=true)
*/
private $secteurfr;
/**
* #var string|null
*
* #ORM\Column(name="secteurar", type="text", length=65535, nullable=true)
*/
private $secteurar;
/**
* #var string|null
*
* #ORM\Column(name="codesecteur", type="text", length=65535, nullable=true)
*/
private $codesecteur;
public function getSecteurid(): ?int
{
return $this->secteurid;
}
public function getSecteurfr(): ?string
{
return $this->secteurfr;
}
public function setSecteurfr(?string $secteurfr): self
{
$this->secteurfr = ucfirst($secteurfr);
return $this;
}
public function getSecteurar(): ?string
{
return $this->secteurar;
}
public function setSecteurar(?string $secteurar): self
{
$this->secteurar = $secteurar;
return $this;
}
public function getCodesecteur(): ?string
{
return $this->codesecteur;
}
public function setCodesecteur(?string $codesecteur): self
{
$this->codesecteur = strtoupper($codesecteur);
return $this;
}
}
** this is the groupement class **
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* Groupements
*
* #ORM\Table(name="groupements", indexes={#ORM\Index(name="fk_relationship_54", columns={"secteurid"})})
* #ORM\Entity
*/
class Groupements
{
/**
* #var int
*
* #ORM\Column(name="groupementid", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $groupementid;
/**
* #var string|null
*
* #ORM\Column(name="groupementmereid", type="decimal", precision=8, scale=0, nullable=true)
*/
private $groupementmereid;
/**
* #var string|null
*
* #ORM\Column(name="codegroupement", type="text", length=65535, nullable=true)
*/
private $codegroupement;
/**
* #var string|null
*
* #ORM\Column(name="nomgroupementfr", type="text", length=65535, nullable=true)
*/
private $nomgroupementfr;
/**
* #var string|null
*
* #ORM\Column(name="nomgroupementar", type="text", length=65535, nullable=true)
*/
private $nomgroupementar;
/**
* #var string|null
*
* #ORM\Column(name="adressepostale", type="text", length=65535, nullable=true)
*/
private $adressepostale;
/**
* #var \DateTime|null
*
* #ORM\Column(name="datecreation", type="date", nullable=true)
*/
private $datecreation;
/**
* #var string|null
*
* #ORM\Column(name="pvcreation", type="text", length=65535, nullable=true)
*/
private $pvcreation;
/**
* #var float|null
*
* #ORM\Column(name="droitfonctionement", type="float", precision=10, scale=0, nullable=true)
*/
private $droitfonctionement;
/**
* #var float|null
*
* #ORM\Column(name="autrecotisations", type="float", precision=10, scale=0, nullable=true)
*/
private $autrecotisations;
/**
* #var string|null
*
* #ORM\Column(name="effectifovinencadre", type="decimal", precision=8, scale=0, nullable=true)
*/
private $effectifovinencadre;
/**
* #var string|null
*
* #ORM\Column(name="effectifcaprinencadre", type="decimal", precision=8, scale=0, nullable=true)
*/
private $effectifcaprinencadre;
/**
* #var string|null
*
* #ORM\Column(name="lieupvcreation", type="text", length=65535, nullable=true)
*/
private $lieupvcreation;
/**
* #var \DateTime|null
*
* #ORM\Column(name="datepvcreation", type="date", nullable=true)
*/
private $datepvcreation;
/**
* #var \Secteurs
*
* #ORM\ManyToOne(targetEntity="Secteurs")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="secteurid", referencedColumnName="secteurid")
* })
*/
private $secteurid;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Droitfonctionement", inversedBy="groupementid")
* #ORM\JoinTable(name="relationship_31",
* joinColumns={
* #ORM\JoinColumn(name="groupementid", referencedColumnName="groupementid")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="droitfonctionementid", referencedColumnName="droitfonctionementid")
* }
* )
*/
private $droitfonctionementid;
/**
* Constructor
*/
public function __construct()
{
$this->droitfonctionementid = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getGroupementid(): ?int
{
return $this->groupementid;
}
public function getGroupementmereid(): ?string
{
return $this->groupementmereid;
}
public function setGroupementmereid(?string $groupementmereid): self
{
$this->groupementmereid = $groupementmereid;
return $this;
}
public function getCodegroupement(): ?string
{
return $this->codegroupement;
}
public function setCodegroupement(?string $codegroupement): self
{
$this->codegroupement = $codegroupement;
return $this;
}
public function getNomgroupementfr(): ?string
{
return $this->nomgroupementfr;
}
public function setNomgroupementfr(?string $nomgroupementfr): self
{
$this->nomgroupementfr = $nomgroupementfr;
return $this;
}
public function getNomgroupementar(): ?string
{
return $this->nomgroupementar;
}
public function setNomgroupementar(?string $nomgroupementar): self
{
$this->nomgroupementar = $nomgroupementar;
return $this;
}
public function getAdressepostale(): ?string
{
return $this->adressepostale;
}
public function setAdressepostale(?string $adressepostale): self
{
$this->adressepostale = $adressepostale;
return $this;
}
public function getDatecreation(): ?\DateTimeInterface
{
return $this->datecreation;
}
public function setDatecreation(?\DateTimeInterface $datecreation): self
{
$this->datecreation = $datecreation;
return $this;
}
public function getPvcreation(): ?string
{
return $this->pvcreation;
}
public function setPvcreation(?string $pvcreation): self
{
$this->pvcreation = $pvcreation;
return $this;
}
public function getDroitfonctionement(): ?float
{
return $this->droitfonctionement;
}
public function setDroitfonctionement(?float $droitfonctionement): self
{
$this->droitfonctionement = $droitfonctionement;
return $this;
}
public function getAutrecotisations(): ?float
{
return $this->autrecotisations;
}
public function setAutrecotisations(?float $autrecotisations): self
{
$this->autrecotisations = $autrecotisations;
return $this;
}
public function getEffectifovinencadre(): ?string
{
return $this->effectifovinencadre;
}
public function setEffectifovinencadre(?string $effectifovinencadre): self
{
$this->effectifovinencadre = $effectifovinencadre;
return $this;
}
public function getEffectifcaprinencadre(): ?string
{
return $this->effectifcaprinencadre;
}
public function setEffectifcaprinencadre(?string $effectifcaprinencadre): self
{
$this->effectifcaprinencadre = $effectifcaprinencadre;
return $this;
}
public function getLieupvcreation(): ?string
{
return $this->lieupvcreation;
}
public function setLieupvcreation(?string $lieupvcreation): self
{
$this->lieupvcreation = $lieupvcreation;
return $this;
}
public function getDatepvcreation(): ?\DateTimeInterface
{
return $this->datepvcreation;
}
public function setDatepvcreation(?\DateTimeInterface $datepvcreation): self
{
$this->datepvcreation = $datepvcreation;
return $this;
}
public function getSecteurid(): ?Secteurs
{
return $this->secteurid;
}
public function setSecteurid(?Secteurs $secteurid): self
{
$this->secteurid = $secteurid;
return $this;
}
/**
* #return Collection|Droitfonctionement[]
*/
public function getDroitfonctionementid(): Collection
{
return $this->droitfonctionementid;
}
public function addDroitfonctionementid(Droitfonctionement $droitfonctionementid): self
{
if (!$this->droitfonctionementid->contains($droitfonctionementid)) {
$this->droitfonctionementid[] = $droitfonctionementid;
}
return $this;
}
public function removeDroitfonctionementid(Droitfonctionement $droitfonctionementid): self
{
if ($this->droitfonctionementid->contains($droitfonctionementid)) {
$this->droitfonctionementid->removeElement($droitfonctionementid);
}
return $this;
}
}
i'm trying return my entity but i get this error when I make a request and i don't know what i'm doing wrong with this relations
(1/2) OutOfBoundsException
Missing value for primary key id on \ApiBundle\Entity\Type
My Session entity:
<?php
namespace Primepass\ApiBundle\Entity;
use Ramsey\Uuid\UuidInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* Session
*
* #ORM\Table(name="session", uniqueConstraints={#ORM\UniqueConstraint(name="session_id_uindex", columns={"id"})})
* #ORM\Entity(repositoryClass="Primepass\ApiBundle\Repository\SessionRepository")
*/
class Session
{
/**
* #var UuidInterface
*
* #ORM\Id
* #ORM\Column(type="uuid", unique=true)
* #ORM\GeneratedValue(strategy="CUSTOM")
* #ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
*/
private $id;
/**
* #var Theater
*
* #ORM\OneToOne(targetEntity="Theater")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="theater_id", referencedColumnName="id")
* })
*/
private $theater;
/**
* #var Movie
*
* #ORM\OneToOne(targetEntity="Movie")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="movie_id", referencedColumnName="id")
* })
*/
private $movie;
/**
* #var Type
*
* #ORM\OneToOne(targetEntity="Type")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="audio_type", referencedColumnName="type_name")
* })
*/
private $audioType;
/**
* #var Type
*
* #ORM\OneToOne(targetEntity="Type")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="screen_type", referencedColumnName="type_name")
* })
*/
private $screenType;
/**
* #var Type
*
* #ORM\OneToOne(targetEntity="Type")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="room_type", referencedColumnName="type_name")
* })
*/
private $roomType;
/**
* #var string
*
* #ORM\Column(name="room_name",type="string")
*/
private $roomName;
/**
* #var int
*
* #ORM\Column(name="price", type="integer", nullable=false)
*/
private $price;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime", nullable=false)
*/
private $date;
/**
* #var \Time
*
* #ORM\Column(name="hour", type="time", nullable=false)
*/
private $hour;
/**
* #var bool
*
* #ORM\Column(name="is_active", type="boolean", nullable=false)
*/
private $isActive;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime", nullable=false, options={"default"="2001-01-01 00:00:00"})
*/
private $createdAt = '2001-01-01 00:00:00';
/**
* #var \DateTime
*
* #ORM\Column(name="updated_at", type="datetime", nullable=false, options={"default"="2001-01-01 00:00:00"})
*/
private $updatedAt = '2001-01-01 00:00:00';
public function getId(): UuidInterface
{
return $this->id;
}
public function getTheater(): ?Theater
{
return $this->theater;
}
public function setTheater(?Theater $theater): self
{
$this->theater = $theater;
return $this;
}
public function getMovie(): ?Movie
{
return $this->movie;
}
public function setMovie(?Movie $movie): self
{
$this->movie = $movie;
return $this;
}
public function getAudioType(): ?Type
{
return $this->audioType;
}
public function setAudioType(?Type $audioType): self
{
$this->audioType = $audioType;
return $this;
}
public function getScreenType(): ?Type
{
return $this->screenType;
}
public function setScreenType(?Type $screenType): self
{
$this->screenType = $screenType;
return $this;
}
public function getRoomType(): ?Type
{
return $this->roomType;
}
public function setRoomType(?Type $roomType): self
{
$this->roomType = $roomType;
return $this;
}
public function getRoomName(): ?string
{
return $this->roomName;
}
public function setRoomName($roomName): self
{
$this->roomName = $roomName;
return $this;
}
public function getPrice(): ?int
{
return $this->price;
}
public function setPrice(?int $price): self
{
$this->price = $price;
return $this;
}
public function getDate(): ?\DateTimeInterface
{
return $this->date;
}
public function setDate(\DateTimeInterface $date): self
{
$this->date = $date;
return $this;
}
public function getHour(): ?\Time
{
return $this->hour;
}
public function setHour(\Time $hour): self
{
$this->hour = $hour;
return $this;
}
public function getIsActive(): bool
{
return $this->isActive;
}
public function setIsActive(bool $isActive): self
{
$this->isActive = $isActive;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
}
Type Entity:
<?php
namespace Primepass\ApiBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Ramsey\Uuid\UuidInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* Type
*
* #ORM\Table(name="type")
* #ORM\Entity(repositoryClass="Primepass\ApiBundle\Repository\TypeRepository")
*/
class Type
{
/**
* #var UuidInterface
*
* #ORM\Id
* #ORM\Column(type="uuid", unique=true)
* #ORM\GeneratedValue(strategy="CUSTOM")
* #ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="type_name", type="string", length=100, nullable=false)
*/
private $typeName;
/**
* #var string
*
* #ORM\Column(name="type_info", type="string", length=100, nullable=false)
*/
private $typeInfo;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime", nullable=false, options={"default"="2001-01-01 00:00:00"})
*/
private $createdAt = '2001-01-01 00:00:00';
/**
* #var \DateTime
*
* #ORM\Column(name="updated_at", type="datetime", nullable=false, options={"default"="2001-01-01 00:00:00"})
*/
private $updatedAt = '2001-01-01 00:00:00';
/**
* #ORM\ManyToMany(targetEntity="TicketRules", mappedBy="types")
* #ORM\JoinTable(name="ticket_rules_type")
*/
private $ticketRuleScreens;
public function __construct()
{
$this->ticketRuleScreens = new ArrayCollection();
}
public function getId(): UuidInterface
{
return $this->id;
}
public function getTypeName(): string
{
return $this->typeName;
}
public function setTypeName(string $typeName): self
{
$this->typeName = $typeName;
return $this;
}
public function getTypeInfo(): string
{
return $this->typeInfo;
}
public function setTypeInfo(string $typeInfo): self
{
$this->typeInfo = $typeInfo;
return $this;
}
public function getCreatedAt(): \DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): \DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getTicketRuleScreens()
{
return $this->ticketRuleScreens;
}
public function setTicketRuleScreens($ticketRuleScreens): self
{
$this->ticketRuleScreens = $ticketRuleScreens;
return $this;
}
}
I expected a json return with a paginator but has something wrong with Session model
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!