INDEX
Laravelを知らない中級(中年)プログラマーがマイグレーションファイルの仕組みを調べてみたけど全くわからない!
- その1「マイグレーションファイルを見てみよう」
- その2「$app['db']って何者?」
- その3「Repositoryクラス」
- その4「Larabelアプリケーションの初期化の流れ」
- その5「リポジトリの読込」
- その6「データベース接続」
- その7「スキーマビルダー」
- その8「migrate コマンドの実行」
- その9「Kernel::handle()」
スキーマビルダー
前回はデータベース接続について読みました。
Schema::getFacadeAccessor()
のstatic::$app['db']->connection()
の戻り値が接続を確立したConnection
インスタンスであるというところまでは読みました。続きを見てみましょう。
/**
* Get a schema builder instance for a connection.
*
* @param string|null $name
* @return \Illuminate\Database\Schema\Builder
*/
public static function connection($name)
{
return static::$app['db']->connection($name)->getSchemaBuilder();
}
Connection::getSchemaBuilder()
メソッドを見てみましょう。
/**
* Get a schema builder instance for the connection.
*
* @return \Illuminate\Database\Schema\Builder
*/
public function getSchemaBuilder()
{
if (is_null($this->schemaGrammar)) {
$this->useDefaultSchemaGrammar();
}
return new SchemaBuilder($this);
}
/**
* Set the schema grammar to the default implementation.
*
* @return void
*/
public function useDefaultSchemaGrammar()
{
$this->schemaGrammar = $this->getDefaultSchemaGrammar();
}
/**
* Get the default schema grammar instance.
*
* @return \Illuminate\Database\Schema\Grammars\Grammar
*/
protected function getDefaultSchemaGrammar()
{
//
}
Connection::getSchemaBuilder()
引数はありません。
戻り値はBuilder
インスタンスです。
$this->schemaGrammar
がnull
の場合、useDefaultSchemaGrammar()
をコールします。その先ではgetDefaultSchemaGrammar()
メソッドがコールされていますが、ロジックは空です。オーバーロードして使うのでしょうか。ちょっと意図がわかりません。
その後にSchemaBuilder
を引数に自身を渡して生成します。SchemaBuilder
はIlluminate\Database\Schema\Builder
が実体です。見てみましょう。
/**
* Create a new database Schema manager.
*
* @param \Illuminate\Database\Connection $connection
* @return void
*/
public function __construct(Connection $connection)
{
$this->connection = $connection;
$this->grammar = $connection->getSchemaGrammar();
}
/**
* Get the schema grammar used by the connection.
*
* @return \Illuminate\Database\Schema\Grammars\Grammar
*/
public function getSchemaGrammar()
{
return $this->schemaGrammar;
}
/**
* Set the schema grammar used by the connection.
*
* @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
* @return $this
*/
public function setSchemaGrammar(Schema\Grammars\Grammar $grammar)
{
$this->schemaGrammar = $grammar;
return $this;
}
Builder::__construct()
第一引数は
Connection
インスタンスです。
戻り値はありません。
Connection
インスタンスを受け取り、$this->connection
に代入します。
受け取ったConnection
のgetSchemaGrammar()
メソッドの返り値を$this->grammar
に代入しています。ただ、先程Connection::getSchemaBuilder()
を読んだ時に、$schemaGrammar
は設定されていませんでした。Builder
クラスには$grammar
を変更するインターフェースがコンストラクタ以外に見当たりません。Connection::setSchemaGrammar()
メソッドが用意されているので、何かのタイミングでConnection
インスタンスにセットした後にBuilder
インスタンスを生成するのかもしれません。とりあえず保留して読みすすめましょう。
/**
* Handle dynamic, static calls to the object.
*
* @param string $method
* @param array $args
* @return mixed
*
* @throws \RuntimeException
*/
public static function __callStatic($method, $args)
{
$instance = static::getFacadeRoot();
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
return $instance->$method(...$args);
}
Facade::__callStatic()
第一引数はストリング型でメソッド名です。
第二引数は配列型で引数をまとめたものです。
戻り値はmix
です。
さて、Schema::getFacadeAccessor()
の戻り値がBuilder
インスタンスであるというところまで読めました。
この記事の冒頭で叩いたコマンド、
php artisan make:migration create_customers_table --create=customers
によって生成されたマイグレーションファイルのup()
及びdown()
メソッドに記述されているstatic
メソッドSchema::create()
等はSchema
クラスが継承している抽象クラスFacade
の__callStatic()
がコールされ、その処理の中の$instance = static::getFacadeRoot()
のステップで$instance
には今まで追ってきてたどり着いたBuilder
インスタンス が代入されるはずです。
インスタンスの代入に失敗した場合、「A facade root has not been set.」というメッセージを添えて、例外RuntimeException
をスローします。
インスタンスが無事代入された場合は、引数として受け取ったメソッド名からコールするメソッドを割り出し、引数として受け取った引数配列を指定してコールします。最初に戻って生成されたマイグレーションファイルを見てみましょう。
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('customers', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
生成されたファイル::up()
引数、戻り値はありません。
つまり、Builder::create()
メソッドを第一引数としてテーブル名のストリング、第二引数としてクロージャーを指定してコールするという設計だということがわかりました。
すばらしい!何をやっているのかちょっとわかってしまいましたね!
本日は少し短いですが、次回からだんだん区切りが長くなってきそうです。
次回
次は実際にマイグレーションが実行される流れを見てみましょう!
楽しみですね!
続く☆