9

この User エンティティがあります。

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ApiResource(
 *     collectionOperations={
 *          "register"={
 *              "method"="POST",
 *              "path"="/users/register",
 *              "denormalization_context"={"groups"={"register"}},
 *              "normalization_context"={"groups"={"read"}},
 *              "validation_groups"={"register"},
 *              "swagger_context"={
 *                  "summary"="Register a user",
 *                  "description"="For anonymous user to register an account."
 *              }
 *          }
 *     }
 * )
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 */
class User implements UserInterface
{
    const ROLE_USER = 'ROLE_USER';
    const ROLE_WEBADMIN = 'ROLE_WEBADMIN';
    const ROLE_SUPERADMIN = 'ROLE_SUPERADMIN';

    const DEFAULT_ROLES = [self::ROLE_USER];

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     * @Groups({"read"})
     */
    private $id;

    /**
     * @Assert\Unique(groups={"write","register"})
     * @ORM\Column(type="string", length=180, unique=true)
     * @Assert\Length(min="6", max="255")
     * @Groups({"read", "write", "register"})
     */
    private $username;

    /**
     * @Assert\Unique(groups={"write","register"})
     * @ORM\Column(type="string", length=255, unique=true)
     * @Assert\Email(groups={"write","register"})
     * @Assert\NotBlank(groups={"register"})
     * @Assert\Length(min=6, max=255, groups={"write","register"})
     * @Groups({"write","register"})
     */
    private $email;

    /**
     * @ORM\Column(type="json")
     * @Groups({"read"})
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     * @Assert\NotBlank(groups={"write", "register"})
     * @Assert\Regex(
     *     pattern="/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{7,}/",
     *     message="Password must be minimum seven characters long and contain at least one digit, one upper case letter, and one lower case letter"
     * )
     * @Groups({"write", "register"})
     */
    private $password;

    /**
     * @Groups({"register"})
     * @Assert\NotBlank(groups={"register"})
     * @Assert\Expression(
     *     "this.getPassword() === this.getRetypePassword()",
     *     message="Passwords does not match",
     *     groups={"register"}
     * )
     */
    private $retypePassword;

    /**
     * @ORM\Column(name="password_change_date", type="integer", nullable=true)
     */
    private $passwordChangeDate;

    /**
     * @var string Full name
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank()
     * @Groups({"read", "write", "register"})
     */
    private $name;

    /**
     * @ORM\Column(name="is_active", type="boolean", options={"default": 0} )
     * @Groups({"read"})
     */
    private $isActive;

    /**
     * @ORM\Column(name="confirmation_token", type="string", length=40, nullable=true)
     */
    private $confirmationToken;

    /**
     * User constructor.
     */
    public function __construct()
    {
        $this->setIsActive(false)
            ->setConfirmationToken(NULL)
            ->setRoles(self::DEFAULT_ROLES);
    }

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

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUsername(): string
    {
        return (string) $this->username;
    }

    public function setUsername(string $username): self
    {
        $this->username = $username;

        return $this;
    }

    /**
     * @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 getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getIsActive(): ?bool
    {
        return $this->isActive;
    }

    public function setIsActive(bool $isActive): self
    {
        $this->isActive = $isActive;

        return $this;
    }

    public function getConfirmationToken(): ?string
    {
        return $this->confirmationToken;
    }

    public function setConfirmationToken(?string $confirmationToken): self
    {
        $this->confirmationToken = $confirmationToken;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getPasswordChangeDate()
    {
        return $this->passwordChangeDate;
    }

    /**
     * @param mixed $passwordChangeDate
     */
    public function setPasswordChangeDate($passwordChangeDate): void
    {
        $this->passwordChangeDate = $passwordChangeDate;
    }

    /**
     * @return string
     */
    public function getRetypePassword(): string
    {
        return $this->retypePassword;
    }

    /**
     * @param string $retypePassword
     */
    public function setRetypePassword(string $retypePassword): void
    {
        $this->retypePassword = $retypePassword;
    }
}

リクエストすると (Insomnia、郵便配達のような API ツール、ヘッダーが既に設定されている)

{
  "username": "cerseilann",
  "password": "password",
  "email": "cerseilann@example.com",
  "name": "Cersei Lannister Duplicate",
  "retypePassword": "password"
}

一意の値に関連するエラー メッセージが表示されることを期待しています。しかし、代わりに、次のエラーが表示されます。

This value should be of type array|IteratorAggregate

完全な応答

{
  "@context": "\/api\/contexts\/ConstraintViolationList",
  "@type": "ConstraintViolationList",
  "hydra:title": "An error occurred",
  "hydra:description": "username: This value should be of type array|IteratorAggregate.\nemail: This value should be of type array|IteratorAggregate.",
  "violations": [
    {
      "propertyPath": "username",
      "message": "This value should be of type array|IteratorAggregate."
    },
    {
      "propertyPath": "email",
      "message": "This value should be of type array|IteratorAggregate."
    }
  ]
}

私は何を取りこぼしたか?

編集

UniqueEntity を使用して削除すると、Unique

...
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @UniqueEntity(fields="username", message="Username {{ value }} already taken. Please use another username.")
 * @UniqueEntity(fields="email", message="Email {{ value }} already being used. COnsider forgot password to retrieve the password.")
 */

...

このリターンエラーが発生しました

{
  "@context": "\/api\/contexts\/Error",
  "@type": "hydra:Error",
  "hydra:title": "An error occurred",
  "hydra:description": "An exception occurred while executing 'INSERT INTO user (username, email, roles, password, password_change_date, name, is_active, confirmation_token) VALUES (?, ?, ?, ?, ?, ?, ?, ?)' with params [\"cerseilann\", \"cerseilann1@example.com\", \"[\\\u0022ROLE_USER\\\u0022]\", \"$argon2id$v=19$m=65536,t=4,p=1$0Wu+2mjS\\\/Uft6lu2ieJOMQ$6ostmakEH2LKYKVvr5PYCoFOZvDwwNT\\\/\\\/+xI+g9hkG8\", null, \"Cersei Lannister 1\", 0, \"adde39972ac50feb3918\"]:\n\nSQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'cerseilann' for key 'UNIQ_8D93D649F85E0677'",
  "trace": [

...

エラーメッセージが表示されることを期待しています。

4

1 に答える 1

14

Unique制約はコレクション (つまり、コレクションを保持するフィールド) 用であり、すべてのエントリが一意であるかどうかを決定します。

おそらく欲しいもの:

UniqueEntity制約 - フィールドではなくエンティティに設定する必要がありますが、フィールドごとに 2 回および 1 回設定し、そのプロパティをそれぞれ適切なフィールドに設定できますfields

于 2019-09-16T05:48:36.580 に答える