Laravel Reading Alias

プロジェクトを作った時に作られるファイルを眺めていて、モデルを見ていると

class User extends Eloquent implements UserInterface, RemindableInterface

ですと。

Eloquentってなんだ。

laravelが独自のORMのことをEloquent ORMって呼んでいるのはわかる。(http://laravel.com/docs/eloquent)

しかし、Eloquentなんていうクラスは存在しない。

なのにextendsしている。なぜ?ということで気になったので見てみる

上述のEloquent ORMのページで、User Modelが使っているメソッドや自動生成されているUser Modelが実装しているメンバ変数($tableとか$hidden)を探してみるとどうやらModelというクラスにありそう。

探してみるとapp/config/app.phpに気になる記述を発見。

    'aliases' => array(

        'App'             => 'Illuminate\Support\Facades\App',
        'Artisan'         => 'Illuminate\Support\Facades\Artisan',
        'Auth'            => 'Illuminate\Support\Facades\Auth',
        'Blade'           => 'Illuminate\Support\Facades\Blade',
        'Cache'           => 'Illuminate\Support\Facades\Cache',
        'ClassLoader'     => 'Illuminate\Support\ClassLoader',
        'Config'          => 'Illuminate\Support\Facades\Config',
        'Controller'      => 'Illuminate\Routing\Controller',
        'Cookie'          => 'Illuminate\Support\Facades\Cookie',
        'Crypt'           => 'Illuminate\Support\Facades\Crypt',
        'DB'              => 'Illuminate\Support\Facades\DB',
        'Eloquent'        => 'Illuminate\Database\Eloquent\Model',
        'Event'           => 'Illuminate\Support\Facades\Event',
        'File'            => 'Illuminate\Support\Facades\File',
        'Form'            => 'Illuminate\Support\Facades\Form',
        'Hash'            => 'Illuminate\Support\Facades\Hash',
        'HTML'            => 'Illuminate\Support\Facades\HTML',
        'Input'           => 'Illuminate\Support\Facades\Input',
        'Lang'            => 'Illuminate\Support\Facades\Lang',
        'Log'             => 'Illuminate\Support\Facades\Log',
        'Mail'            => 'Illuminate\Support\Facades\Mail',
        'Paginator'       => 'Illuminate\Support\Facades\Paginator',
        'Password'        => 'Illuminate\Support\Facades\Password',
        'Queue'           => 'Illuminate\Support\Facades\Queue',
        'Redirect'        => 'Illuminate\Support\Facades\Redirect',
        'Redis'           => 'Illuminate\Support\Facades\Redis',
        'Request'         => 'Illuminate\Support\Facades\Request',
        'Response'        => 'Illuminate\Support\Facades\Response',
        'Route'           => 'Illuminate\Support\Facades\Route',
        'Schema'          => 'Illuminate\Support\Facades\Schema',
        'Seeder'          => 'Illuminate\Database\Seeder',
        'Session'         => 'Illuminate\Support\Facades\Session',
        'SoftDeletingTrait' => 'Illuminate\Database\Eloquent\SoftDeletingTrait',
        'SSH'             => 'Illuminate\Support\Facades\SSH',
        'Str'             => 'Illuminate\Support\Str',
        'URL'             => 'Illuminate\Support\Facades\URL',
        'Validator'       => 'Illuminate\Support\Facades\Validator',
        'View'            => 'Illuminate\Support\Facades\View',
    ),

aliasesとな

なるほどEloquentをModelのaliasにしていそうな感じがする。

しかしどうやっているのか。ちょっと見てみる

$config['aliases]'を使っているのはlaravel/framework/src/Illuminate/Foundation/start.php

https://github.com/laravel/framework/blob/4.2/src/Illuminate/Foundation/start.php#L180#L182

$aliases = $config['aliases'];

AliasLoader::getInstance($aliases)->register();

(githublaravel/laravelでFoundation/start.phpが見つからず、この段階でlaravelがframeworkとかdatabaseとかいくつかのモジュールで構成されていることに気付いた)

さて、AliasLoaderの中で、autoload関数として自分自身のload関数を登録しています。

https://github.com/laravel/framework/blob/4.2/src/Illuminate/Foundation/AliasLoader.php#L100

    protected function prependToLoaderStack()
    {
        spl_autoload_register(array($this, 'load'), true, true);
    }

で、loadの中でclass_aliasというのを呼び出しています。(http://php.net/manual/ja/function.class-alias.php)

    public function load($alias)
    {
        if (isset($this->aliases[$alias]))
        {
            return class_alias($this->aliases[$alias], $alias);
        }
    }

PHPは嗜む程度なのでこれは初めて知った。

これでEloquentという存在しないクラスをextendsしている謎は解けました

Modelと読み替えてコードを読めば良いということでした。