CakePHP3で自作アプリを作ってみた part6 〜削除、ログイン、認証・認可〜

7回に渡って記載していきます。
**CakePHP3で自作アプリを作ってみた シリーズ**
セミファイナルです！

今回part6では

* 削除機能
* ログイン 認証、認可

を解説したいと思います。

ブツはこちら公開済み。
https://cocktail-com.herokuapp.com/

データ登録が間に合わなかったので悪しからず。。。
少しづつ登録します。

今までの記事
**CakePHP3で自作アプリを作ってみた part1 〜イントロ〜**
https://qiita.com/m-hatano/items/61392c33fdbd49376747

**CakePHP3で自作アプリを作ってみた part2 〜herokuでHello World!!まで〜**
https://qiita.com/m-hatano/items/79480fa380ebc49c0209

**CakePHP3で自作アプリを作ってみた part3 〜検索機能の実装〜**
https://qiita.com/m-hatano/items/e85b8aa8fcaa0c3410f0

**CakePHP3で自作アプリを作ってみた part4 〜登録・編集機能の実装〜**
https://qiita.com/m-hatano/items/86657cf8b69fcb542d66

**CakePHP3で自作アプリを作ってみた part5 〜画像アップロードの実装〜**
https://qiita.com/m-hatano/items/47cd8607e19a523749f0

---

# 削除

```php
    /**
     * カクテル削除
     */
    public function delete($id = null)
    {
        $this->request->allowMethod(['post', 'delete']);
        $cocktails = $this->Cocktails->get($id);
        if ($this->Cocktails->delete($cocktails)) {
            $this->Flash->success(__('カクテルを削除しました。'));
        } else {
            $this->Flash->error(__(MessageUtil::getMsg(MessageUtil::SAVE_ERROR)));
        }

        return $this->redirect(['action' => 'index']);
    }
```
簡単です。
allowMethodは認可なので後述します。

tableクラスのdeleteメソッドを使う場合は削除対象のEntityを渡します。
CocktailsController内ならば、

```php
$this->Cocktails->get($id)
```
でエンティティが取得できるので、それをdeleteに渡してあげれば削除できます。
Tableクラスを見て見ればわかりますが、deleteAllというメソッドも用意されていて、こっちはwhere句として生成する条件を渡せば削除できます。

```php
$this->Cocktails->->deleteAll(['id >' => 3]);
```
みたいな感じで渡せばidが3よりも大きい条件で削除できます。

# ログイン 認証・認可
チュートリアル
https://book.cakephp.org/3.0/ja/tutorials-and-examples/cms/authentication.html

公式の記事がなんだかんだわかりやすいです。
Cakeに沿って作成すればここは生産性がものすごいあがるとこですね。

認証= わかりやすいところユーザのログイン認証のことです。
認可= 各アクションやページでそのユーザやログインが許可されているかの判別ってとこです。

* Controller/AppController#initialized()

```php
        $this->loadComponent('Auth', [
            // 認可
            'authorize' => 'Controller',
            // ログイン認証
            'authenticate' => [
                'Form' => [
                    'fields' => [
                        'username' => 'login',
                        'password' => 'password'
                    ]
                ]
            ],
            'loginAction' => [
                'controller' => 'Users',
                'action' => 'login'
            ],
            // 未認証の場合、直前のページに戻します
            'unauthorizedRedirect' => $this->referer()
        ]);

        // 未承認で許可するアクション
        $this->Auth->allow(['index', 'search', 'view']);
```
まずコンポーネントを読み込み、設定をします。

　ビューはこんな感じです。

```php
<h1>管理者ログイン</h1>
<?= $this->Form->create() ?>
<?= $this->Form->control('login') ?>
<?= $this->Form->control('password') ?>
<?= $this->Form->button('ログイン') ?>
<?= $this->Form->end() ?>
```
* 認可はコントローラで制御します。
* ログイン画面のlogin, passwordの要素で認証します。
* ログインのアクションのコントローラとアクションはこれです。
* 未承認のときのリダイレクト先
* 未承認でも実行できるアクション

をそれぞれ設定しています。

* Controller/UserController.php

```php
    /**
     * ログイン
     * POST users/login
     * @return \Cake\Http\Response|NULL
     */
    public function login()
    {
        if ($this->request->is('post')) {
            $user = $this->Auth->identify();
            if ($user) {
                $this->Auth->setUser($user);
                $this->Flash->success('ログインしました。');
                return $this->redirect($this->Auth->redirectUrl());
            }
            $this->Flash->error('ユーザー名またはパスワードが不正です。');
        }
    }

    /**
     * ログアウト
     * @return \Cake\Http\Response|NULL
     */
    public function logout()
    {
        $this->Flash->success('ログアウトしました。');
        return $this->redirect($this->Auth->logout());
    }
```

ログイン、ログアウトは簡潔です。
ここはCakeの呪文のように書くだけです。

```php
$this->Auth->identify();
```
でAuthをロードした時に設定したfieldsを使用したログイン認証をします。
認証成功したらsetUserでセッションにユーザを設定します。
セッションの管理場所はcongig/app.phpに記載されています。

セッション参考
https://book.cakephp.org/3.0/ja/development/sessions.html

* Controller/AppController#isAuthorized()

```php
    /**
     * 'authorize' => 'Controller'でアクセスのたびに評価される
     * allowで許可させているアクションでは実行されない
     * {@inheritDoc}
     * @see \Cake\Controller\Controller::isAuthorized($user)
     */
    public function isAuthorized($user)
    {
        // デフォルトでは、アクセスを拒否する
        return false;
    }
```

ControllerのisAuthorizedをオーバーライドして認可のロジックを実装できます。
AppControllerではコントローラ共通ロジックを実装しておくといいですね。
今回は全アクションで拒否にしておいて。
各コントローラで許可する形にします。
しかし、コメントに書いてあるようにallow()してあるメソッドでは実行されません。

* Controller/CocktailsController#isAuthorized()

```php
    public function isAuthorized($user)
    {
        $action = $this->request->getParam('action');
        // ログイン時に許可するアクション
        if (in_array($action, ['edit', 'add', 'delete', 'mergeElementsTable', 'deleteElementsTable'])) {
            return true;
        }
        return false;
    }
```

ログインしていないと実行できないアクションを定義しています。
発展系としては、ログインユーザのロールを判別してアクションの実行権限を判別したりに使用できます。

allow()で常時許可の設定をしてisAuthorized()でログイン時の許可をするってとこでしょうか。

---

さっぱりしていますが以上です。

part6はここまでで次回ラストは

* キャッシュ設定

を解説します。
最後までお付き合いありがとうございました！