クエリビルダを使用すると、toSqlメソッド
で実行されるSQLを取得することができます。
しかし、City::all()
のようにallメソッドを使用した場合は、toSqlメソッドを使うことができません。
以下のエラーが出ます。
Method Illuminate\Database\Eloquent\Collection::toSql does not exist.
エラーメッセージの通りなのですが、原因を探ってみました。
allメソッドの場合
$sql_all = City::all();
var_dump(get_class($sql_all));
// エラー発生
var_dump($sql_all->toSql());
オブジェクトのクラス名を取得すると、Illuminate\Database\Eloquent\Collection
クラスが使用されていることがわかります。
addメソッド自身は、スーパークラスであるSupport\Collection
クラスに定義されています。
しかし、両クラスともtoSqlメソッドが定義されていません。
これが原因でした。
/**
* Get all of the items in the collection.
*
* @return array
*/
public function all()
{
return $this->items;
}
さらに、getメソッド
を使用した場合も同じエラーが出ます。
$sql_builder = DB::table('city')->get();
var_dump(get_class($sql_builder));
// エラー発生
var_dump($sql_builder->toSql());
上記のコードではEloquentを使用していないので、オブジェクトのクラス名はIlluminate\Support\Collection
になります。
エラーの理由は上記と同じです。
toSqlメソッドの場所
当のtoSqlメソッドが定義されているクラスは、Builderクラスになります。
/**
* 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メソッドが定義されているクラスと同じです。
$sql_where = City::where('Name', '=', 'Kabul');
var_dump(get_class($sql_where));
// 出力される
var_dump($sql_where->toSql());
コアファイルを読む良いきっかけになりました。