Yii2: MongoDB Exception: unknown operator $oid

Created on 22 Nov 2017  Â·  12Comments  Â·  Source: yiisoft/yii2

What steps will reproduce the problem?

Only when 'enableAutoLogin' is set to true on backend/config/main.php:

'user' => [
            'identityClass' => 'common\models\User',
            'enableAutoLogin' => true,
            'identityCookie' => ['name' => '_identity-backend', 'httpOnly' => true],
        ],  

What is the expected result?

The login form should appear.

What do you get instead?

In debug mode the site is throwing the warning:

MongoDB Exception – yii\mongodb\Exception
unknown operator: $oid
Caused by: MongoDB\Driver\Exception\ConnectionException

Additional info

| Q | A
| ---------------- | ---
| Yii version | 2.0.12
| PHP version | 7.1.5
| Operating system | windows 10

question

Most helpful comment

Just replace findIdentity on User model like below:

    public static function findIdentity($id)
    {
        if ($id === (array) $id && isset($id['$oid'])) $id = $id['$oid'];

        return static::findOne($id);
    }

Working for me

All 12 comments

How does common\models\User look like?


namespace common\models;
use Yii;
use yii\base\NotSupportedException;
use yii\mongodb\ActiveRecord;
use yii\web\IdentityInterface;

class User extends ActiveRecord implements IdentityInterface
{
    const STATUS_DELETED = 0;
    const STATUS_ACTIVE = 10;

    const ROLE_ADMIN = 'admin'
    const ROLE_SADMIN = 'superadmin'

    public static function collectionName()
    {
        return [Yii::$app->params['mongodb'], 'users'];
    }

    public function attributes()
    {
        return [
            '_id',
            'name',
            'surname',
            'username',
            'password',
            'password_hash',
            'password_reset_token',
            'email',
            'auth_key',
            'role',
            'status',
            'created_at',
            'updated_at',
            'avatar'
        ];
    }

    public function behaviors()
    {
        return [
            'timestamp' => [
                'class' => 'yii\behaviors\TimestampBehavior',
                 'attributes'=>[
                        ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
                        ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at']
                    ]
            ]
        ];
    }

    public function rules()
    {
        return [
            ['status', 'default', 'value' => self::STATUS_ACTIVE],
            ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
            ['role', 'default', 'value' => self::ROLE_USER],
            ['role', 'in', 'range' => [self::ROLE_USER, self::ROLE_ADMIN]],
        ];
    }

    public static function findIdentity($id)
    {
        return static::findOne(['_id' => $id, 'status' => self::STATUS_ACTIVE]);
    }

    public static function findIdentityByAccessToken($token, $type = null)
    {
        throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
    }

    public static function findByUsername($username)
    {
        return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
    }

    public static function findByPasswordResetToken($token)
    {
        if (!static::isPasswordResetTokenValid($token)) {
            return null;
        }

        return static::findOne([
            'password_reset_token' => $token,
            'status' => self::STATUS_ACTIVE,
        ]);
    }

    public static function isPasswordResetTokenValid($token)
    {
        if (empty($token)) {
            return false;
        }

        $timestamp = (int) substr($token, strrpos($token, '_') + 1);
        $expire = Yii::$app->params['user.passwordResetTokenExpire'];
        return $timestamp + $expire >= time();
    }

    public function getId()
    {
        return $this->getPrimaryKey();
    }

    public function getAuthKey()
    {
        return $this->auth_key;
    }

    public function validateAuthKey($authKey)
    {
        return $this->getAuthKey() === $authKey;
    }

    public function validatePassword($password)
    {
        return Yii::$app->security->validatePassword($password, $this->password_hash);
    }

    public function setPassword($password)
    {
        $this->password_hash = Yii::$app->security->generatePasswordHash($password);
    }

    public function generateAuthKey()
    {
        $this->auth_key = Yii::$app->security->generateRandomString();
    }

    public function generatePasswordResetToken()
    {
        $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
    }

    public function removePasswordResetToken()
    {
        $this->password_reset_token = null;
    }
}

Provide full stacktrace of the warning appearing.

Exception (MongoDB Exception) 'yii\mongodb\Exception' with message 'unknown operator: $oid' 

in C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2-mongodb\Command.php:292

