PHPでログイン機能を実装するチュートリアル #2


[前回](http://qiita.com/ShibuyaKosuke/items/f114ffccf441edb2b745)の続き。

1. [基本設計、ユーザーモデル](http://qiita.com/ShibuyaKosuke/items/f114ffccf441edb2b745)
2. [オートローダー](http://qiita.com/ShibuyaKosuke/items/6109810464a7293293bd)
3. [例外・ログ](http://qiita.com/ShibuyaKosuke/items/88b1305a4ff0c5f3e728)
4. [PDO シングルトン　SQLインジェクション](http://qiita.com/ShibuyaKosuke/items/094df7f399912ae7df56)
	* [汎用データベース・クラス作成](http://qiita.com/ShibuyaKosuke/items/8502492ac024362b528d)

5. [ユーザーモデルの作成](http://qiita.com/ShibuyaKosuke/items/81c556d836d70a29c5f3)
6. [クラスの継承](http://qiita.com/ShibuyaKosuke/items/490ffa6a92670cf6c644)
7. [テンプレート・クラスの実装](http://qiita.com/ShibuyaKosuke/items/803dc58a23601118942e)
8. [アカウントロック機能の実装](http://qiita.com/ShibuyaKosuke/items/e890becdb8193d3def05)
9. [メール送信機能の実装](http://qiita.com/ShibuyaKosuke/items/78c8673782ebbf51584b)
10. [アカウントロック解除機能の実装](http://qiita.com/ShibuyaKosuke/items/ee4b1896071eeca37628)
11. [CSRF対策](http://qiita.com/ShibuyaKosuke/items/8100e304e4447e44e98c)

##オートローディング機能の実装

とりあえず、不十分ではありますが、UserModel の実体ができましたので、[オートローディング](http://php.net/manual/ja/language.oop5.autoload.php)の機能を作成します。オートローディング機能を使うと、`new ClassName()` をするなど、クラスをインスタンス化したり、静的メソッドを実行する際に、毎回 `require` や `require_once` を記述しなくても済むようになります。

PHP5.3 以上で実装された[名前空間](http://php.net/manual/ja/language.namespaces.rationale.php)を上手に利用してこの機能を実装してみましょう。

前回、UserModel は以下のように作成しました。

```php:UserModel.class.php
<?php

final class UserModel
{

（中略）
```

名前空間を利用して、以下のように変更します。

```php:UserModel.class.php
<?php

namespace MyApp\model

final class UserModel
{

（中略）
```

classes/model/UserModel.class.php に配置しているファイルを自動的に require する機能を実装すれば良いわけです。

動作を検証しながら作成を進めます。
ブラウザで実行結果を確認しながら進めるので、webroot/index.php を作成します。

```php:webroot/index.php
<?php

$objUserModel = new MyApp\model\UserModel;
```

このように記述すると、通常、「そんなクラスねえ！」って怒られるわけですが、autoload を作っておくとよしなにやってくれるわけですね。

[リファレンス](http://php.net/manual/ja/language.oop5.autoload.php)にも書かれているように、

> spl_autoload_register() を使えば、より柔軟にクラスのオートロードができます。 そのため、今や __autoload() を使うことはおすすめできません。 将来のバージョンではこの機能が非推奨となり、削除されるかもしれません。 

なので、素直に、[spl_autoload_register 関数](http://php.net/manual/ja/function.spl-autoload-register.php) を利用します。

ついでに、どのファイルからも共通で読み込みして利用する common.php, 各種設定値を定義する config.php を作成しておきましょう。

以後、webroot 以下に作成するファイルには `require_once '../common.php';` を共通して記述することになります。

```php:webroot/index.php
<?php

require_once '../common.php';

$objUserModel = new MyApp\model\UserModel;
var_dump($objUserModel); //@todo 後で消す
```

`common.php` から `config.php` を読み込んでおけば、忘れることもありません。

```php:common.php
<?php
require_once 'config.php';

//本番の時には PRODUCTION に書き換える
define('MODE', DEVELOPPING);

//	開発モードのときにエラーを表示する
if (MODE === DEVELOPPING) {
	ini_set('display_errors', true);
	error_reporting(E_ALL);
} else {
	ini_set('display_errors', false);
}

require_once BASE_DIR . '/autoload.php';
spl_autoload_register('autoloader');
```



```php:config.php
<?php
/**
 * 開発モード
 */
define('DEVELOPPING', 1);

/**
 * 本番モード
 */
define('PRODUCTION', 2);

define('BASE_DIR', __DIR__);
```

```php:autoload.php
<?php
function autoloader($name)
{
	$arrToken = explode('\\', $name);
	$arrToken[0] = '/classes';
	$filename = BASE_DIR . implode("/", $arrToken) . '.class.php';
	if (file_exists($filename)) {
		require_once($filename);
	}
}
```

ここまでできれば、ブラウザから index.php にアクセスすると、

```php:index.php
object(MyApp\model\UserModel)[1]
  private '_userId' => null
  private '_password' => null
  private '_displayName' => null
  private '_email' => null
  private '_token' => null
  private '_loginFailureCount' => null
  private '_loginFailureDatetime' => null
  private '_deleteFlag' => null
```

上記のようにブラウザに表示されるはずです。

続きはまた後日…