0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravelを知らない中級(中年)プログラマーがマイグレーションファイルの仕組みを調べてみたけど全くわからない!その3「Repositoryクラス」

Last updated at Posted at 2020-04-14

INDEX

Laravelを知らない中級(中年)プログラマーがマイグレーションファイルの仕組みを調べてみたけど全くわからない!

Repositoryクラス

前回DatabaseManager$this->app['config']['database.default']ってなんだろうというところまで読みました。それを追ってみましょう。
DatabaseManagerクラスのコンストラクタは以下のように定義されています。

Illuminate/Database/DatabaseManager::__construct
    /**
     * 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->appApplicationインスタンスなのは確かなようです。
前回のコードリーディングでApplicationクラスはContainerクラスを継承していて、ArrayAccessインターフェースを実装してることがわかっています。配列としてアクセスすると名前解決され指定されたクラスのインスタンスが渡されます。
エイリアス設定を参照すると、実体は Illuminate\Contracts\Config\Repository インターフェースを実装した Illuminate\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()メソッドは以下のように定義されています。

Illuminate/Support/Arr::get()|accessible()
/**
 * 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->itemsRepositoryクラスのコンストラクタでセットされるもののようです。このインスタンスはDatabaseManagerインスタンスの$this->app['config']で、$this->appDatabaseManager::__construct$appがセットされています。つまり Laravelアプリケーション自体で初期化したものであるだろうと推測できます。

次回

次回はLarabelアプリケーションの初期設定の流れを追ってみましょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?