web-dev-qa-db-ja.com

Symfony2 / Symfony3のFOSUserBundleを使用して、ユーザー名フィールドを削除/メールで置き換えます

ログインモードとしてメールのみが必要で、ユーザー名は必要ありません。 symfony2/symfony3とFOSUserbundleで可能ですか?

ここを読みます http://groups.google.com/group/symfony2/browse_thread/thread/92ac92eb18b423fe

しかし、その後、2つの制約違反が発生します。

問題は、ユーザーが電子メールアドレスを空白のままにすると、2つの制約違反が発生することです。

  • ユーザー名を入力して下さい
  • メールアドレスを入力してください

特定のフィールドの検証を無効にする方法、またはフォームからフィールドを完全に削除するより良い方法はありますか?

57
user825904

実行する必要があるものの完全な概要

ここで、実行する必要があるものの完全な概要を示します。この投稿の最後に、あちこちで見つかったさまざまなソースをリストしました。

1. Acme\UserBundle\Entity\Userのセッターをオーバーライドします

public function setEmail($email)
{
    $email = is_null($email) ? '' : $email;
    parent::setEmail($email);
    $this->setUsername($email);

    return $this;
}

2.フォームタイプからユーザー名フィールドを削除します

RegistrationFormTypeProfileFormTypeの両方で)

public function buildForm(FormBuilder $builder, array $options)
{
    parent::buildForm($builder, $options);
    $builder->remove('username');  // we use email as the username
    //..
}

3.検証の制約

@nurikabeで示されているように、FOSUserBundleで提供される検証制約を取り除き、独自の制約を作成する必要があります。これは、以前にFOSUserBundleで作成されたすべての制約を再作成し、usernameフィールドに関係する制約を削除する必要があることを意味します。作成する新しい検証グループは、AcmeRegistrationAcmeProfileです。したがって、FOSUserBundleによって提供されるものを完全にオーバーライドしています。

3.a. Acme\UserBundle\Resources\config\config.ymlの設定ファイルを更新します

fos_user:
    db_driver: orm
    firewall_name: main
    user_class: Acme\UserBundle\Entity\User
    registration:
        form:
            type: acme_user_registration
            validation_groups: [AcmeRegistration]
    profile:
        form:
            type: acme_user_profile
            validation_groups: [AcmeProfile]

3.b.検証ファイルを作成Acme\UserBundle\Resources\config\validation.yml

それは長いです:

Acme\UserBundle\Entity\User:
    properties:
    # Your custom fields in your user entity, here is an example with FirstName
        firstName:
            - NotBlank:
                message: acme_user.first_name.blank
                groups: [ "AcmeProfile" ]
            - Length:
                min: 2
                minMessage: acme_user.first_name.short
                max: 255
                maxMessage: acme_user.first_name.long
                groups: [ "AcmeProfile" ]



# Note: We still want to validate the email
# See FOSUserBundle/Resources/config/validation/orm.xml to understand
# the UniqueEntity constraint that was originally applied to both
# username and email fields
#
# As you can see, we are only applying the UniqueEntity constraint to 
# the email field and not the username field.
FOS\UserBundle\Model\User:
    constraints:
        - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity: 
             fields: email
             errorPath: email 
             message: fos_user.email.already_used
             groups: [ "AcmeRegistration", "AcmeProfile" ]

    properties:
        email:
            - NotBlank:
                message: fos_user.email.blank
                groups: [ "AcmeRegistration", "AcmeProfile" ]
            - Length:
                min: 2
                minMessage: fos_user.email.short
                max: 255
                maxMessage: fos_user.email.long
                groups: [ "AcmeRegistration", "ResetPassword" ]
            - Email:
                message: fos_user.email.invalid
                groups: [ "AcmeRegistration", "AcmeProfile" ]
        plainPassword:
            - NotBlank:
                message: fos_user.password.blank
                groups: [ "AcmeRegistration", "ResetPassword", "ChangePassword" ]
            - Length:
                min: 2
                max: 4096
                minMessage: fos_user.password.short
                groups: [ "AcmeRegistration", "AcmeProfile", "ResetPassword", "ChangePassword"]

FOS\UserBundle\Model\Group:
    properties:
        name:
            - NotBlank:
                message: fos_user.group.blank
                groups: [ "AcmeRegistration" ]
            - Length:
                min: 2
                minMessage: fos_user.group.short
                max: 255
                maxMessage: fos_user.group.long
                groups: [ "AcmeRegistration" ]

FOS\UserBundle\Propel\User:
    properties:
        email:
            - NotBlank:
                message: fos_user.email.blank
                groups: [ "AcmeRegistration", "AcmeProfile" ]
            - Length:
                min: 2
                minMessage: fos_user.email.short
                max: 255
                maxMessage: fos_user.email.long
                groups: [ "AcmeRegistration", "ResetPassword" ]
            - Email:
                message: fos_user.email.invalid
                groups: [ "AcmeRegistration", "AcmeProfile" ]

        plainPassword:
            - NotBlank:
                message: fos_user.password.blank
                groups: [ "AcmeRegistration", "ResetPassword", "ChangePassword" ]
            - Length:
                min: 2
                max: 4096
                minMessage: fos_user.password.short
                groups: [ "AcmeRegistration", "AcmeProfile", "ResetPassword", "ChangePassword"]


FOS\UserBundle\Propel\Group:
    properties:
        name:
            - NotBlank:
                message: fos_user.group.blank
                groups: [ "AcmeRegistration" ]
            - Length:
                min: 2
                minMessage: fos_user.group.short
                max: 255
                maxMessage: fos_user.group.long
                groups: [ "AcmeRegistration" ]

