You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 10+MongoDB下Sanctum生成Token遇prepare() on null错误

Laravel 10 + MongoDB 生成Sanctum Token时报错:Call to a member function prepare() on null

问题描述

我有一个使用MongoDB数据库的Laravel 10应用,正在为api_users集合中的用户创建生成Token的API端点。创建用户的函数运行完全正常,但调用createToken生成Token时触发错误。

创建用户的正常代码

public function createApiUser(Request $request)
{
    $username = $request->input('username');
    $password = $request->input('password');

    $password = Hash::make($password);

    $apiUser = new ApiUser();

    $apiUser->username = $username;
    $apiUser->password = $password;

    try {
        $apiUser->save();
        return ["Success"];
    } catch (\Throwable $th) {
        return ["error" => $th->getMessage()];
    }
}

生成Token的报错代码

public function generateToken(Request $request)
{
    $username = $request->input('username');
    $password = $request->input('password');
    $collection = DB::connection('mongodb')->collection('api_users');

    // 根据用户名获取用户文档
    $userData = ApiUser::where('username', $username)->first();

    if ($userData && Hash::check($password, $userData['password'])) {
        $user = $userData;
        // 执行此行时触发错误
        $token = $user->createToken('MyApp')->plainTextToken;

        return response()->json([
            'token' => $token,
            'user' => $user,
        ], 200);
    }

    return response()->json(['error' => 'Unauthorised'], 401);
}

错误信息

Error: Call to a member function prepare() on null in file /vendor/laravel/framework/src/Illuminate/Database/Connection.php on line 574

ApiUser模型代码

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use MongoDB\Laravel\Eloquent\Model as Eloquent;
use MongoDB\Laravel\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
use Laravel\Sanctum\HasApiTokens;

class ApiUser extends Eloquent
{
    use HasApiTokens, HasFactory,Notifiable;
    protected $guard = 'api';
    protected $table = 'api_users';
    protected $connection = 'mongodb';
    protected $guarded = [];

    protected $fillable = [
        'username', 'password',
    ];
}

auth.php配置

<?php

return [ 
    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
        'email' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
    ], 

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'mongodb' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'sanctum',
            'provider' => 'api_users',
        ],
        'api_users' => [
            'driver' => 'sanctum',
            'provider' => 'api_users',
        ],
    ],

    'verification' => [
        'enabled' => false,
        'expire' => 60,
    ], 

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],
        'api_users' => [
            'driver' => 'eloquent',
            'model' => App\Models\ApiUser::class,
        ],
    ],
 
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
    ],
 
    'password_timeout' => 10800,
];

解决方案

问题根源

错误是因为Laravel Sanctum默认使用默认数据库连接(通常为MySQL)存储Token,但你的ApiUser模型使用MongoDB连接,导致Sanctum尝试用错误的连接操作Token表。

修复步骤

  1. 修正ApiUser模型继承关系
    移除多余的模型引用,直接继承MongoDB提供的Authenticatable类,确保认证契约正确实现:

    <?php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use MongoDB\Laravel\Auth\User as Authenticatable;
    use Illuminate\Notifications\Notifiable;
    use Laravel\Sanctum\HasApiTokens;
    
    class ApiUser extends Authenticatable
    {
        use HasApiTokens, HasFactory, Notifiable;
    
        protected $guard = 'api';
        protected $table = 'api_users';
        protected $connection = 'mongodb';
        protected $guarded = [];
    
        protected $fillable = [
            'username', 'password',
        ];
    }
    
  2. 配置Sanctum使用MongoDB连接
    发布Sanctum配置文件(如果未发布):

    php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
    

    在config/sanctum.php中指定数据库连接为mongodb:

    return [
        // 其他配置...
        'database_connection' => env('SANCTUM_DB_CONNECTION', 'mongodb'),
        // 其他配置...
    ];
    
  3. 确保MongoDB连接配置正确
    检查.env文件中的MongoDB连接参数:

    DB_CONNECTION=mongodb
    DB_HOST=127.0.0.1
    DB_PORT=27017
    DB_DATABASE=your_database_name
    DB_USERNAME=
    DB_PASSWORD=
    
  4. 重新生成Sanctum迁移(可选)
    如果之前用MySQL创建过Sanctum迁移,删除相关文件后运行MongoDB迁移:

    php artisan mongodb:migrate
    
  5. 简化generateToken方法
    优化代码,直接使用模型查询:

    public function generateToken(Request $request)
    {
        $request->validate([
            'username' => 'required',
            'password' => 'required',
        ]);
    
        $user = ApiUser::where('username', $request->username)->first();
    
        if (!$user || !Hash::check($request->password, $user->password)) {
            return response()->json(['error' => 'Unauthorised'], 401);
        }
    
        $token = $user->createToken('MyApp')->plainTextToken;
    
        return response()->json([
            'token' => $token,
            'user' => $user,
        ], 200);
    }
    

内容的提问来源于stack exchange,提问作者bob269

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 15:02:03