4

laravel/ardentでパスワードを使用してユーザーモデルを編集する意図された方法は何ですか? 私の問題は、ユーザー入力が正しく検証される前に、データベースから実際のユーザーモデルをロードしたくないということです。パスワードが必要なため、パスワード フィールドを空のままにすると、検証は明らかに失敗します。これは私の現在の編集後のアクションです:

public function postEdit($id)
{
    // ardent autohydrates this model
    $newUser = new User;

    // validation fails
    if(!$newUser->validate())
        return Redirect::action('UsersController@getEdit', $id)
            ->with('error', Lang::get('Bitte Eingabe überprüfen'))
            ->withErrors($newUser->errors())
            ->withInput(Input::except('password'));

    // load model from db
    $exUser = User::find($id);
    if(!$exUser->exists)
        return Response::make('No such user', 500);

    // save model, ardent autohydrates again?
    if($exUser->save())
        return Redirect::action('UsersController@getShow', $id)
            ->with('success', Lang::get('Änderungen gespeichert'));
    else
        return Redirect::action('UsersController@getEdit', $id)
            ->with('error', Lang::get('Bitte Eingabe überprüfen'))
            ->withErrors($newUser->errors())
            ->withInput(Input::except('password'));
}

これは非常に多くのコードのようです (+ 機能していません)。この状況の例を見つけることができませんでした

4

2 に答える 2

2

これはあまり活発なトピックではないので、自分で解決しました。

問題は、ardents の自動ハイドレーション機能と、新しいパスワードが指定されていない場合に古いパスワードを保持するという独自の要件を組み合わせることでした。ardent はvalidate()ANDsave()で自動ハイドレートするため、空のパスワードも自動ハイドレートするのを防ぐ方法はありませんでした。最初に、入力配列を変更して古いパスワードで上書きしようとしましたが、ユーザー モデルのオートハイドレーションをオフにしました。

class User extends Ardent implements UserInterface, RemindableInterface {

    public $forceEntityHydrationFromInput = false;
    public $autoHydrateEntityFromInput = false;

これは、POST での編集アクションです。

public function postEdit($id)
{
    // manually insert the input
    $user = new User(Input::all());

    // validate the user with special rules (password not required)
    if($user->validate(User::$updateRules)) {

        // get user from database and fill with input except password
        $user = User::find($id);
        $user->fill(Input::except('password'));

        // fill in password if it is not empty
        // will flag the pw as dirty, which will trigger rehashing on save()
        if(!empty(Input::get('password')))
            $user->password = Input::get('password');

        if($user->save())
            return Redirect::action('UsersController@getIndex')
                ->with('success', Lang::get('Änderungen gespeichert'));
    }

    return Redirect::action('UsersController@getEdit', $id)
        ->with('error', Lang::get('Bitte Eingaben überprüfen'))
        ->withErrors($user->errors())
        ->withInput(Input::except('password'));
}
于 2014-01-25T16:48:48.487 に答える
1

私はあなたと同じ問題に遭遇しました。永遠に検索した後、Ardent コードを読み、これを思いつきました。これにより、一連のルール、自動ハイドレーション、自動ハッシュ パスワード、および Ardent の updateUnique() 関数を使用できます。私はそれがクリーンアップできることを知っており、それを行うためのより良い方法があると確信していますが、私はすでにこの問題に多くの時間を費やしてきました.

これは、コントローラーで動的な beforeSave() クロージャーを使用します (ここに記載されています)。更新中なので、パスワードが送信されているかどうかを確認します。パスワードがない場合は、$rules 配列のパスワード検証を空白に設定し、検証からパスワードを除外します。パスワードの自動ハッシュは検証後、beforeSave() の前に行われるため、これを無効にする (false に設定する) 必要があります。モデルは検証に合格した後に 2 回伝播されるため、送信された空白のパスワード フィールドは beforeSave() の前にハッシュが発行され、空白ではなくなり、2 回目のチェックに失敗します。updateUniques() 'または Save()' を実行するとき、送信されているパスワードがあるかどうかを再度確認する beforeSave クロージャを渡します。送信されていない場合は、更新から削除します。

tl;dr最小限のコードで、Ardent自動ハイドレーションが管理更新でパスワードを要求および/または削除するのを防ぎます。

モデル:

class User extends Ardent implements UserInterface, RemindableInterface {

use UserTrait, RemindableTrait;

// Auto Hydrate
public $autoHydrateEntityFromInput   = true;
public $forceEntityHydrationFromInput   = true;
public $autoPurgeRedundantAttributes    = true;
// Auto hash passwords
public static $passwordAttributes  = array('password');
public $autoHashPasswordAttributes = true;

protected $table  = 'users';
protected $guarded  = array('id','created_at','updated_at');
protected $hidden = array('password');
protected $fillable = array('first_name','last_name','employee_id','position','email','password');

public static $rules = array(
    'first_name'            => 'required',
    'last_name'             => 'required',
    'employee_id'           => 'required|max:10',
    'position'              => 'required',
    'email'                 => 'required|email|unique',
    'password'              => 'required|alpha_num|min:6',
);

コントローラ:

public function update($id)
{
    $user = User::find($id);
    // Check if a password has been submitted
    if(!Input::has('password')){
    // If so remove the validation rule
      $user::$rules['password'] = '';
    // Also set autoHash to false;
      $user->autoHashPasswordAttributes = false;
    }
    // Run the update passing a Dynamic beforeSave() closure as the fourth argument
    if($user->updateUniques(
      array(),
      array(),
      array(),
      function($user){
    // Check for the presence of a blank password field again
        if(empty($user->password)){
    // If present remove it from the update
          unset($user->password);
          return true;
        }
      })
    ){
      Alert::success('User Updated')->flash();
      return Redirect::route('admin.users.index');
    }
        Alert::add('form','true')->flash();
    return Redirect::back()
      ->withInput(Input::except('password'))
      ->withErrors($user->errors());
}
于 2014-08-11T03:17:40.663 に答える