Laravel中如何将活动日志存到MongoDB?遇prepare()调用空对象错误
问题解决:spatie/laravel-activitylog 结合 MongoDB 存储日志报错处理
问题根源
- spatie/laravel-activitylog 默认的
Activity模型基于 MySQL 的 Eloquent 实现,直接指定 MongoDB 连接会导致与 MongoDB 驱动不兼容,触发Call to a member function prepare() on null错误。 - 你的
User模型错误继承了 MongoDB 版本的Authenticatable,这会强制 User 数据存储到 MongoDB,违背了「User 存 MySQL」的需求。
解决方案步骤
1. 修正 User 模型(确保数据存 MySQL)
将 User 模型改回继承原生 Laravel 的 Authenticatable,并指定 MySQL 连接(若默认连接已是 MySQL 可省略):
<?php namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Contracts\Auth\MustVerifyEmail; use Spatie\Activitylog\LogOptions; use Spatie\Activitylog\Traits\LogsActivity; class User extends Authenticatable implements MustVerifyEmail { use LogsActivity; // 指定使用 MySQL 连接(可选,默认连接为 MySQL 时可删除) protected $connection = 'mysql'; protected $fillable = [ 'name', 'email', 'password', // 根据实际业务补充字段 ]; // 按需补充 hidden、cast 等属性 public function getActivitylogOptions(): LogOptions { return LogOptions::defaults(); } }
2. 创建 MongoDB 版自定义 Activity 模型
在 app/Models 目录下新建 MongoActivity.php,继承 Jenssegers 的 MongoDB 模型并实现 spatie 的 Activity 接口:
<?php namespace App\Models; use Jenssegers\Mongodb\Eloquent\Model; use Spatie\Activitylog\Contracts\Activity; class MongoActivity extends Model implements Activity { // 指定使用 MongoDB 连接 protected $connection = 'mongodb'; // MongoDB 主键配置 protected $primaryKey = '_id'; protected $keyType = 'string'; public $incrementing = false; // 对应 MongoDB 集合名 protected $collection = 'activities'; // 允许批量赋值的字段 protected $fillable = [ 'log_name', 'description', 'subject_id', 'subject_type', 'causer_id', 'causer_type', 'properties', 'batch_uuid', ]; // 字段类型转换 protected $casts = [ 'properties' => 'array', 'created_at' => 'datetime', 'updated_at' => 'datetime', ]; // 实现 ActivityInterface 接口方法 public function getLogName(): string { return $this->log_name; } public function getDescription(): string { return $this->description; } public function getSubject() { if (! $this->subject_type || ! $this->subject_id) { return null; } return app($this->subject_type)->find($this->subject_id); } public function getCauser() { if (! $this->causer_type || ! $this->causer_id) { return null; } return app($this->causer_type)->find($this->causer_id); } public function getProperties(): array { return $this->properties; } public function getBatchUuid(): ?string { return $this->batch_uuid; } }
3. 修改 activitylog 配置,指定自定义模型
打开 config/activitylog.php,将默认的 Activity 模型替换为刚创建的 MongoActivity:
// 原配置 // 'activity_model' => Spatie\Activitylog\Models\Activity::class, // 修改为 'activity_model' => App\Models\MongoActivity::class,
确认数据库连接配置保留原有设置:
'database_connection' => env('ACTIVITY_LOGGER_DB_CONNECTION'),
4. 初始化 MongoDB 集合
MongoDB 无需传统迁移,可手动创建 activities 集合,或通过迁移生成:
- 创建 MongoDB 迁移文件:
php artisan make:migration create_activities_collection --connection=mongodb
- 编写迁移内容:
<?php use Illuminate\Database\Migrations\Migration; use Jenssegers\Mongodb\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { public function up() { Schema::connection('mongodb')->create('activities', function (Blueprint $table) { $table->string('_id')->primary(); $table->string('log_name'); $table->text('description'); $table->nullableMorphs('subject'); $table->nullableMorphs('causer'); $table->json('properties'); $table->string('batch_uuid')->nullable(); $table->timestamps(); }); } public function down() { Schema::connection('mongodb')->dropIfExists('activities'); } };
- 运行迁移:
php artisan migrate --connection=mongodb
5. 清除配置缓存
确保新配置生效:
php artisan config:clear
内容的提问来源于stack exchange,提问作者Riya
相关产品推荐
相关产品推荐

