
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.パスワードのみの変更画面を作る
を実装することにしました。
最初からこっちにしておけばよかったな~
実装の仕方は次回書きます。
