FuelPHP でシンプルメンテナンスモード


動かしたバージョン: Ver. 1.7.1

[自分用に書いた](http://peketamin.hatenablog.jp/entry/2013/07/08/fuelphp_%E3%81%A7%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%83%A1%E3%83%B3%E3%83%86%E3%83%8A%E3%83%B3%E3%82%B9%E3%83%A2%E3%83%BC%E3%83%89)記事をまとめ直し

- DB を一時的に止めたり、メールの飛び先を変えたり、内部の処理を大きく変える時に、メンテナンス画面を出して、ユーザーの行動をそこでストップしたかったので書きました (蓄積データへの意図しない追記・変更を防ぐため)
- ちゃんとやる場合は、コントローラーとルーターをちゃんと書いてる方もいるような気もしています。
- 知り合いは、そっちではなく、 *nginx* や *Apache* の conf の方で切り替えてました (知り合いは Django 使い)。
- *Laravel* 用に書いた記事は[こちら](http://peketamin.hatenablog.jp/entry/2013/07/03/laravel4_%E3%81%AE%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%83%A1%E3%83%B3%E3%83%86%E3%83%8A%E3%83%B3%E3%82%B9%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AE%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB)


## 出来る事 ##

- どの URL にアクセスしてもリダイレクトなしにメンテナンス画面を表示する
- HTTP ステータスコード 503 を返す
- コントローラーを書かずに済ませる
  - コンフィグとビュー (テンプレート) だけ書く
  - `config/routes.php`, `public/index.php` を変更しない


## メンテナンス画面表示処理のブロックで出来ない事 ##

- `\Request::active()` とかは取得出来ない (*Uri::segment()* も)
- コントローラーまで処理が渡らないので、コントローラーが必要な処理は出来ない
- たぶん、IP ベースでスルーさせる処理とか、 **簡単なことしか出来ない** と思う
  (なので「 **シンプル** メンテナンスモード」)

凝った制御が必要な場合は、別の仕組みが必要…。


## 用意するもの ##

1. メンテナンスフラグ用 *config* ファイルを作成。
2. `fuel/app/config/event.php` というパスでファイルを作成。

要は *config* ファイルを 2 つ作成する。


### メンテナンスフラグ用 config ファイル ###

メンテナンスモードの切り替えは *config* ファイルでスイッチしようと思います。
(メンテナンスモードのフラグとなるファイルを touch してスイッチする方法もあると思いますが、今回は array の値でやります…。)

```php
<?php
return array(
    'active' => true,
);
```

みたいな内容で、 `fuel/app/config/app/maintenance.php` などのパスに置いておく。


### fuel/app/config/event.php を作成 ###

FuelPHP フレームワーク側には、中枢のコードに直接手を入れずに、
任意の処理を介入させるためのイベントというフックのポイントが用意されているみたいで、
公式ドキュメントは下記。

オリジナル: [Event - Classes - FuelPHP Documentation](http://fuelphp.com/docs/classes/event.html#/system_events)
日本語翻訳版: [Event - クラス - FuelPHP ドキュメント](http://fuelphp.jp/docs/1.8/classes/event.html)

上記ページの、 *Example 	In app/config/event.php* の内容を参考に作ります。


#### コード ####

```php
<?php

\Config::load('app/maintenance.php', 'maintenance');
$maintenance_active = \Config::get('maintenance.active');

return array(
    'fuelphp' => array(
        'app_created' => function()
        {
            // After FuelPHP initialised
        },
        'request_created' => function() use ($maintenance_active)
        {
            // After Request forged
            if ($maintenance_active)
            {
                $data = array(
                    'title' => 'Maintenance 503 (メンテナンス 503)',
                    'content' => render('503'),
                );
                // Set a HTTP 503 output header
                return \Response::forge(render('template', $data, false), 503)->send(true);
            }
        },
        'request_started' => function() use ($maintenance_active)
        {
            // Request is requested
            if ($maintenance_active)
            {
                exit;
            }
        },
        'controller_started' => function()
        {
            // Before controllers before() method called
        },
        'controller_finished' => function()
        {
            // After controllers after() method called
        },
        'response_created' => function()
        {
            // After Response forged
        },
        'request_finished' => function()
        {
            // Request is complete and Response received
        },
        'shutdown' => function()
        {
            // Output has been send out
        },
    ),
);
```


上から順に各イベントが実行されるとすると、
「そんなところで、 *exit* したら、後続の、本来必要な終了処理とかも含めて強制中断しちゃう？」
とも思ったのですが、 `response_created` 以降のイベントは普通に動いてました。
(多分)
(各イベント中で *echo 1234;* して簡易的にチェックしました)
(ソースはまだ追ってないです、スミマセン…)

冒頭で `\Config::load()` が実行されてることについて何らかのディスがあるかも知れません。
とりあえず以上。

追記 2014/07/07
----------

もう少し手を入れた内容を書いた。
[(改修) FuelPHP でシンプルメンテナンスモード: 特定 URL や特定 IP 許可 - Qiita](http://qiita.com/peketamin/items/e47abef644475074ab2f)