4.終了

それでおしまい!あなたは行くのが良いはずです!


この投稿に使用されたドキュメント:

104
Mick

登録フォームとプロフィールフォームの両方のタイプを詳細に上書きすることでこれを行うことができました here 、ユーザー名フィールドを削除します

$builder->remove('username');

具体的なユーザークラスでsetEmailメソッドをオーバーライドするとともに:

 public function setEmail($email) 
 {
    $email = is_null($email) ? '' : $email;
    parent::setEmail($email);
    $this->setUsername($email);
  }
7
Ben_hawk

Sf 2.3の時点では、簡単な回避策は、BaseUserを拡張するクラスUserの_construct内の任意の文字列にユーザー名を設定することです。

public function __construct()
    {
        parent::__construct();
        $this->username = 'username';
    }

このように、バリデーターは違反をトリガーしません。ただし、 Patt で投稿されたユーザー名にメールを設定することを忘れないでください。

public function setEmail($email)
{
    $email = is_null($email) ? '' : $email;
    parent::setEmail($email);
    $this->setUsername($email);
}

User:usernameへの参照について他のファイルを確認し、それに応じて変更する必要がある場合があります。

2
iambray

Michaelが指摘しているように、これはカスタム検証グループで解決できます。例えば:

fos_user:
    db_driver: orm
    firewall_name: main
    user_class: App\UserBundle\Entity\User
    registration:
        form:
            type: app_user_registration
            validation_groups: [AppRegistration]

次に、エンティティで(user_class: App\UserBundle\Entity\User)AppRegistrationグループを使用できます。

class User extends BaseUser {

    /**
     * Override $email so that we can apply custom validation.
     * 
     * @Assert\NotBlank(groups={"AppRegistration"})
     * @Assert\MaxLength(limit="255", message="Please abbreviate.", groups={"AppRegistration"})
     * @Assert\Email(groups={"AppRegistration"})
     */
    protected $email;
    ...

これは、Symfony2スレッドにその返信を投稿した後にやったことです。

詳細については http://symfony.com/doc/2.0/book/validation.html#validation-groups をご覧ください。

2
nurikabe

検証をカスタマイズしてみましたか?

これを行うには、UserBundleから継承する独自のバンドルを作成してから、Resources/config/validation.xmlをコピー/調整する必要があります。さらに、config.ymlのvalidation_groupsをカスタム検証に設定する必要があります。

1
Michael Sauter

Validationを置き換える代わりに、RegistrationFormHandler#processを置き換え、元のメソッドのコピーである新しいメソッドprocessExtended(たとえば)をより正確に追加し、RegistrationControllerでutを使用します。 (オーバーライド: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md#next-steps

登録フォームをバインドする前に、たとえば「空」のユーザー名を設定します。

class RegistrationFormHandler extends BaseHandler
{

    public function processExtended($confirmation = false)
    {
        $user = $this->userManager->createUser();
        $user->setUsername('empty'); //That's it!!
        $this->form->setData($user);

        if ('POST' == $this->request->getMethod()) {


            $this->form->bindRequest($this->request);

            if ($this->form->isValid()) {

                $user->setUsername($user->getEmail()); //set email as username!!!!!
                $this->onSuccess($user, $confirmation);

                /* some my own logic*/

                $this->userManager->updateUser($user);
                return true;
            }
        }

        return false;
    }
    // replace other functions if you want
}

どうして? FOSUserBundle検証ルールを使用することを好みます。登録フォームのconfig.ymlの検証グループを置き換えると、自分のユーザーエンティティでユーザーの検証ルールを繰り返す必要があるためです。

1
ZloyPotroh

それらのどれも動作しない場合、迅速かつ汚い解決策があります

public function setEmail($email)
{
    $email = is_null($email) ? '' : $email;
    parent::setEmail($email);
    $this->setUsername(uniqid()); // We do not care about the username

    return $this;
}
1
getvivekv

ユーザー名をNULL可能にしてから、フォームタイプから削除できます。

最初のAppBundle\Entity\Userで、上に注釈を追加しますユーザークラス

_use Doctrine\ORM\Mapping\AttributeOverrides;
use Doctrine\ORM\Mapping\AttributeOverride;

/**
 * User
 *
 * @ORM\Table(name="fos_user")
 *  @AttributeOverrides({
 *     @AttributeOverride(name="username",
 *         column=@ORM\Column(
 *             name="username",
 *             type="string",
 *             length=255,
 *             unique=false,
 *             nullable=true
 *         )
 *     ),
 *     @AttributeOverride(name="usernameCanonical",
 *         column=@ORM\Column(
 *             name="usernameCanonical",
 *             type="string",
 *             length=255,
 *             unique=false,
 *             nullable=true
 *         )
 *     )
 * })
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 */
class User extends BaseUser
{
//..
_

_php bin/console doctrine:schema:update --force_を実行すると、データベース内でユーザー名がNULL可能になります。

Second、フォームタイプAppBundle\Form\RegistrationTypeで、フォームからのユーザー名。

_    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder->remove('username');
        // you can add other fields with ->add('field_name')
    }
_

これで、フォームにusernameフィールドが表示されなくなります($builder->remove('username');のおかげです)。また、フォームを送信するときに、検証エラーが表示されなくなりました(注釈のおかげで)「ユーザー名を入力してください」は不要になりました。

ソース: https://github.com/FriendsOfSymfony/FOSUserBundle/issues/982#issuecomment-1293166

0
Eissa