Edited at

【Laravel】allメソッドを使うとtoSqlメソッドが使えない

クエリビルダを使用すると、toSqlメソッドで実行されるSQLを取得することができます。

しかし、City::all()のようにallメソッドを使用した場合は、toSqlメソッドを使うことができません。

以下のエラーが出ます。

Method Illuminate\Database\Eloquent\Collection::toSql does not exist.

エラーメッセージの通りなのですが、原因を探ってみました。


allメソッドの場合


test.php

$sql_all = City::all();

var_dump(get_class($sql_all));
// エラー発生
var_dump($sql_all->toSql());

オブジェクトのクラス名を取得すると、Illuminate\Database\Eloquent\Collectionクラスが使用されていることがわかります。

addメソッド自身は、スーパークラスであるSupport\Collectionクラスに定義されています。

しかし、両クラスともtoSqlメソッドが定義されていません。

これが原因でした。


Illuminate\Support\Collection.php

/**

* Get all of the items in the collection.
*
* @return array
*/

public function all()
{
return $this->items;
}

さらに、getメソッドを使用した場合も同じエラーが出ます。


test.php

$sql_builder = DB::table('city')->get();

var_dump(get_class($sql_builder));
// エラー発生
var_dump($sql_builder->toSql());

上記のコードではEloquentを使用していないので、オブジェクトのクラス名はIlluminate\Support\Collectionになります。

エラーの理由は上記と同じです。


toSqlメソッドの場所

当のtoSqlメソッドが定義されているクラスは、Builderクラスになります。


Illuminate\Database\Query\Builder.php

/**

* Get the SQL representation of the query.
*
* @return string
*/

public function toSql()
{
return $this->grammar->compileSelect($this);
}


whereメソッドの場合

whereメソッドを使用する場合は、toSqlメソッドが使用できます。

オブジェクトのクラス名を確認すると、lluminate\Database\Eloquent\Builderクラスが使用されていると確認できます。

これはtoSqlメソッドが定義されているクラスと同じです。


test.php

$sql_where = City::where('Name', '=', 'Kabul');

var_dump(get_class($sql_where));
// 出力される
var_dump($sql_where->toSql());

コアファイルを読む良いきっかけになりました。