[オレオレ09] MVCのC コントローラー

## 解説
前回はフロントコントローラーですべてのリクエストを index.php に集約しました。
結果、index.phpに全ての機能を実装するのは非現実的であることが明らかになりました。
今回はindex.phpから個別の処理部分を分離して各クラス（コントローラー）で管理するようにします。
例としてユーザー管理機能を実装していきます。

## 目次
1. ディレクトリ再構成
1. .htaccess修正
1. Request.php修正
1. ディスパッチャークラス作成
1. Httpクラス作成
1. コントローラー（親）クラス作成
1. ユーザーコントローラー作成
1. create.html修正
1. index.php修正
1. ブラウザで確認

## ディレクトリ再構成
```:現在の構成
stampede/
    public/
        .htaccess
        index.php
    supplier/
        stampede/
            App/
                Http/
                    Request.php
                    View.php
    views/
        create.html
        hello.html
        thanks.html
    autoLoader.php
```
```:修正後の構成
stampede/
    app/
        Http/
            Controllers/
                Controller.php
                UserController.php
    public/
        .htaccess
        index.php
    supplier/
        stampede/
            App/
                Http/
                    Request.php
                    View.php
                    Dispatcher.php
                Http.php
    views/
        create.html
        hello.html
        thanks.html
    autoLoader.php
```
```bash
$ cd /opt/project/stampede/
$ mkdir -p app/Http/Controllers
$ touch app/Http/Controllers/Controller.php
$ touch app/Http/Controllers/UserController.php
$ touch supplier/stampede/App/Http.php
$ touch supplier/stampede/App/Http/Dispatcher.php
```

## .htaccess修正
```bash:.htaccess
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L] # ?url=$1 を追記
```

## Request.php修正
```php:Request.php
    /* 以下追記 */
    /**
     * 
     */
    public $controller = '';
    
    /**
     * 
     */
    public $action = '';

    /**
     * 
     */
    public $params = [];

    /**
     * 
     */
    public $uri = '';

    // 中略

    private function __construct()
    {
        $this->uri = $_GET['url'] ?? ''; // 追記
        $this->get = $_GET;
        $this->post = $_POST;
    }

```

## ディスパッチャークラス作成
```php:Dispatcher.php
<?php

namespace Stampede\App\Http;

use Stampede\App\Http\Request;

class Dispatcher
{
    /**
     * 
     * 
     */
    public static $instance = null;

    /**
     * 
     * 
     */
    private function __construct()
    {
    }

    /**
     * 
     * 
     */
    public static function getInstance()
    {
        if (is_null(self::$instance) === true) {
            self::$instance = new self;
        }
        return self::$instance;
    }

    /**
     * 
     * 
     */
    public function dispatch(Request $request)
    {
        list($controller, $action) = explode('/', $request->uri);

        $request->controller = 'App\Http\Controllers\\' . ucfirst($controller) . 'Controller';
        $request->action = $action;

        return;
    }
}
```

## Httpクラス作成
```php:Http.php
<?php

namespace Stampede\App;

use Stampede\App\Http\Request;
use Stampede\App\Http\Dispatcher;

class Http
{
    /**
     * 
     * @var \Config
     */
    private static $instance = null;

    /**
     * コンストラクタ
     * 
     */
    private function __construct()
    {
    }

    /**
     * 
     * 
     */
    public static function getInstance()
    {
        if (is_null(self::$instance) === true) {
            self::$instance = new self;
        }
        return self::$instance;
    }

    /**
     * 
     * 
     */
    public function bootstrap($view)
    {
        // リクエストの処理
        $request = Request::getInstance();

        // ルートディスパッチ
        $dispatcher = Dispatcher::getInstance();
        $dispatcher->dispatch($request);

        // メソッド実行
        $app = new $request->controller([
            'request' => $request,
            'view' => $view
        ]);
        $app->{$request->action}();
    }
}
```

## コントローラー（親）クラス作成
```php:Controller.php
<?php

namespace App\Http\Controllers;

class Controller
{
    /**
     * 
     */
    protected $request = null;

    /**
     * 
     */
    protected $view = null;
    
    /**
     * 
     * 
     */
    public function __construct($params)
    {
        $this->request = $params['request'];
        $this->view = $params['view'];
    }
}
```

## ユーザーコントローラー作成
```php:UserController.php
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * 
     * 
     */
    public function create()
    {
        $this->view->display('create.html');
    }

    /**
     * 
     * 
     */
    public function store()
    {
        header('Location: /stampede/user/thanks');
    }

    /**
     * 
     * 
     */
    public function thanks()
    {
        $this->view->display('thanks.html');
    }
}
```

## create.html修正
formタグのaction属性を修正
```html:create.html
        <main>
            <form class="gy-5" method="post" action="/stampede/user/store">
                <div class="mb-3 col-4">

```

## index.php修正
```php:index.php
<?php

ini_set('display_errors', "On");

require_once('../autoLoader.php');

use Stampede\App\Http;
use Stampede\App\Http\View;

//
$root = '/opt/project/stampede/';

// オートローダー起動
$autoloader = new autoLoader($root);
$autoloader->register();

// ビュークラスのインスタンス取得
$view = View::getInstance();

//
$app = Http::getInstance();
$app->bootstrap($view);

exit;
```

## ブラウザで確認
>https://192.168.56.110/stampede/user/create
---
前の記事
[[オレオレ08] フロントコントローラー](https://qiita.com/tonoaki_sato/items/35e9e0d1e909fc9d485c)
次の記事
[[オレオレ10] ヘルパー関数](https://qiita.com/tonoaki_sato/items/b17df476932eed2fc08e)