7

FOSUserBundle でユーザー名の必要性を取り除きたいです。ユーザーはメール アドレスのみを使用してログインし、ユーザー エンティティの一部として実名フィールドを追加しました。ここで説明されているように、マッピング全体をやり直す必要があることに気付きました。 正しく行ったと思いますが、登録フォームを送信しようとするとエラーが発生します。

「一意性を検証できるのは、Doctrine によってマップされたフィールド名のみです。」

奇妙なことに、ユーザー エンティティ内の何かに対して一意の制約をアサートしようとはしていません。

これが私の完全なユーザーエンティティファイルです:

 <?php
        // src/MyApp/UserBundle/Entity/User.php

        namespace MyApp\UserBundle\Entity;

        use FOS\UserBundle\Model\User as BaseUser;
        use Doctrine\ORM\Mapping as ORM;
        use Symfony\Component\Validator\Constraints as Assert;

        /**
         * @ORM\Entity
         * @ORM\Table(name="depbook_user")
         */
        class User extends BaseUser
        {
            /**
             * @ORM\Id
             * @ORM\Column(type="integer")
             * @ORM\GeneratedValue(strategy="AUTO")
             */
            protected $id;

            /**
             * @ORM\Column(type="string", length=255)
             *
             * @Assert\NotBlank(message="Please enter your first name.", groups={"Registration", "Profile"})
             * @Assert\MaxLength(limit="255", message="The name is too long.", groups={"Registration", "Profile"})
             */
            protected $firstName;

            /**
             * @ORM\Column(type="string", length=255)
             *
             * @Assert\NotBlank(message="Please enter your last name.", groups={"Registration", "Profile"})
             * @Assert\MaxLength(limit="255", message="The name is too long.", groups={"Registration", "Profile"})
             */
            protected $lastName;

            /**
             * @ORM\Column(type="string", length=255)
             *
             * @Assert\NotBlank(message="Please enter your email address.", groups={"Registration", "Profile"})
             * @Assert\MaxLength(limit="255", message="The name is too long.", groups={"Registration", "Profile"})
             * @Assert\Email(groups={"Registration"})
             */
            protected $email;

            /**
             * @ORM\Column(type="string", length=255, name="email_canonical", unique=true)
             */
             protected $emailCanonical;

            /**
             * @ORM\Column(type="boolean")
             */
             protected $enabled;

            /**
             * @ORM\Column(type="string")
             */
             protected $salt;

            /**
             * @ORM\Column(type="string")
             */
             protected $password;

            /**
             * @ORM\Column(type="datetime", nullable=true, name="last_login")
             */
             protected $lastLogin;

            /**
             * @ORM\Column(type="boolean")
             */
             protected $locked;

            /**
             * @ORM\Column(type="boolean")
             */
             protected $expired;

            /**
             * @ORM\Column(type="datetime", nullable=true, name="expires_at")
             */
             protected $expiresAt;

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

            /**
             * @ORM\Column(type="datetime", nullable=true, name="password_requested_at")
             */
             protected $passwordRequestedAt;

            /**
             * @ORM\Column(type="array")
             */
             protected $roles;

            /**
             * @ORM\Column(type="boolean", name="credentials_expired")
             */
             protected $credentialsExpired;

            /**
             * @ORM\Column(type="datetime", nullable=true, name="credentials_expired_at")
             */
             protected $credentialsExpiredAt;

            public function __construct()
            {
                parent::__construct();
                // your own logic
            }

            /**
             * @return string
             */
            public function getFirstName()
            {
                return $this->firstName;
            }

            /**
             * @return string
             */
            public function getLastName()
            {
                return $this->lastName;
            }

             /**
             * Sets the first name.
             *
             * @param string $firstname
             *
             * @return User
             */
            public function setFirstName($firstname)
            {
                $this->firstName = $firstname;

                return $this;
            }

                 /**
             * Sets the last name.
             *
             * @param string $lastname
             *
             * @return User
             */
            public function setLastName($lastname)
            {
                $this->lastName = $lastname;

                return $this;


       }
    }

これについてさまざまな提案を見てきましたが、どの提案もうまくいかないようです。FOSUserBundle ドキュメントは、非常に一般的な要求である必要があるものについて非常にまばらです。

4

3 に答える 3

15

これを行う最も簡単な方法は、バンドルをそのままにして、電子メール アドレスと同じユーザー名を持つようにユーザー クラスを設定することだと思います。

setEmail()これを行うには、メソッドをオーバーライドして、$usernameプロパティも$emailパラメーターにsetEmailCanonical()設定し、 も に設定し$usernameCanonicalます$emailCanonical

