[自分メモ]FuelPHPでユーザー認証（登録まで）

## やること

SimpleAuthパッケージを使ってユーザー認証の仕組みを作る。
ざっくりこの3つのことができれば良さそう。

* usersテーブル作成
* ユーザー登録
* ログイン（これはまた別の記事で作成）


SimpleAuthについては以下のドキュメント参照。
docs: http://fuelphp.jp/docs/1.9/packages/auth/simpleauth/intro.html

参考: https://qiita.com/hththt/items/77428ffd489b953c610c

## 設定

### パッケージ有効化

`config.php`でpackageを有効化。

コメントアウトされている`always_load`の項目のコメントアウトを外す。

```
'always_load' => array(
  'orm',
  'auth',
),
```

とする。

ormはORMapperパッケージ。

doc: http://fuelphp.jp/docs/1.9/packages/orm/intro.html

### auth設定を導入

```
$ cp packages/auth/config/auth.php app/config
```

このauthファイルの中でソルトを設定できるみたいなので、その設定をしておく。

```
return array(
    'driver'                 => 'Simpleauth',
    'verify_multiple_logins' => false,
    'salt'                   => '********',
    'iterations'             => 10000,
);
```


`verify_multiple_logins`は同一ユーザーの複数ログインを許可するかどうかの設定。
`salt`ってgit管理下に置かない方がいいのでは…？と思ったけど、ソルトはバレてもいいぽい。探索に時間がかかるようにすることで安全性を担保する。PBKDF2方式を採用している。

https://ask.fm/tokumaru/answers/125698957117

## usersテーブル作成

モデル作成と同時にマイグレーションを作成してくれるよう。

authに必要なマイグレーションの作成は以下のコマンドからできる。

```
$ php oil refine migrate --packages=auth
```

生成されたテーブル確認

```
mysql> show tables;
+-------------------------+
| Tables_in_fuel_practice |
+-------------------------+
| migration               |
| users                   |
| users_clients           |
| users_providers         |
| users_scopes            |
| users_sessions          |
| users_sessionscopes     |
+-------------------------+

mysql> desc users;
+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| id             | int(11)      | NO   | PRI | NULL    | auto_increment |
| username       | varchar(50)  | NO   | MUL | NULL    |                |
| password       | varchar(255) | NO   |     | NULL    |                |
| group          | int(11)      | NO   |     | 1       |                |
| email          | varchar(255) | NO   |     | NULL    |                |
| last_login     | varchar(25)  | NO   |     | NULL    |                |
| login_hash     | varchar(255) | NO   |     | NULL    |                |
| profile_fields | text         | NO   |     | NULL    |                |
| created_at     | int(11)      | NO   |     | 0       |                |
| updated_at     | int(11)      | NO   |     | 0       |                |
+----------------+--------------+------+-----+---------+----------------+

```

それぞれのテーブルの用途については、別途。


## ユーザー登録画面作成

### View

* FormHelper使える。
doc: http://fuelphp.jp/docs/1.9/classes/form.html

```
<div class="row alert alert-danger">
  <p><?php echo Session::get_flash('message') ?></p>
</div>

<div class="row" style="padding: 2rem;">
<?php echo Form::open(['action' => 'user/register', 'method' => 'post']); ?>
<div class="form-group">
  <label for="username">ユーザー名</label>
  <?php echo Form::input('username', null, ['id' => 'username', 'class' => 'form-controll']); ?>
</div>
<div class="form-group">
  <label for="email">メールアドレス</label>
  <?php echo Form::input('email', null, ['id' => 'email', 'class' => 'form-controll']); ?>
</div>
<div class="form-group">
  <label for="password">パスワード</label>
  <?php echo Form::password('password', null, ['id' => 'password', 'class' => 'form-controll']); ?>
</div>
<?php echo form::button('submit', null, ['class' => 'btn btn-primary']); ?>
<?php echo Form::close(); ?>
</div>
```

### Controller

* メソッド名を`get_*`、`post_*`とすることでHTTPメソッドに対応させることができる。

* テーブルにusernameとemailで複合ユニークキーがついているので、同一ユーザーがすでに登録済みかどうかは、例外で判定。（create_user()の内部処理で、もしusernameとemailのどちらかがすでに登録済みだった場合に、例外を投げる処理が実装されている）
* エラー後に元のページに戻るのをいい感じに書きたい。

``

```
  public function post_register()
  {
    if (
      empty($_POST['username'])
      || empty($_POST['password'])
      || empty($_POST['email'])
    )
    {
      Session::set_flash('message', '入力は全て必須です');
      $data["subnav"] = array('register'=> 'active' );
      $this->template->title = 'User &raquo; Register';
      $this->template->content = View::forge('user/register', $data);
      return;
    }

    try {
      Auth::create_user(
        $_POST['username'],
        $_POST['password'],
        $_POST['email'],
        1
      );
    } catch (Exception $e) {
      Session::set_flash('message', 'そのユーザーは登録できません');
      $data["subnav"] = array('register'=> 'active' );
      $this->template->title = 'User &raquo; Register';
      $this->template->content = View::forge('user/register', $data);
      return;
    }

    Response::redirect('/');
  }
```