laravel-mongodb icon indicating copy to clipboard operation
laravel-mongodb copied to clipboard

Call to a member function prepare() on null

Open djeux opened this issue 3 years ago • 8 comments

  • Laravel-mongodb Version: 3.8.2
  • PHP Version: 7.4.13
  • Database Driver & Version: 1.9.0

Description:

Adding a mysql relation to a mongodb model causes the given error when fetching the relation.

{
  "exception": "Error"
  "file": "/var/www/project/vendor/laravel/framework/src/Illuminate/Database/Connection.php"
  "line": 338
  "message": "Call to a member function prepare() on null"
}

My model class

use App\Models\User;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Jenssegers\Mongodb\Eloquent\Model;

class Draft extends Model
{
    protected $collection = 'survey_drafts';

    protected $connection = 'mongodb';

    protected $attributes = [
        'questions' => [],
    ];

    public function owner(): BelongsTo
    {
        return $this->belongsTo(User::class, 'owner_id', 'id');
    }
}

The User class uses the default MySQL connection.

Upon investigation further, I saw that Connection::getPdoForSelect is being called on the MongoDB connection instance, where the $pdo is NULL. Therefore throwing the error when trying to retrieve the PDO class for some reason.

The cause for this is that the MySQL User model does not have a $connection property defined as it should pick the default mysql connection when it's not specifically defined otherwise (as its done with the mongodb model).

This is being done in HasRelationships::newRelatedInstance(). When being used as a relation to a mongodb model the $this->connection is a mongodb connection.

The only way to fix this currently is to add a

$connection = 'mysql'

to all MySQL models that are being used as relations to a mongodb model. In the given example, to the User model

djeux avatar Mar 16 '21 08:03 djeux

The drawback to this "fix" is that if you're using the memory database for tests, they will start to fail as the models will be using the mysql connection instead of the memory one, as it's hardcoded into them.

djeux avatar Mar 16 '21 08:03 djeux

i think this is the used models of installed packages

jalallinux avatar May 08 '21 09:05 jalallinux

same issue

vahidei avatar Oct 24 '22 08:10 vahidei

I have the same issue too

Cart Class

use Jenssegers\Mongodb\Eloquent\Model;

class Cart extends Model
{
    protected $connection = 'mongodb';

    protected $guarded = [];

    protected $with = ['items'];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function items()
    {
        return $this->hasMany(CartItem::class);
    }
}

User model is default mysql connection and when I call like this: $cart->user

I got same error: Call to a member function prepare() on null

But in reverse works well with HybridRelations $user->carts

Mahan-Shoghy avatar Mar 04 '23 16:03 Mahan-Shoghy

I have the same issue without any relation with a simple model

class ActivityLog extends Model
{
    protected $connection = 'mongodb';
    protected $fillable = [
        'action'
    ];
}

alkhachatryan avatar Aug 11 '23 13:08 alkhachatryan

Replace Illuminate\Database\Eloquent\Model with MongoDB\Laravel\Eloquent\Model inside your models. Example:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;    // instead of Illuminate\Database\Eloquent\Model

class Comment extends Model
{
    
}

using mongodb/laravel-mongodb

shahid163 avatar Nov 05 '23 17:11 shahid163