我是API平台的新手。 目前,我正面临来自API平台的"PUT"操作的问题。
我有两个实体。一个是用户实体,另一个是信用实体。他们的关系是一对多的关系。我有一个数据持久性器,我参考并遵循此文档(https://api-platform.com/docs/core/data-persisters/)。所以,坚持,我想做一些业务逻辑。所以现在的问题是当我更新信用时。它应该添加当前值 + 请求的信用额度,相反,它会直接添加请求的信用金额。例如,假设我在信用表中有 100 美元的金额。当我尝试再加 50 美元时,它应该是 150,但相反,它只存储为 50 美元。
下面是我的用户实体
<?php
namespace AppEntity;
use ApiPlatformCoreAnnotationApiResource;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineCommonCollectionsCollection;
use DoctrineORMMapping as ORM;
use SymfonyBridgeDoctrineValidatorConstraintsUniqueEntity;
use SymfonyComponentSecurityCoreUserUserInterface;
use SymfonyComponentSerializerAnnotationGroups;
use SymfonyComponentValidatorConstraints as Assert;
use SymfonyComponentSerializerAnnotationSerializedName;
use GedmoMappingAnnotation 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"})
* @ORMEntity(repositoryClass="AppRepositoryUserRepository")
*/
class User implements UserInterface
{
/**
* @ORMId()
* @ORMGeneratedValue()
* @Groups({"user:read", "user:write"})
* @ORMColumn(type="integer")
*/
private $id;
/**
* @ORMColumn(type="string", length=180, unique=true)
* @Groups({"user:read", "user:write", "user:item:get", "credit:item:get"})
* @AssertEmail()
* @AssertNotBlank()
*/
private $email;
/**
* @ORMColumn(type="json")
*/
private $roles = [];
/**
* @var string The hashed password
* @ORMColumn(type="string")
*/
private $password;
/**
* @Groups("user:write")
* @SerializedName("password")
* @AssertNotBlank(groups={"create"})
*/
private $plainPassword;
/**
* @ORMColumn(type="string", length=255)
* @Groups({"user:read", "user:write"})
* @AssertNotBlank()
*/
private $firstName;
/**
* @ORMColumn(type="string", length=255)
* @Groups({"user:read", "user:write"})
* @AssertNotBlank()
*/
private $lastName;
/**
* @var string provide in YYYY-MM-DD (neglect Time)
* @ORMColumn(type="date")
* @Groups({"user:read", "user:write"})
* @AssertNotBlank()
*/
private $dob;
/**
* @ORMColumn(type="text")
* @Groups({"user:read", "user:write"})
* @AssertNotBlank()
*/
private $address;
/**
* @ORMColumn(type="string", length=255)
* @Groups({"user:read", "user:write"})
* @AssertNotBlank()
* @AssertLength(
* min=8,
* max=8,
* maxMessage="contact number must have 8 character",
* minMessage="contact number must have 8 character"
* )
*/
private $contact;
/**
* @ORMOneToMany(targetEntity="AppEntityCredit", mappedBy="user", cascade={"persist"}, orphanRemoval=true)
* @Groups({"user:read", "user:write"})
* @AssertValid()
*/
private $credits;
/**
* @var DateTime $created
*
* @GedmoTimestampable(on="create")
* @ORMColumn(type="datetime")
*/
private $created_at;
/**
* @var DateTime $updated
*
* @GedmoTimestampable(on="update")
* @ORMColumn(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;
}
}
这是我的信用实体
<?php
namespace AppEntity;
use ApiPlatformCoreAnnotationApiResource;
use DoctrineORMMapping as ORM;
use GedmoMappingAnnotation as Gedmo;
use SymfonyComponentSerializerAnnotationGroups;
use SymfonyComponentValidatorConstraints 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"},
* )
* @ORMEntity(repositoryClass="AppRepositoryCreditRepository")
*/
class Credit
{
/**
* @ORMId()
* @ORMGeneratedValue()
* @ORMColumn(type="integer")
*/
private $id;
/**
* @ORMManyToOne(targetEntity="AppEntityUser", inversedBy="credits")
* @ORMJoinColumn(nullable=false)
* @Groups({"credit:read", "credit:write"})
* @AssertValid()
*/
private $user;
/**
* @ORMColumn(type="string", length=255)
* @Groups({ "user:read", "user:write", "credit:read", "credit:write"})
*/
private $amount;
/**
* @var DateTime $created
*
* @GedmoTimestampable(on="create")
* @ORMColumn(type="datetime")
*/
private $created_at;
/**
* @var DateTime $updated
*
* @GedmoTimestampable(on="update")
* @ORMColumn(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;
}
}
这是我的用户数据持久器
<?php
namespace AppDataPersister;
use ApiPlatformCoreDataPersisterDataPersisterInterface;
use AppEntityCredit;
use AppEntityUser;
use AppManagersEmailManager;
use DoctrineORMEntityManagerInterface;
use SymfonyComponentSecurityCoreEncoderUserPasswordEncoderInterface;
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();
}
}
我相信问题来自用户数据持久器的这个会话
//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();
当 API 被称为"PUT"操作时,我如何实现,金额包括信用额度,(已经实现)并添加当前金额 + 从 API 请求的金额?提前谢谢。
我很确定您正在尝试对数组中的所有积分求和,但您只是在这里使用最后一个元素的值来$creditAmt
:
$creditAmt = 0;
foreach ( $creditArray as $credit ) {
$creditAmt = $credit->getAmount();
}
这可能应该是:
$creditAmt = 0;
foreach ( $creditArray as $credit ) {
$creditAmt = $creditAmt + $credit->getAmount();
}
此外,如果您的$creditArray
为空,您将$creditAmt = 0;
这解释了为什么您没有看到任何添加的信用。确保$data->getCredits()
真正拥有您要总结的"学分"!