数据持久性器在"PUT"操作时未累加金额



我是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()真正拥有您要总结的"学分"!

最新更新