CakePHP3の管理画面をプラグインで設定する

#CakePHP3の管理画面をプラグインで設定する

というわけでCakePHP2の時にcacheのせいで断念してた、管理画面をプラグインで管理に再チャレンジ

##プラグインを作成する
手動でも設置可能そうだが、色々設定がめんどくさそうなのでとりあえずbakeで作成してみる。

http://book.cakephp.org/3.0/en/plugins.html#creating-a-plugin-using-bake

```
[fusic@localhost hoge]$ bin/cake bake plugin Admin
(略)
File `/var/www/html/hoge/composer.json` exists
Do you want to overwrite? (y/n/q)
[n] > y
Wrote `/var/www/html/hoge/composer.json`
Error: Could not run `composer dump-autoload`:

```
ふぁー？

composer.jsonの中身を見ると

```
"suggest": [],
```
とCakeが書き換えてしまってるので(多分バグ？)jsonファイルを手動で
```
"suggest": {},
```
に書き換えて、
```
[fusic@localhost hoge]$ php composer.phar dumpautoload
Generating autoload files
```

##bakeでやってたこと（っぽいこと）
- Adminディレクトリを設置し、AppControllerとroutes.phpを設置
- bootstrapにPlugin::loadを記述
- composer.jsonを書き換えて、autoloadを更新

プラグインをCakePHP3対応するに当たってはこのへんが必要そう。

(特にControllerを使う場合は。使わない場合はプラグインを設置して、Plugin::loadを記述するだけでいいと思う)

##AuthComponentを設置

plugins/Admin/src/Controller/AppController.php

※私がCakePHP2で使用していた設定ベース

```
<?php
namespace Admin\Controller;

use App\Controller\AppController as BaseController;
use Cake\Controller\Component\AuthComponent;

use Cake\Event\Event;

class AppController extends BaseController
{
    public $components = [
        'Auth' => [
             'authenticate' => [
                'Form' => [
                    'userModel' => 'Admins',
                    'fields' => [
                        'username' => 'loginid',
                        'password' => 'password'
                    ]
                ],
            ],
            'loginAction' => [
                'controller' => 'admins',
                'action' => 'login',
                'plugin' => 'admin'
            ],
            'loginRedirect' => [
                'controller' => 'tops',
                'action' => 'index',
                'plugin' => 'admin'
            ],
        ]
    ];
    
    public function beforeFilter(Event $event){
        parent::beforeFilter($event);
        $this->Auth->sessionKey = 'Auth.Admin';
        $this->_loginuser = $this->Auth->user();
        $this->set('loginuser', $this->_loginuser);
    }
}

```

plugins/Admin/src/Controller/AdminsController.php

```
<?php
namespace Admin\Controller;

use Admin\Controller\AppController;
use Cake\Event\Event;
use Cake\Core\Configure;
use Cake\Network\Exception\NotFoundException;
use Cake\Auth\DefaultPasswordHasher;

class AdminsController extends AppController
{
    /*
     * beforeFilter
     */
    public function beforeFilter(Event $event){
        parent::beforeFilter($event);
        $this->Auth->allow('edit');
    }
    
    public function login()
    {
        if ($this->request->is('post')) {
            $user = $this->Auth->identify();
            if ($user) {
                $this->Auth->setUser($user);
                return $this->redirect($this->Auth->redirectUrl());
            } else {
                $this->Flash->error(
                    __('Username or password is incorrect'),
                    'default',
                    [],
                    'auth'
                );
            }
        }
    }
    
    public function logout()
    {
        return $this->redirect($this->Auth->logout());
    }
    
    //ここは各自いい感じに。
    function edit() {
        //リリースモードではこのページは表示させない。
        if (!Configure::read('debug')) {
            //not found exception実行には上部にuseが必要
            throw new NotFoundException('404 not found');
        }
        
        $admin = $this->Admins->newEntity();
        //id 1で決め打ち
        $admin_user = $this->Admins->find()
            ->where(['id' => 1])
            ->first();
        if (!$this->request->is('post') && !$this->request->is('put') && !empty($admin_user)) {
            $admin = $admin_user;
        }
        if ($this->request->is('post') || $this->request->is('put')) {
            if (!empty($admin_user)) {
                $this->request->data['id'] = 1;
            }
            if (!empty($this->request->data['edit_password'])) {
                //CakePHP2での$this->Auth->password()に相当
                $this->request->data['password'] = (new DefaultPasswordHasher)->hash($this->request->data['edit_password']);
            }
            $admin = $this->Admins->patchEntity($admin, $this->request->data);
            if ($this->Admins->save($admin)) {
                $this->redirect(['action' => 'login']);
            }
        }
        if (isset($this->request->data['id'])) {
            unset($this->request->data['id']);
        }
        
        $this->set('admin',$admin);
    }
    
}

```

##まとめ
動作に特に問題はなさそう。

- ControllerにAdminなどプレフィックスが不要
- AppControllerを継承したAdminAppControllerみたいなものも作らなくていい
- App::buildとか書かなくても、公開画面と別の個所に設置が可能

てな訳で、管理画面はプラグインに設置が良さそう！