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()メソッドを第一引数としてテーブル名のストリング、第二引数としてクロージャーを指定してコールするという設計だということがわかりました。
すばらしい!何をやっているのかちょっとわかってしまいましたね!
本日は少し短いですが、次回からだんだん区切りが長くなってきそうです。
次回
次は実際にマイグレーションが実行される流れを見てみましょう!
楽しみですね!
続く☆