4

FOSUserBundle を使用しており、ユーザーがユーザー プロファイルを更新できるページを作成しようとしています。私が直面している問題は、ユーザーがパスワードを変更/更新したくない場合に、フォームでパスワードを再入力する必要がないことです。したがって、ユーザーが空のパスワードでフォームを送信すると、データベースは空の文字列で更新され、ユーザーはログインできなくなります。

パスワード フィールドが設定されていない場合、フォームにパスワード フィールドの更新を無視させるにはどうすればよいですか? 以下は私が使用しているコードです。

$user = $this->get('security.context')->getToken()->getUser();

//user form has email and repeating password fields    
$userForm = $this->createForm(new UserFormType(), $user);

if ($request->getMethod() == 'POST') {
   $userForm->bindRequest($request);

   if($userForm->isValid()){
      //this will be be empty string in the database if the user does not enter a password
      $user->setPlainPassword($userForm->getData()->getPassword());
      $em->flush();
   }
}

次のようないくつかのことを試しましたが、bindRequest が空のパスワードをユーザーに設定するため、これはまだ空です。

if($userForm->getData()->getPassword())
   $user->setPlainPassword($userForm->getData()->getPassword());

私も試しましたが、これは同様の状況になり、不要なクエリが発生します

if($userForm->getData()->getPassword())
   $user->setPlainPassword($userForm->getData()->getPassword());
else
   $user->setPlainPassword($user->getPlainPassword());

このユースケースを処理するエレガントな方法はありますか?

4

4 に答える 4

6

問題は、パスワードを制御する前に、フォームをユーザー オブジェクトにバインドすることです。コードのスニペットを分析してみましょう。

以下をせよ

$user = $this->get('security.context')->getToken()->getUser();

既存のユーザーをユーザー オブジェクトに読み込みます。
次に、そのデータを使用してフォームを「構築」し、投稿を受信した場合、投稿されたデータを前のオブジェクトに取り込みます

$userForm = $this->createForm(new UserFormType(), $user);

if ($request->getMethod() == 'POST') {
   $userForm->bindRequest($request);

したがって、空のままにしておくと、以前のパスワードがオブジェクトにbindRequest既に失われています(明らかにデータベースにはまだありません)。これからのすべてのコントロールは役に立たない。

その場合の解決策は、フォームのフィールドの値をオブジェクトに直接手動で検証し$requestてから、基になるオブジェクトにバインドすることです。
この簡単なコード スニペットでこれを行うことができます。

$postedValues = $request->request->get('formName');

ここで、パスワード値が入力されていることを確認する必要があります

if($postedValues['plainPassword']) { ... }

私たちがplainPassword興味を持っている分野の名前だと思います。

このフィールドに値が含まれていることがわかった場合 (else ブランチ)、何もする必要はありません。
それ以外の場合は、ユーザー オブジェクトから元のパスワードを取得し、$request対応する値に設定する必要があります。
( update$request ) それ以外の場合は、ユーザー オブジェクトからパスワードを取得できますが、そのパスワードはハッシュされた値で保存されているため、再びハッシュに苦しむため、オブジェクトに入れることはできません。
あなたができること-私が推測する-は、オブジェクトに直接array_pop$requestし、すべてのものを台無しにするフィールドを片付けることです(plainPassword)これらのことを行ったので、投稿されたデータを基になるオブジェクトにバインドできます。

別の解決策 (一部のビジネス ロジックをコントローラーから遠ざけるため、おそらくより良い方法) はprePersistフックを使用することですが、概念的にはより高度です。その解決策を探りたい場合は、フォームイベントについてこれを読むことができます

于 2012-07-22T08:18:11.410 に答える
1

これが実際に良いユースケースであるかどうかを再考する必要があると思います. ユーザーは他のユーザーのパスワードを編集できる必要がありますか? 私たちの機関では、最高レベルの管理者でさえ、このタスクを実行することを許可していません.

ユーザーがパスワードを変更する必要がある場合は、ユーザー自身が処理できるようにします。パスワードを忘れた場合は、電子メールで取得できます。メールの調整で支援が必要な場合は、管理者がユーザーを支援できるようにします。ただし、すべてのパスワードの更新と作成は、ユーザーのみが行います。

FOSUserBundle が他の方法で行うのを非常に困難にしているのは素晴らしいことだと思いますが、必要な場合は DonCallisto が良い解決策を持っているようです。

于 2012-07-23T20:52:49.633 に答える
0
<?php

class User
{
    public function setPassword($password)
    {
        if (false == empty($password)) {
            $this->password = $password;
        }
    }
}

これは、空でない場合にのみ、ユーザーのパスワードを更新します。

于 2012-07-20T10:49:35.533 に答える