Stack trace:
#0 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2-mongodb\Command.php(614): yii\mongodb\Command->query('users', Array)
#1 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2-mongodb\Collection.php(218): yii\mongodb\Command->find('users', Array, Array)
#2 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2-mongodb\Query.php(198): yii\mongodb\Collection->find(Array, Array, Array)
#3 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2-mongodb\Query.php(365): yii\mongodb\Query->buildCursor(NULL)
#4 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2-mongodb\ActiveQuery.php(149): yii\mongodb\Query->one(NULL)
#5 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\db\BaseActiveRecord.php(107): yii\mongodb\ActiveQuery->one()
#6 C:\MAMP\htdocs\mongocms_theme\common\models\User.php(98): yii\db\BaseActiveRecord::findOne(Array)
#7 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\web\User.php(565): common\models\User::findIdentity(Array)
#8 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\web\User.php(287): yii\web\User->getIdentityAndDurationFromCookie()
#9 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\web\User.php(675): yii\web\User->loginByCookie()
#10 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\web\User.php(188): yii\web\User->renewAuthStatus()
#11 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\web\User.php(334): yii\web\User->getIdentity()
#12 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\Component.php(133): yii\web\User->getIsGuest()
#13 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2-debug\views\default\panels\user\summary.php(6): yii\base\Component->__get('isGuest')
#14 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\View.php(332): require('C:\\MAMP\\htdocs\\...')
#15 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\View.php(250): yii\base\View->renderPhpFile('C:\\MAMP\\htdocs\\...', Array)
#16 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\View.php(152): yii\base\View->renderFile('C:\\MAMP\\htdocs\\...', Array, NULL)
#17 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2-debug\panels\UserPanel.php(38): yii\base\View->render('panels/user/sum...', Array)
#18 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2-debug\views\default\toolbar.php(40): yii\debug\panels\UserPanel->getSummary()
#19 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\View.php(332): require('C:\\MAMP\\htdocs\\...')
#20 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\View.php(250): yii\base\View->renderPhpFile('C:\\MAMP\\htdocs\\...', Array)
#21 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\View.php(152): yii\base\View->renderFile('C:\\MAMP\\htdocs\\...', Array, Object(yii\debug\controllers\DefaultController))
#22 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\Controller.php(415): yii\base\View->render('toolbar', Array, Object(yii\debug\controllers\DefaultController))
#23 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2-debug\controllers\DefaultController.php(104): yii\base\Controller->renderPartial('toolbar', Array)
#24 [internal function]: yii\debug\controllers\DefaultController->actionToolbar('5a155baf32feb')
#25 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\InlineAction.php(57): call_user_func_array(Array, Array)
#26 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\Controller.php(157): yii\base\InlineAction->runWithParams(Array)
#27 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\Module.php(528): yii\base\Controller->runAction('toolbar', Array)
#28 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\web\Application.php(102): yii\base\Module->runAction('debug/default/t...', Array)
#29 C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\base\Application.php(386): yii\web\Application->handleRequest(Object(yii\web\Request))
#30 C:\MAMP\htdocs\mongocms_theme\backend\web\index.php(17): yii\base\Application->run()
#31 {main}

common\models\User::findIdentity(Array)

What is an argument for this invocation?

C:\MAMP\htdocs\mongocms_theme\vendor\yiisoft\yii2\web\User.php at line 565 – common\models\User::findIdentity(['$oid' => '5989b8e0a0aec60af9d24210'])

So, what is $oid? Where it comes from?

You need to typecaset \MongoId object into a string at your Identity::getId().
There is already note about \MongoId specifics:
https://github.com/yiisoft/yii2-mongodb/blob/master/docs/guide/usage-mongoid.md

Thank you for your question.
In order for this issue tracker to be effective, it should only contain bug reports and feature requests.

We advise you to use our community driven resources:

If you are confident that there is a bug in the framework, feel free to provide information on how to reproduce it. This issue will be closed for now.

_This is an automated comment, triggered by adding the label question._

The $oid is the Object ID for a document in a collection for Mongodb, the format ['$oid' => '5989b8e0a0aec60af9d24210'] is equal to ObjectId("5989b8e0a0aec60af9d24210"). The $oid comes from the cookie setted when "remember me" check is active, i think:

$_COOKIE = [
    '_identity-backend' => '5025a629a067736eadc9d9ecc2cc9b424cc1870d5c1bee4e53dd677cbc8ace77a:2:{i:0;s:17:"_identity-backend";i:1;s:48:"[{"$oid":"5989b8e0a0aec60af9d24210"},"",2592000]";}',
    '_identity' => '2eed46e2a9b09d7433eff14bc9a9056bfe30e7b0e32d1cf2e5ccef84d3d05ea9a:2:{i:0;s:9:"_identity";i:1;s:48:"[{"$oid":"5989b8e0a0aec60af9d24210"},"",2592000]";}',
];

User model in just Replace.

public static function findIdentity($id)
{        
  return static::findOne($id);             
}

Just replace findIdentity on User model like below:

    public static function findIdentity($id)
    {
        if ($id === (array) $id && isset($id['$oid'])) $id = $id['$oid'];

        return static::findOne($id);
    }

Working for me

Was this page helpful?
0 / 5 - 0 ratings