public function setEmail($email){
    $this->email = $email;
    $this->username = $email;
}

public function setEmailCanonical($emailCanonical){
    $this->emailCanonical = $emailCanonical;
    $this->usernameCanonical = $emailCanonical;
}

これ以外に行う必要があるのは、セマンティクスに関連することだけです。デフォルトの Username ラベルの代わりに、フォーム ラベルに E-mail を読むようにします。これは、翻訳ファイルをオーバーライドすることで実行できます。あなたにとっては必要ないかもしれないので、これはあなた(または他の誰か)に任せます。

この戦略を使用すると、データベースに冗長なデータが含まれますが、再マッピングの頭痛の種が大幅に軽減されます。

于 2012-09-15T15:29:39.840 に答える
2

ドクトリン 2 を使用している場合は、Life Cycle Events を使用してロジックをコールバック内に配置できます。

http://docs.doctrine-project.org/en/2.0.x/reference/events.html

/**
 * @ORM\PreUpdate()
 * @ORM\PrePersist()
 */
public function setUsernameToEmail()
{
    $this->username = $this->email;
    $this->usernameCanonical = $this->emailCanonical;
}
于 2014-07-16T08:41:51.687 に答える
1

ユーザーにメールの入力を要求したくない場合(つまり、FOSUserBundle でメールをオプションにする)、Symfony 2.7 + FOSUser+SonataUser+SonataAdmin を使用します。

同時に、入力したメールはシステム内で一意である必要がありました。そのため、ユーザーには登録時に 2 つのオプションがあります。

  1. メールを空のままにする
  2. まだシステムにない一意の電子メールを提供します

以下は、期待どおりに機能する私のソリューションです(最もクリーンなソリューションであるとは言いませんが、同様のタスクを達成する方法を示してくれることを願っています)

1) Entity/User.php の変更

namespace AppBundle\Entity;

use Sonata\UserBundle\Entity\BaseUser as BaseUser;
use Doctrine\ORM\Mapping as ORM;


/**
 * @ORM\Entity
 * @ORM\Table(name="fos_user")
 *
 *
 * @ORM\AttributeOverrides({
 *      @ORM\AttributeOverride(name="email",
 *          column=@ORM\Column(
 *              type =  "string",
 *              name     = "email",
 *              nullable = true,
 *              unique   = true
 *          )
 *      ),
 *      @ORM\AttributeOverride(name="emailCanonical",
 *          column=@ORM\Column(
 *              type = "string",
 *              name     = "email_canonical",
 *              nullable = true,
 *              unique   = true
 *          )
 *      )
 * })
 *
\*/
class User extends BaseUser
{

2) app/console doctrine:migrations:diff & migrate を実行すると、データベース テーブルが期待どおりに変更され、email および email_canonical フィールドに「DEFAULT NULL」が追加されました。

3)何を試しても、メールは NULL に設定されていましたが、email_canonical はそうではなく、"" を返していました。RegistrationFormHandler で手動で NULL に設定しようとしましたが、そこの var_dump で、電子メールが入力されていないときに実際に NULL に設定されていることが確認されました。しかし、データベースに FOSUser は "" 空の文字列を送信し、メールに設定した UNIQUE 制約に違反するため、解決策は Entity/User.php のメソッドをオーバーライドすることでした (この質問に対する以前の回答で説明したように)。

// src/AppBundle/Entity/User.php
// ...
public function setEmailCanonical($emailCanonical)
{
   // when email is empty, force canonical to NULL
   // for some reason by default "" empty string is inserted
   $this->emailCanonical = $this->getEmail();
}

4)私の場合、FOSUserBundle (または SonataUserBundle) の Validation を変更して、メールを設定する必要がないようにします。(電子メールに適用されなくなったため、validation.xml から .. を単純に削除しました)

これら 2 つのファイルを config/validation/ ディレクトリにコピーします (SonataUser+FOSUser の場合は、Application/Sonata/UserBundle/Resources です)。

  1. ベンダー/friendsofsymfony/user-bundle/FOS/UserBundle/Resources/config/storage-validation/orm.xml
  2. 上記のパス、config/validation/orm.xml

それらのファイルの「Registration」グループの名前を「myRegistration」などの独自の名前に変更します。

config.yml で新しい validation_group を fos_user にバインドします。Sonata User を使用している場合は、次のとおりです。

sonata_user:
   profile:
      register:
          form:
              ...
              validation_groups:
                - myRegistration
                - Default

楽しむ。

于 2016-02-28T09:30:07.453 に答える