Laravel-mongodb: $statement = $this->prepared($this->getPdoForSelect($useReadPdo) ->prepare($query)); vendor\laravel\framework\src\Illuminate\Database\Connection.php Symfony \ Component \ Debug \ Exception \FatalThrowableError (E_ERROR) Call to a member function prepare() on null

Created on 15 May 2018  路  5Comments  路  Source: jenssegers/laravel-mongodb

$statement = $this->prepared($this->getPdoForSelect($useReadPdo)
->prepare($query));
vendor\laravel\framework\src\Illuminate\Database\Connection.php

Symfony \ Component \ Debug \ Exception \FatalThrowableError (E_ERROR)
Call to a member function prepare() on null

question

All 5 comments

I'm having this same issue when trying to use the belongsTo relationship from a MongoDB model to a MySQL model.

The issue seems to be caused by the belongs to relationship trying to use the MongoDB connection. If I specify the connection property on the MySQL model to mysql then it works. This isn't a solution for me as in tests I use sqlite and in production I use mysql so I need it to use the default connection.

I'm using PHP 7.2, laravel v5.6.23, and laravel-mongodb v3.4.2

My mongodb model

use Jenssegers\Mongodb\Eloquent\Model;

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

    protected $collection = 'notifications';

    public function tenant()
    {
        return $this->belongsTo('Tenant');
    }
}

My MySQL model

use Illuminate\Database\Eloquent\Model;
use Jenssegers\Mongodb\Eloquent\HybridRelations;

class Tenant extends Model
{
    use HybridRelations;

    protected $table = 'tenants';
}

Stack trace of the error.

1) NotificationModelTest::it_belongs_to_a_tenant
Error: Call to a member function prepare() on null

/vendor/laravel/framework/src/Illuminate/Database/Connection.php:330
/vendor/laravel/framework/src/Illuminate/Database/Connection.php:661
/vendor/laravel/framework/src/Illuminate/Database/Connection.php:628
/vendor/laravel/framework/src/Illuminate/Database/Connection.php:337
/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:1909
/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:1894
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:481
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:465
/vendor/laravel/framework/src/Illuminate/Database/Concerns/BuildsQueries.php:77
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php:81
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:419
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:397
/vendor/jenssegers/mongodb/src/Jenssegers/Mongodb/Eloquent/Model.php:145
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1414

I've done some more digging and when you hit the mysql relation from the mongodb model it tries to use the mongodb connection.

I've made a basic test using the models above. I'm just trying to hit the relation without any data which I would expect to return null.

$notification = new Notification();

$notification->tenant;

But that is throwing the following error.

1) NotificationModelTest::it_belongs_to_a_tenant
Error: Call to a member function prepare() on null

/vendor/laravel/framework/src/Illuminate/Database/Connection.php:330
/vendor/laravel/framework/src/Illuminate/Database/Connection.php:661
/vendor/laravel/framework/src/Illuminate/Database/Connection.php:628
/vendor/laravel/framework/src/Illuminate/Database/Connection.php:337
/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:1909
/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:1894
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:481
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:465
/vendor/laravel/framework/src/Illuminate/Database/Concerns/BuildsQueries.php:77
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php:81
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:419
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:397
/vendor/jenssegers/mongodb/src/Jenssegers/Mongodb/Eloquent/Model.php:145
/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1414

When I run the test if I dd in the getConnectionName() method in Illuminate\Database\Eloquent\Model it returns 'mongodb', but it should return the default driver.

If I override that method in the Tenant model to return the default connection that fixes the issue.

use Illuminate\Database\Eloquent\Model;
use Jenssegers\Mongodb\Eloquent\HybridRelations;

class Tenant extends Model
{
    use HybridRelations;

    protected $table = 'tenants';

    public function getConnectionName()
    {
        return config('database.default');
    }
}

if you use native authentication in laravel with mongodb, you must change in the path

/vendor/laravel/framework/src/Illuminate/Foundation/Auth/User.php

<?php

namespace Illuminate\Foundation\Auth;

use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\MustVerifyEmail;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
#use Illuminate\Database\Eloquent\Model;
use Jenssegers\Mongodb\Eloquent\Model;
use Illuminate\Foundation\Auth\Access\Authorizable;

class User extends Model implements
    AuthenticatableContract,
    AuthorizableContract,
    CanResetPasswordContract
{
    use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail;
}

@stardesign77, is it issue actual for you?

if you use native authentication in laravel with mongodb, you must change in the path

/vendor/laravel/framework/src/Illuminate/Foundation/Auth/User.php

<?php

namespace Illuminate\Foundation\Auth;

use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\MustVerifyEmail;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
#use Illuminate\Database\Eloquent\Model;
use Jenssegers\Mongodb\Eloquent\Model;
use Illuminate\Foundation\Auth\Access\Authorizable;

class User extends Model implements
    AuthenticatableContract,
    AuthorizableContract,
    CanResetPasswordContract
{
    use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail;
}

not worked for Laravel 8.x

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sanjay1688 picture sanjay1688  路  3Comments

Vasiliy-Bondarenko picture Vasiliy-Bondarenko  路  3Comments

YSimple picture YSimple  路  3Comments

geofflancaster picture geofflancaster  路  3Comments

phuocduy1988 picture phuocduy1988  路  3Comments