INDEX
Laravelを知らない中級(中年)プログラマーがマイグレーションファイルの仕組みを調べてみたけど全くわからない!
- その1「マイグレーションファイルを見てみよう」
- その2「$app['db']って何者?」
- その3「Repositoryクラス」
- その4「Larabelアプリケーションの初期化の流れ」
- その5「リポジトリの読込」
- その6「データベース接続」
- その7「スキーマビルダー」
- その8「migrate コマンドの実行」
Repositoryクラス
前回DatabaseManager
の$this->app['config']['database.default']
ってなんだろうというところまで読みました。それを追ってみましょう。
DatabaseManager
クラスのコンストラクタは以下のように定義されています。
/**
* Create a new database manager instance.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @param \Illuminate\Database\Connectors\ConnectionFactory $factory
* @return void
*/
public function __construct($app, ConnectionFactory $factory)
{
$this->app = $app;
$this->factory = $factory;
$this->reconnector = function ($connection) {
$this->reconnect($connection->getName());
};
}
$this->app
には生成される時の第一引数が代入されています。コードヒントにはIlluminate\Contracts\Foundation\Application
とあります。生成する時の手順はまだはっきりとわかりませんが、$this->app
がApplication
インスタンスなのは確かなようです。
前回のコードリーディングでApplication
クラスはContainer
クラスを継承していて、ArrayAccess
インターフェースを実装してることがわかっています。配列としてアクセスすると名前解決され指定されたクラスのインスタンスが渡されます。
エイリアス設定を参照すると、実体は Illuminate\Contracts\Config\Repository
インターフェースを実装した Illuminate\Config\Repository
だということがわかります。見てみましょう!
<?php
namespace Illuminate\Config;
use ArrayAccess;
use Illuminate\Contracts\Config\Repository as ConfigContract;
use Illuminate\Support\Arr;
class Repository implements ArrayAccess, ConfigContract
{
/**
* All of the configuration items.
*
* @var array
*/
protected $items = [];
/**
* Create a new configuration repository.
*
* @param array $items
* @return void
*/
public function __construct(array $items = [])
{
$this->items = $items;
}
/* ========== 中略 ========== */
/**
* Get the specified configuration value.
*
* @param array|string $key
* @param mixed $default
* @return mixed
*/
public function get($key, $default = null)
{
if (is_array($key)) {
return $this->getMany($key);
}
return Arr::get($this->items, $key, $default);
}
/* ========== 中略 ========== */
/**
* Get a configuration option.
*
* @param string $key
* @return mixed
*/
public function offsetGet($key)
{
return $this->get($key);
}
/* ========== 中略 ========== */
}
このクラスもArrayAccess
が実装されています。offsetGet()
メソッドはreturn $this->get($key)
と定義されています。配列で渡された時の処理を挟んでいますが、実行するのはreturn Arr::get($this->items, $key, $default)
のようです。Arr
クラスを見てみましょう。
Arr::get
Arr
クラスの定義ファイルはIlluminate/Support/Arr.php
です。get()
メソッドは以下のように定義されています。
/**
* Get an item from an array using "dot" notation.
*
* @param \ArrayAccess|array $array
* @param string|int|null $key
* @param mixed $default
* @return mixed
*/
public static function get($array, $key, $default = null)
{
if (! static::accessible($array)) {
return value($default);
}
if (is_null($key)) {
return $array;
}
if (static::exists($array, $key)) {
return $array[$key];
}
if (strpos($key, '.') === false) {
return $array[$key] ?? value($default);
}
foreach (explode('.', $key) as $segment) {
if (static::accessible($array) && static::exists($array, $segment)) {
$array = $array[$segment];
} else {
return value($default);
}
}
return $array;
}
/**
* Determine whether the given value is array accessible.
*
* @param mixed $value
* @return bool
*/
public static function accessible($value)
{
return is_array($value) || $value instanceof ArrayAccess;
}
/**
* Determine if the given key exists in the provided array.
*
* @param \ArrayAccess|array $array
* @param string|int $key
* @return bool
*/
public static function exists($array, $key)
{
if ($array instanceof ArrayAccess) {
return $array->offsetExists($key);
}
return array_key_exists($key, $array);
}
説明の通り、「ドット」表記を使用して配列から値を取得するメソッドのようです。第一引数にArrayAccess
か配列を、第二引数にキー、第三引数にデフォルト値を受け取ります。受け取った第一引数がArrayAccess
のインスタンスでなく且つ配列でもないものならデフォルト値を戻す、キーがnull
なら第一引数をそのまま戻す。第一引数がArrayAccess
で且つ、その中に第二引数がオフセットとして存在する場合、若しくは第一引数が配列であり且つ第二引数がキーとして存在する場合は第一引数の第二引数オフセット、もしくは第一引数配列のキーが第二引数の値を戻す。第二引数に「.
」が含まれていない場合は、第一引数の第二引数オフセットもしくは第一引数配列にキーが第二引数の値があればそれを、なければ第三引数デフォルト値を戻す。冗長な部分があるきがしますが、気にせず次に行きましょう。
ここからがメインです。キーを「.
」で分割し配列にしforeach()
で回します。 「.
」で区切られた文字列の値で第一引数をネストして、オフセットであるか、配列のキーに存在するかを確認していきます。正当性の確認が取れた場合第一引数から第二引数の「.」記法で指定されたオブジェクト若しくは配列を戻し、正当性が取れない場合はデフォルト値を戻します。 まぁ、平たく言えばドットシンタックスを使ってオブジェクトか配列を階層構造を追って取得する感じでしょうか。 本題に戻りましょう。
$this->items
Arr::get()
の挙動は理解できましたがこれが引数として受け取る$array
がまだ追えていません。config
の定数なのではないかと予想はできますが、一応追ってみましょう。Arr::get
を呼び出しているRepository::get()
には、Arr::get($this->items, $key, $default)
とあります。$this->items
はRepository
クラスのコンストラクタでセットされるもののようです。このインスタンスはDatabaseManager
インスタンスの$this->app['config']
で、$this->app
はDatabaseManager::__construct
で$app
がセットされています。つまり Laravelアプリケーション自体で初期化したものであるだろうと推測できます。
次回
次回はLarabelアプリケーションの初期設定の流れを追ってみましょう。