Laravelを使ってアプリを開発中、maatwebsite/excelを用いて
CSV出力を行う機能を実装する際に、ハマったところがあるので共有です
mb_strpos() expectsってエラーが出た
Hoge.php
:
class Hoge extends Model
{
use \LaravelTreats\Model\Traits\HasCompositePrimaryKey;
protected $table = 'hoge';
protected $primaryKey = ['key1', 'key2'];
:
こんな感じで、データ抽出対象のテーブルのモデルを定義して
Export.php
:
use App\Models\Hoge;
class Export implements FromQuery, WithHeadings
{
use Exportable;
public function __construct($condition)
{
$this->conditions = $conditions;
}
public function headings(): array
{
return [
'カラム1',
'カラム2',
'カラム3',
];
}
public function query()
{
return Hoge::select(
'key1',
'key2',
'column'
)->where('key1', 'hoge');
}
:
こんな感じのすごくシンプルなクエリを組んだ
この状態で動作確認をすると、以下のようなエラーが発生する
local.ERROR: mb_strpos() expects parameter 1 to be string, array given {"exception":"[object] (ErrorException(code: 0): mb_strpos() expects parameter 1 to be string, array given at APP\vendor\\laravel\\framework\\src\\Illuminate\\Support\\Str.php:158)
[stacktrace]
#0 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(2, 'mb_strpos() exp...', 'APP...', 158, Array)
#1 APP\vendor\\laravel\\framework\\src\\Illuminate\\Support\\Str.php(158): mb_strpos(Array, '.')
#2 APP\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Model.php(363): Illuminate\\Support\\Str::contains(Array, '.')
#3 APP\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Model.php(1344): Illuminate\\Database\\Eloquent\\Model->qualifyColumn(Array)
#4 APP\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Builder.php(683): Illuminate\\Database\\Eloquent\\Model->getQualifiedKeyName()
#5 APP\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Concerns\\BuildsQueries.php(20): Illuminate\\Database\\Eloquent\\Builder->enforceOrderBy()
エラーの原因
さっきのエラーログをみると、Model.phpの363行目に何かがありそう。ってことで確認
/**
* Qualify the given column name by the model's table.
*
* @param string $column
* @return string
*/
public function qualifyColumn($column)
{
if (Str::contains($column, '.')) {
return $column;
}
return $this->getTable().'.'.$column;
}
Str::containsってところが悪いらしい。カラム名を受け取って ‘.’ があるかチェックしてる感じ
じゃぁ qualifyColumn って関数を呼び出している箇所を確認してみる。
/**
* Get the table qualified key name.
*
* @return string
*/
public function getQualifiedKeyName()
{
return $this->qualifyColumn($this->getKeyName());
}
$this->getKeyName() ここで、文字列を取得する想定で組まれてますねー
ところが、Hoge.phpのprimaryKeyは複合KEYなので、配列で飛んできます。。。
これがエラーの原因か!判明
対応
さて、どうやってこの問題に対応すればよいかを唸りながら考えました。
compositePrimaryKeyのトレイトも書いてるし、これでダメならどうしたものか。。と
結局、とても簡単な解決方法に辿り着きました。
モデルを使わなければイイ!
というわけで、以下のコードで解決です。
public function query()
{
return DB::table('hoge')
->select(
'key1',
'key2',
'column'
)
->where('key1', 'hoge');
}
どうしてもModelを使いたいって人は・・・
ごめんなさい。わかりません!