推荐使用 spatie/laravel-scout-elasticsearch(Laravel 10+/PHP 8.1+),需显式配置 hosts、index,重写 toSearchableArray() 控制字段,注意 ES 与数据库数据不同步。

Scout 默认不支持 Elasticsearch,直接配 SCOUT_DRIVER=elasticsearch 会报 Driver [elasticsearch] not supported 错误——必须装第三方扩展包,不能跳过。
选哪个扩展包?看 Laravel 和 PHP 版本
不是所有 laravel-scout-elastic 都能用,版本错配是高频报错根源:
-
spatie/laravel-scout-elasticsearch:推荐用于 Laravel 10+、PHP 8.1+,底层用elasticsearch-phpv8,主动维护中,文档清晰 -
tamayo/laravel-scout-elastic:Laravel 5–8 兼容,但已多年未更新,PHP 8.2+ 下可能触发Deprecated: Return type of ...类警告 -
matchish/laravel-scout-elasticsearch:支持多模型搜索(如同时搜User和Post),但索引命名逻辑较隐晦,toSearchableArray()返回空字段时易静默失败
如果你用的是 Laravel 10 或 11,只装 spatie/laravel-scout-elasticsearch,别混用其他 Scout 扩展。
配置不只改 driver,hosts 和 index 必须显式声明
很多人卡在 php artisan scout:import 报 cURL error 7: Failed to connect,问题往往出在配置没真正生效:
- 运行
php artisan vendor:publish --provider="Spatie\Searchable\SearchableServiceProvider"(注意不是 Scout 自带的 publish 命令) -
config/scout.php里必须有完整的elasticsearch块,不能只靠 env 变量:'elasticsearch' => [ 'index' => env('ELASTICSEARCH_INDEX', 'laravel'), 'hosts' => [env('ELASTICSEARCH_HOST', 'http://localhost:9200')], ], -
.env中至少写明:SCOUT_DRIVER=elasticsearch ELASTICSEARCH_HOST=http://localhost:9200 ELASTICSEARCH_INDEX=posts
(别漏掉ELASTICSEARCH_INDEX,否则默认用laravel,和你建的索引名对不上)
toSearchableArray() 不是可选项,是字段控制开关
搜 User::search('john')->get() 返回空?大概率是没重写 toSearchableArray(),Scout 默认只同步 $fillable 字段,而 name 往往是访问器或来自关联模型:
- 必须显式返回你要搜的字段,比如:
public function toSearchableArray() { return [ 'id' => $this->id, 'name' => $this->name, // 即使是访问器,也要手动取 'email' => $this->email, 'role' => $this->role_name ?? '', // 关联字段提前加载好,别在这里调 $this->role->name ]; } - 别在该方法里做 N+1 操作(如
$this->load('profile')),模型同步是批量触发的,会拖垮性能 - 日期字段建议转为字符串:
'created_at' => $this->created_at?->toIso8601String(),ES 不认 Carbon 实例
搜索结果不是 Eloquent 查询,字段值不走 casts/appends
Model::search('xxx')->get() 看起来像查数据库,实际发的是 HTTP 请求到 ES,返回的 JSON 是原始索引内容:
- 如果模型定义了
$appends = ['full_name'],full_name不会出现在搜索结果里 - 如果字段用了
casts(如'price' => 'decimal:2'),ES 里存的仍是原始字符串或整数,不会自动格式化 - 搜索返回的模型实例,
$user->name是从 ES 索引里读的,不是从数据库查的——所以删库但没 flush 索引,还能搜出已删除的数据
ES 索引和数据库是两套数据源,同步靠事件驱动,但字段映射、类型、生命周期都得你亲手对齐,没有魔法。


















