スポンサードリンク

CakePHP
CakePHP

CakePHPで管理機能を作っているところなんですが、

ユーザーのパスワードを変更したい場合に

どの方法を取ろうかと色々と悩んだので

2つほど考えたのですが、

片方を色々な理由でボツにしました。

なんとなく、もったいないかもと思ったので

その覚え書きです。

スポンサードリンク

パスワードの変更画面をどうするか

最初パスワードの変更をどの画面でやるのかで迷いました。

とりあえず、考えられるのは

1.ユーザー名の変更と同じにする
2.パスワードのみの変更画面を作る

1番は画面とアクションを新たに作らなくてもいいので

最初は1番で作っていました。

この方法がボツになりました。

理由はモデルにあるbeforeSaveメソッドを消さないといけなくなったためです。

でも、何かに使えるかもしれないので

とりあえず、その構築を書いていきます。

パスワードの変更をユーザー名の変更と同じにする

まず、Viewファイルを作ります。

View/Users/edit.ctp

<?php echo $this->Form->create('User'); ?>
<table>
	<tr>
		<th>ユーザー名</th>
		<td><?php echo $this->Form->input('username', array('label' => 'username'));?></td>
	</tr>
	<tr>
		<th>パスワード</th>
		<td><?php echo $this->Form->input('password', array('label' => '', 'value' => '')); ?></td>
	</tr>
</table>
<?php echo $this->Form->end('編集'); ?>

パスワードは空白の場合は以前のパスワードのままにして

入力されたら変更するという方法をとりました。

次に、バリデートを付けます。

Model/User.php

class User extends AppModel{
	public $name = 'User';
    public $validate = array(
        'username' => array(
            'required' => array(
                'rule' => array('notEmpty'),
                'message' => 'ユーザー名は必須です。'
            )
        ),
        'password' => array(
            'rule1' => array(
                'rule' => array('alphaNumeric'),
            	'required' => false,
            	'allowEmpty' => true,
                'message' => '半角英数字で入力して下さい。'
            ),
        	'rule2' => array(
        		'rule' => array('minLength', 6),
                'message' => '6文字以上で入力して下さい。'
        	)
        )
    );

    public function beforeSave($options = array()) {
    	if (isset($this->data[$this->alias]['password'])) {
    		$this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
    	}
    	return true;
    }
}

※この段階ではbeforeSaveはまだあります。

バリデーションは空白を許可しています。

空白の場合は以前のパスワードのままという風にするためです。

Controller/UsersController.php

function edit($id = null) {
	if (!$id) {
		throw new NotFoundException(__('エラー:【戻る】を押して下さい!'));
	}

	$user = $this->User->findById($id);

	if (!$user) {
		throw new NotFoundException(__('エラー:データがありません【戻る】を押して下さい!'));
	}

	// POST送信なら
	if($this->request->is('post') || $this->request->is('put')) {
		$this->User->set($this->data);
		//バリデーションをハッシュ化前にチェック
		if ($this->User->validates()) {
			if ($this->request->data['User']['password'] == ""){
				//入力されてなかったら元のパスワードのまま;
				$this->request->data['User']['password'] = $user['User']['password'];
			}
			$this->User->create();

			if ($this->User->save($this->request->data)) {
				$this->Session->setFlash(__('変更しました'));
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash(__('変更できませんでした。やり直して下さい'));
			}
		}
	}else{
		//指定プライマリーキーのデータをセット
		$this->request->data = $user;
	}
}

フォームから送られてきたデータからの場合は

元のパスワードを入れて保存するので

これでできたと思った・・・のですが。

スポンサードリンク

saveの時点でbeforeSaveが呼び出される

結果的に元のパスワードをフォームデータに入れても

saveメソッドの前にbeforeSaveメソッドが動いて

ハッシュされてたパスワードが

さらにハッシュされるという事態になりました。

じゃあ、befoerSaveをなくせばいいじゃんということで

function edit($id = null) {
	if (!$id) {
		throw new NotFoundException(__('エラー:【戻る】を押して下さい!'));
	}

	$user = $this->User->findById($id);

	if (!$user) {
		throw new NotFoundException(__('エラー:データがありません【戻る】を押して下さい!'));
	}

	// POST送信なら
	if($this->request->is('post') || $this->request->is('put')) {
		$this->User->set($this->data);
		//バリデーションをハッシュ化前にチェック
		if ($this->User->validates()) {
			if ($this->request->data['User']['password'] == ""){
				//入力されてなかったら元のパスワードのまま
				$this->request->data['User']['password'] = $user['User']['password'];
			}else{  //※↓↓↓↓追加↓↓↓↓
				//パスワードをハッシュ化
				$this->request->data['User']['password'] = AuthComponent::password($this->request->data['User']['password']);
			}

			$this->User->create();

			if ($this->User->save($this->request->data)) {
				$this->Session->setFlash(__('変更しました'));
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash(__('変更できませんでした。やり直して下さい'));
			}
		}
	}else{
		//指定プライマリーキーのデータをセット
		$this->request->data = $user;
	}
}

以上のようにして

モデルに書いてあるbeforeSaveを消してしまえば

期待通りの動きができました。

しかし、befoerSaveを消してしまうと

後々面倒なので

この方法はあきらめて

最初に書いていた

2.パスワードのみの変更画面を作る

を実装することにしました。

最初からこっちにしておけばよかったな~

実装の仕方は次回書きます。

スポンサードリンク