Laravelを知らない中級（中年）プログラマーがマイグレーションファイルの仕組みを調べてみたけど全くわからない！その６「データベース接続」

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

- [その１「マイグレーションファイルを見てみよう」](https://qiita.com/xioncc/items/1dcec2fbe3485b7e769a)
- [その２「$app['db']って何者？」](https://qiita.com/xioncc/items/cd4a46e5aca16b13174d)
- [その３「Repositoryクラス」](https://qiita.com/xioncc/items/1ce2132594c4596a73ae)
- [その４「Larabelアプリケーションの初期化の流れ」](https://qiita.com/xioncc/items/a17d7f905d4a5abf8103)
- [その５「リポジトリの読込」](https://qiita.com/xioncc/items/dc7df63c2487b02052f3)
- [その６「データベース接続」](https://qiita.com/xioncc/items/3cf9336eecd5f6905831)
- [その７「スキーマビルダー」](https://qiita.com/xioncc/items/04c95ce9ff6d0b7c9d44)
- [その８「migrate コマンドの実行」](https://qiita.com/xioncc/items/4a5166a0963991e33eb5)
- [その９「Kernel::handle()」](https://qiita.com/xioncc/items/07c1f0ba9b40bd230608)


## データベース接続
前回はリポジトリの読込を追いました。今日はデータベースとの接続を読んでみようと思います。

``PROJECT_ROOT/config/app.php``の``providers``には、``Illuminate\Database\DatabaseServiceProvider``が記述されています。このプロバイダーが初期化時に読み込まれ、``register()``メソッドがコールされます。

```php:Illuminate\Database\DatabaseServiceProvider&#x3a;&#x3a;register()|関連メソッド
/**
 * Register the service provider.
 *
 * @return void
 */
public function register()
{
    Model::clearBootedModels();
    $this->registerConnectionServices();
    $this->registerEloquentFactory();
    $this->registerQueueableEntityResolver();
}
/**
 * Register the primary database bindings.
 *
 * @return void
 */
protected function registerConnectionServices()
{
    // The connection factory is used to create the actual connection instances on
    // the database. We will inject the factory into the manager so that it may
    // make the connections while they are actually needed and not of before.
    $this->app->singleton('db.factory', function ($app) {
        return new ConnectionFactory($app);
    });
    // The database manager is used to resolve various connections, since multiple
    // connections might be managed. It also implements the connection resolver
    // interface which may be used by other components requiring connections.
    $this->app->singleton('db', function ($app) {
        return new DatabaseManager($app, $app['db.factory']);
    });
    $this->app->bind('db.connection', function ($app) {
        return $app['db']->connection();
    });
}
```

``register()``メソッドから、``registerConnectionServices()``メソッドがコールされ、そこで以下がシングルトン結合及びバインドされます。

- db.factory
- db
- db.connection

まず、``db.factory``として``Illumination/Database/Connectors/ConnectionFactory``をシングルトン結合します。次に``db``として、``Illumination/Database/DatabaseManager``を先程結合した``db.factory``を引数として渡して生成しシングルトン結合します。最後に``db.connection``として先程生成した``$app['db']``の``connection()``メソッドを使い生成した接続をバインドします。
これでいよいよデータベース接続の処理に入ります。

``DatabaseManager::makeConnection()``メソッドの戻り値の``return $this->factory->make($config, $name)``の``factory``の正体は、``$app['db.factory']``つまり、アプリケーションコンテナを引数として生成した``Illumination/Database/Connectors/ConnectionFactory``ということですね。では、``ConnectionFactory::make()``メソッドを考察します。なるべく実行される順番通りに追いかけていきます。

### ConnectionFactory::make() の処理の流れ

```php:ConnectionFactory&#x3a;&#x3a;make()|parseConfig()
    /**
     * Establish a PDO connection based on the configuration.
     *
     * @param  array  $config
     * @param  string|null  $name
     * @return \Illuminate\Database\Connection
     */
    public function make(array $config, $name = null)
    {
        $config = $this->parseConfig($config, $name);
        if (isset($config['read'])) {
            return $this->createReadWriteConnection($config);
        }
        return $this->createSingleConnection($config);
    }
    /**
     * Parse and prepare the database configuration.
     *
     * @param  array  $config
     * @param  string  $name
     * @return array
     */
    protected function parseConfig(array $config, $name)
    {
        return Arr::add(Arr::add($config, 'prefix', ''), 'name', $name);
    }
```

#### ConnectionFactory::make()
> 第一引数に接続情報配列を受け取っています。
第二引数にストリング型のデータベース名を受け取ります。デフォルトは``null``です。
戻り値は``Connection``インスタンスです。

``make()``の処理のはじめに、``$config`` に ``parseConfig()``メソッドの戻り値を入れています。``parseConfig``は受け取った接続情報に``prefix``に空文字を、``name``に接続名を加えて戻しています。次に接続情報に``read``が含まれているか判定し、含まれていた場合は``createReadWriteConnection()``メソッドを、含まれない場合は``createSingleConnection()``メソッドをコールしたものを戻します。

流れを追って一つずつメソッドを追っていきましょう。


```php:ConnectionFactory&#x3a;&#x3a;createReadWriteConnection()
    /**
     * Create a single database connection instance.
     *
     * @param  array  $config
     * @return \Illuminate\Database\Connection
     */
    protected function createReadWriteConnection(array $config)
    {
        $connection = $this->createSingleConnection($this->getWriteConfig($config));
        return $connection->setReadPdo($this->createReadPdo($config));
    }
```

#### ConnectionFactory::createReadWriteConnection()
> 引数は``$config``としてデータベース接続情報を配列型で受け取っています。
戻り値は``Connection``インスタンスです。

受け取った接続情報を引数に、``getWriteConfig()``をコールし、戻り値を引数に``createSingleConnection()``をコールし、戻り値の``Connection``インスタンスに対して``createReadPdo()``に接続情報を引数としてコールした戻り値を引数に``setReadPdo()``メソッドをコールした戻り値を返すというのがこのメソッドの流れです。

```php:ConnectionFactory&#x3a;&#x3a;getWriteConfig()
    /**
     * Get the read configuration for a read / write connection.
     *
     * @param  array  $config
     * @return array
     */
    protected function getWriteConfig(array $config)
    {
        return $this->mergeReadWriteConfig(
            $config, $this->getReadWriteConfig($config, 'write')
        );
    }
```

#### ConnectionFactory::getWriteConfig()
> 引数は``$config``としてデータベース接続情報を配列型で受け取っています。
戻り値は整形したデータベース接続情報の配列です。

接続情報を受け取り、``getReadWriteConfig()``メソッドの戻り値の配列を``mergeReadWriteConfig()``でマージして戻しています。

```php:ConnectionFactory&#x3a;&#x3a;getReadWriteConfig()
    /**
     * Get a read / write level configuration.
     *
     * @param  array  $config
     * @param  string  $type
     * @return array
     */
    protected function getReadWriteConfig(array $config, $type)
    {
        return isset($config[$type][0])
                        ? Arr::random($config[$type])
                        : $config[$type];
    }
```

#### ConnectionFactory::getReadWriteConfig()
> 第一引数は``$config``としてデータベース接続情報を配列型で受け取っています。
第二引数はストリング型で接続タイプを受け取っています。今回は 「``write``」 が入ります。
戻り値は整形したデータベース接続情報の配列です。

接続情報配列の接続タイプキー（今回は「``write``」） の０番目があるか調べています。存在していた場合は``Arr::random()``を``static``でコールしています。これは、「``write``」キーが配列である、つまり書き込み用接続が複数ある仕様の時の処理だと思われます。``Arr::random()``は``PHP``の``array_rand``を強化した``static``メソッドで、指定した配列から指定した数をランダム取得するものです。ソースはとてもかんたんですので興味があれば``Illuminate/Support/Arr.php``を参照してみると良いと思います。「``write``」キーの０番目が存在しない場合、つまり接続情報が１つの場合は「``write``」キーをそのまま返します。

```php:ConnectionFactory&#x3a;&#x3a;mergeReadWriteConfig()
    /**
     * Merge a configuration for a read / write connection.
     *
     * @param  array  $config
     * @param  array  $merge
     * @return array
     */
    protected function mergeReadWriteConfig(array $config, array $merge)
    {
        return Arr::except(array_merge($config, $merge), ['read', 'write']);
    }
```

#### ConnectionFactory::mergeReadWriteConfig()
> 第一引数に接続情報配列を受け取っています。
第二引数にマージする配列を受け取っています。
戻り値は整形したデータベース接続情報の配列です。

引数として受け取った配列を、``array_merge``したものを第一引数に、第二引数に ['``read``', '``write``'] として``Arr::except()``をコールしています。``Arr::except()``は第一引数で渡された配列を対象に、第二引数として渡された配列で指定されたキーの値を全て取り除いた結果を配列として返します。つまり、['``read``', '``write``'] の情報を削除したものを戻しています。
まだ読んでいる途中ですので、確証はありませんが、読み込みと書き込みの対象データベースが違う場合は、タイプ名をキーにして接続情報を保持していると思われます。接続時にそれを取得し、必要のない接続情報を削除し、接続に必要な情報のみ配列に直に代入するという処理なのだと思われます。書き込み、読み込みの接続は複数設定することが出来、接続ごとにランダムに対象が切り替わるのでしょう。

```php:ConnectionFactory&#x3a;&#x3a;createSingleConnection()
    /**
     * Create a single database connection instance.
     *
     * @param  array  $config
     * @return \Illuminate\Database\Connection
     */
    protected function createSingleConnection(array $config)
    {
        $pdo = $this->createPdoResolver($config);
        return $this->createConnection(
            $config['driver'], $pdo, $config['database'], $config['prefix'], $config
        );
    }
```

#### ConnectionFactory::createSingleConnection()
> 引数は``$config``としてデータベース接続情報を配列型で受け取っています。
戻り値は``Illuminate\Database\Connection``型です。

``createPdoResolver()``メソッドでPDO接続用``Connector``インスタンスを生成し、``createConnection()``メソッドで接続を確立した``Connection``インスタンスを戻します。

```php:ConnectionFactory&#x3a;&#x3a;createPdoResolver()
    /**
     * Create a new Closure that resolves to a PDO instance.
     *
     * @param  array  $config
     * @return \Closure
     */
    protected function createPdoResolver(array $config)
    {
        return array_key_exists('host', $config)
                            ? $this->createPdoResolverWithHosts($config)
                            : $this->createPdoResolverWithoutHosts($config);
    }
```

#### ConnectionFactory::createPdoResolver()
> 引数は``$config``としてデータベース接続情報を配列型で受け取っています。
戻り値はクロージャー型です。

受け取った接続情報配列のキーに「``host``」が存在するか検証し、存在する場合は``createPdoResolverWithHosts()``メソッド、存在しない場合は``createPdoResolverWithoutHosts``メソッドの戻り値のクロージャーを返します。
通常は「``host``」情報はあると思いますが、``SQLite``などの場合かもしれません。

```php:ConnectionFactory&#x3a;&#x3a;createPdoResolverWithHosts()|関連メソッド
    /**
     * Create a new Closure that resolves to a PDO instance with a specific host or an array of hosts.
     *
     * @param  array  $config
     * @return \Closure
     */
    protected function createPdoResolverWithHosts(array $config)
    {
        return function () use ($config) {
            foreach (Arr::shuffle($hosts = $this->parseHosts($config)) as $key => $host) {
                $config['host'] = $host;
                try {
                    return $this->createConnector($config)->connect($config);
                } catch (PDOException $e) {
                    continue;
                }
            }
            throw $e;
        };
    }
    /**
     * Parse the hosts configuration item into an array.
     *
     * @param  array  $config
     * @return array
     *
     * @throws \InvalidArgumentException
     */
    protected function parseHosts(array $config)
    {
        $hosts = Arr::wrap($config['host']);
        if (empty($hosts)) {
            throw new InvalidArgumentException('Database hosts array is empty.');
        }
        return $hosts;
    }
```

#### ConnectionFactory::createPdoResolverWithHosts()
> 引数は``$config``としてデータベース接続情報を配列型で受け取っています。
戻り値はクロージャー型です。

受け取った配列情報を``parseHosts()``を通して``Arr::wrap()``で配列型にキャストしたものを``Arr::shuffle()``で配列をシャッフルしたものを``foreach``で回し、接続情報の 「``host``」 に代入し、``createConnector()->connect()``で接続の確立を``TRY``したものを戻すというクロージャーを戻します。接続が確立できなかった場合は``PDOException``をスローします。``foreach``で回していますが、接続が成功したら``return``、失敗したら例外をスローするので１回しか回らないように見えます。``Arr``クラスの静的メソッドはソースはとてもかんたんですので興味があれば``Illuminate/Support/Arr.php``を参照してみると良いと思います。
これもホスト情報が配列で複数あった場合の処理と推測できます。

```php:ConnectionFactory&#x3a;&#x3a;createPdoResolverWithoutHosts()
    /**
     * Create a new Closure that resolves to a PDO instance where there is no configured host.
     *
     * @param  array  $config
     * @return \Closure
     */
    protected function createPdoResolverWithoutHosts(array $config)
    {
        return function () use ($config) {
            return $this->createConnector($config)->connect($config);
        };
    }
```

#### ConnectionFactory&#x3a;&#x3a;createPdoResolverWithoutHosts()
> 引数は``$config``としてデータベース接続情報を配列型で受け取っています。
戻り値はクロージャーです。

接続情報に 「``host``」が設定されていなかった場合、受け取った接続情報を引数に``createConnector()``メソッドをコールし、戻ってきた``Connecter``インスタンスに接続情報を引数に``connect()``メソッドをコールし戻ってきた``PDO``インスタンスを返すクロージャーを戻します。

```php:ConnectionFactory&#x3a;&#x3a;createConnector()
    /**
     * Create a connector instance based on the configuration.
     *
     * @param  array  $config
     * @return \Illuminate\Database\Connectors\ConnectorInterface
     *
     * @throws \InvalidArgumentException
     */
    public function createConnector(array $config)
    {
        if (! isset($config['driver'])) {
            throw new InvalidArgumentException('A driver must be specified.');
        }
        if ($this->container->bound($key = "db.connector.{$config['driver']}")) {
            return $this->container->make($key);
        }
        switch ($config['driver']) {
            case 'mysql':
                return new MySqlConnector;
            case 'pgsql':
                return new PostgresConnector;
            case 'sqlite':
                return new SQLiteConnector;
            case 'sqlsrv':
                return new SqlServerConnector;
        }
        throw new InvalidArgumentException("Unsupported driver [{$config['driver']}]");
    }
```

#### ConnectionFactory::createConnector()
> 引数は``$config``としてデータベース接続情報を配列型で受け取っています。
戻り値は``ConnectorInterface``インターフェースを実装したインスタンスです。

受け取った接続情報配列にキーが「``driver``」の情報が存在しなければ「``A driver must be specified.``」というメッセージを添えて例外``InvalidArgumentException``をスローします。
アプリケーションコンテナに接続ドライバがバインドされている場合はそれを返します。
接続ドライバの設定に合わせて適切なデータベース用のドライバを戻します。デフォルトでは``MySqlConnector``です。

```php:MySqlConnector&#x3a;&#x3a;connect()
    /**
     * Establish a database connection.
     *
     * @param  array  $config
     * @return \PDO
     */
    public function connect(array $config)
    {
        $dsn = $this->getDsn($config);
        $options = $this->getOptions($config);
        // We need to grab the PDO options that should be used while making the brand
        // new connection instance. The PDO options control various aspects of the
        // connection's behavior, and some might be specified by the developers.
        $connection = $this->createConnection($dsn, $config, $options);
        if (! empty($config['database'])) {
            $connection->exec("use `{$config['database']}`;");
        }
        $this->configureEncoding($connection, $config);
        // Next, we will check to see if a timezone has been specified in this config
        // and if it has we will issue a statement to modify the timezone with the
        // database. Setting this DB timezone is an optional configuration item.
        $this->configureTimezone($connection, $config);
        $this->setModes($connection, $config);
        return $connection;
    }
```

#### MySqlConnector::connect()
> 引数は$config としてデータベース接続情報を配列型で受け取っています。
戻り値はPDO インスタンスです。

各データベース用のドライバが用意されています。デフォルトの``MySQL``用のものを見てみましょう。範囲が広くなりすぎるので、詳細は別の機会に追いたいと思いますので、ざっと見てみます。
``DSN``とオプションをセットし接続情報と合わせて、``Connection::createConnection()``で``PDO``インスタンスを生成します。
設定情報にデータベース名があればそれを使うように設定します。
エンコードとタイムゾーンとモードを設定してて整えたインスタンスを戻します。

```php:Connector&#x3a;&#x3a;createConnection()
    /**
     * Create a new PDO connection.
     *
     * @param  string  $dsn
     * @param  array  $config
     * @param  array  $options
     * @return \PDO
     *
     * @throws \Exception
     */
    public function createConnection($dsn, array $config, array $options)
    {
        [$username, $password] = [
            $config['username'] ?? null, $config['password'] ?? null,
        ];
        try {
            return $this->createPdoConnection(
                $dsn, $username, $password, $options
            );
        } catch (Exception $e) {
            return $this->tryAgainIfCausedByLostConnection(
                $e, $dsn, $username, $password, $options
            );
        }
    }
```
#### Connector::createConnection()
> 第一引数はストリング型で``DSN``情報です。
第二引数は配列型で接続情報です。
第三引数は配列型でオプション情報です。
戻り値は``PDO``インスタンスです。

接続情報配列からユーザーネームとパスワードを取り出します。存在しなければ ``null`` です。
``createPdoConnection()``メソッドで接続を ``TRY`` し、成功の場合は戻り値を返します。
失敗した場合、コネクションロストの可能性を考慮し再度接続を試みます。

```php:Connector&#x3a;&#x3a;createPdoConnection()
    /**
     * Create a new PDO connection instance.
     *
     * @param  string  $dsn
     * @param  string  $username
     * @param  string  $password
     * @param  array  $options
     * @return \PDO
     */
    protected function createPdoConnection($dsn, $username, $password, $options)
    {
        if (class_exists(PDOConnection::class) && ! $this->isPersistentConnection($options)) {
            return new PDOConnection($dsn, $username, $password, $options);
        }
        return new PDO($dsn, $username, $password, $options);
    }
    /**
     * Determine if the connection is persistent.
     *
     * @param  array  $options
     * @return bool
     */
    protected function isPersistentConnection($options)
    {
        return isset($options[PDO::ATTR_PERSISTENT]) &&
               $options[PDO::ATTR_PERSISTENT];
    }
```

#### Connector::createPdoConnection()
> 第一引数はストリング型で``DSN``情報です。
第二引数はストリング型でユーザーネーム情報です。
第三引数はストリング型でパスワード情報です。
第四引数は配列型で接続情報です。
戻り値は``PDO``インスタンスです。

``PDOConnection``クラスが定義済みで、``PDO::ATTR_PERSISTENT``オプションが``true``であった場合、``PDOConnection``インスタンスを、そうでない場合は``PDO``インスタンスを生成して返します。``PDO::ATTR_PERSISTENT``はデータベースへの常時接続のパラメーターで、アクセス数が多いサービスなどで毎回接続を確立するよりも常時接続していた方がパフォーマンスを確保できるケースで利用するためのものです。
この、``PDOConnection``は``Doctrine\DBAL\Driver\PDOConnection``なのですが、通常インストール時には``composer``がインストールしていません。少し調べただけなので確実なことは言えませんが、GitHubのページも 404 Not found. となっています。

-----

同じメソッド名で混同しそうですが、``createSingleConnection()``で``PDO``インスタンスを生成した後の処理に続きます。

```php:ConnectionFactory&#x3a;&#x3a;createConnection()
    /**
     * Create a new connection instance.
     *
     * @param  string  $driver
     * @param  \PDO|\Closure  $connection
     * @param  string  $database
     * @param  string  $prefix
     * @param  array  $config
     * @return \Illuminate\Database\Connection
     *
     * @throws \InvalidArgumentException
     */
    protected function createConnection($driver, $connection, $database, $prefix = '', array $config = [])
    {
        if ($resolver = Connection::getResolver($driver)) {
            return $resolver($connection, $database, $prefix, $config);
        }
        switch ($driver) {
            case 'mysql':
                return new MySqlConnection($connection, $database, $prefix, $config);
            case 'pgsql':
                return new PostgresConnection($connection, $database, $prefix, $config);
            case 'sqlite':
                return new SQLiteConnection($connection, $database, $prefix, $config);
            case 'sqlsrv':
                return new SqlServerConnection($connection, $database, $prefix, $config);
        }
        throw new InvalidArgumentException("Unsupported driver [{$driver}]");
    }
```

#### ConnectionFactory::createConnection()
> 第一引数はストリング型で接続ドライバー名です。
第二引数は``PDO``インスタンスもしくはクロージャーです。
第三引数はストリング型でデータベース名です。
第四引数はストリング型でプレフィックスです。
第五引数は``$config``としてデータベース接続情報を配列型で受け取っています。
戻り値は``Connection``インスタンスです。

``createSingleConnection()``の処理の続きです。
``createSingleConnection()``には以下のように記述されていました。

```php
return $this->createConnection(
    $config['driver'], $pdo, $config['database'], $config['prefix'], $config
);
```

``Connection::getResolver()``メソッドの内容は以下です。

```php:Connection&#x3a;&#x3a;getResolver()
    public static function getResolver($driver)
    {
        return static::$resolvers[$driver] ?? null;
    }
```

受け取ったドライバー名が``static``変数``Connection::$resolvers[]``に存在する場合はそれを、存在しない場合は``null``を返します。ドライバーを拡張した時に使うのではないかと推測されます。
存在しない場合はドライバー名に従って各データベース用の``Connection``クラスを生成し戻します。
指定したドライバーがなければ「``Unsupported driver [ドライバー名]``」 というメッセージを添えて 例外``InvalidArgumentException``をスローします。
デフォルトでの対応ドライバーは、「``mysql``」「``pgsql``」「``sqlite``」「``sqlsrv``」です。
Laravelのデフォルト設定では生成されるのは``MySqlConnection``クラスです。このクラスにはコンストラクタがありません。``Connection``クラスを継承しているのでそちらを読んでみましょう。

```php:Connection&#x3a;&#x3a;__construct()
    /**
     * Create a new database connection instance.
     *
     * @param  \PDO|\Closure  $pdo
     * @param  string  $database
     * @param  string  $tablePrefix
     * @param  array  $config
     * @return void
     */
    public function __construct($pdo, $database = '', $tablePrefix = '', array $config = [])
    {
        $this->pdo = $pdo;
        // First we will setup the default properties. We keep track of the DB
        // name we are connected to since it is needed when some reflective
        // type commands are run such as checking whether a table exists.
        $this->database = $database;
        $this->tablePrefix = $tablePrefix;
        $this->config = $config;
        // We need to initialize a query grammar and the query post processors
        // which are both very important parts of the database abstractions
        // so we initialize these to their default values while starting.
        $this->useDefaultQueryGrammar();
        $this->useDefaultPostProcessor();
    }
```

#### Connection::__construct()
> 第一引数は``PDO``インスタンス、若しくは``PDO``インスタンスを返すクロージャーです。
第二引数はストリング型でデータベース名です。
第三引数はストリング型でプレフィックスです。
第四引数は配列型で接続情報です。
戻り値はありません。

受け取った引数を変数にセットし、``useDefaultQueryGrammar()``メソッドと``useDefaultPostProcessor()``メソッドをコールします。

```php:Connection&#x3a;&#x3a;useDefaultQueryGrammar()|関連メソッド
    /**
     * Set the query grammar to the default implementation.
     *
     * @return void
     */
    public function useDefaultQueryGrammar()
    {
        $this->queryGrammar = $this->getDefaultQueryGrammar();
    }
    /**
     * Get the default query grammar instance.
     *
     * @return \Illuminate\Database\Query\Grammars\Grammar
     */
    protected function getDefaultQueryGrammar()
    {
        return new QueryGrammar;
    }
```

#### Connection::useDefaultQueryGrammar()
> 引数、戻り値はありません。

``useDefaultQueryGrammar()``メソッドは``$this->queryGrammar``に``getDefaultQueryGrammar()``メソッドの戻り値を代入します。
``getDefaultQueryGrammar()``メソッドは``QueryGrammar``インスタンスを生成し戻します。
``QueryGrammar``の実体は``Illuminate\Database\Query\Grammars\Grammar``です。
``Illuminate\Database\Grammar``抽象クラスを継承しています。これはおそらくSQLを生成するための各種メソッドをまとめたものと推測できます。

```php:Connection&#x3a;&#x3a;useDefaultPostProcessor()|関連メソッド
    /**
     * Set the query post processor to the default implementation.
     *
     * @return void
     */
    public function useDefaultPostProcessor()
    {
        $this->postProcessor = $this->getDefaultPostProcessor();
    }
    /**
     * Get the default post processor instance.
     *
     * @return \Illuminate\Database\Query\Processors\Processor
     */
    protected function getDefaultPostProcessor()
    {
        return new Processor;
    }
```

#### Connection::useDefaultPostProcessor()
> 引数、戻り値はありません。

``useDefaultPostProcessor()``メソッドは``$this->postProcessor``に``getDefaultPostProcessor()``メソッドの戻り値を代入します。
``getDefaultPostProcessor()``メソッドは``Processor``インスタンスを生成し戻します。
``Processor``の実体は``Illuminate\Database\Query\Processors\Processor``です。おそらくSQLを処理するものと推測できます。あとで出てくると思いますので、その時に読みましょう。

----

``ConnectionFactory::createConnection()``メソッドは、接続の確立後に設定するパラメーターやクエリを実行するための準備などをする役割のようです。以上で``ConnectionFactory::createSingleConnection()``メソッドの処理が読み終わりました。``ConnectionFactory::createReadWriteConnection()``の最後の処理を読んでみましょう。以下のように記述されていました。

```php
return $connection->setReadPdo($this->createReadPdo($config));
```

``createReadPdo()``から見てみましょう。

```php:ConnectionFactory&#x3a;&#x3a;createReadPdo()|関連メソッド
    /**
     * Create a new PDO instance for reading.
     *
     * @param  array  $config
     * @return \Closure
     */
    protected function createReadPdo(array $config)
    {
        return $this->createPdoResolver($this->getReadConfig($config));
    }
    /**
     * Get the read configuration for a read / write connection.
     *
     * @param  array  $config
     * @return array
     */
    protected function getReadConfig(array $config)
    {
        return $this->mergeReadWriteConfig(
            $config, $this->getReadWriteConfig($config, 'read')
        );
    }
```

#### ConnectionFactory::createReadPdo()
> 引数は``$config``としてデータベース接続情報を配列型で受け取っています。
戻り値はクロージャーです。

``createPdoResolver()``メソッドは先程追ったのを覚えていると思います。接続情報にホスト情報が含まれているか調べ、``PDO``インスタンスを戻すクロージャーを返します。``ConnectionFactory::createReadWriteConnection()``メソッドはこの処理の前に書き込み接続の設定を使い接続を確立しています。
``getReadConfig()``メソッドを見てみましょう。見覚えのある記述です。``getWriteConfig()``メソッドの第二引数を「``read``」に変えただけのものですね。読込用の接続情報以外を削除し配列を整える処理をしています。
読込接続用の設定で接続を確立するクロージャーを作り返す処理ということです。では、最後に``setReadPdo()``を見てみましょう。

```php:Connection::setReadPdo()
    /**
     * Set the PDO connection used for reading.
     *
     * @param  \PDO|\Closure|null  $pdo
     * @return $this
     */
    public function setReadPdo($pdo)
    {
        $this->readPdo = $pdo;
        return $this;
    }
```

#### Connection::setReadPdo()
> 第一引数は``PDO``インスタンス若しくはクロージャーもしくは``null``です。
戻り値は``$this``です。

受け取った引数を``readPdo``に代入しています。

このメソッドをコールしたのはすでに書込接続が確立された``Connection``インスタンスで、接続は``pdo``に代入されています。書込時は``pdo``読み込み時は``readPdo``と接続を切り替える仕様だろうと推測できます。

-----

以上で、``ConnectionFactory::make()``の処理の流れを読み終わりました。
データベースに接続する仕組みが少しわかりましたね！

## 次回
データベースの接続まで読めましたので、次回は本筋に戻ってスキーマビルダーについて追っていきたいと思います。


続く☆