Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Для профи > Laravel 5.2.x + jenssegers/mongodb 3.0.x


Автор: doctor2k 8.8.2016, 11:39
Доброго времени суток, уважаемые господа, товарищи, граждане. Коллеги. Друзья. Братья.

Проблема в следующем. Имеется Laravel 5.2.x с прикрученным к нему https://github.com/jenssegers/laravel-mongodb для работы с MongoDB. Дока в принципе подробная, штуковина работает, но вот понадобилось мне N дней назад взять объект по его _id. И тут я напоролся на грабли.

В доке указано просто:
Код

$user = User::find('517c43667db388101e00000f');

То есть, по сути, _id передаём строкой. Но этот код возвращает NULL. Помню, когда для Yii писал свою обёртку, там взаимодействие с монгой было через PHPшное расширение, и надо было перед обращением к базе превратить строку в MongoId, т.е.:
Код

$_id = new MongoId( $id );

Здесь такое не срабатывает. Я полез в исходники самого расширения, нашёл следующие вещи:
Код

public function find($id, $columns = [])
    {
        return $this->where('_id', '=', $this->convertKey($id))->first($columns);
    }

Код

public function convertKey($id)
    {
        if (is_string($id) and strlen($id) === 24 and ctype_xdigit($id)) {
            return new ObjectID($id);
        }

        return $id;
    }

Т.е. find() это просто такая обёртка для where(). Ладно, пробуем по-другому. Пишем сами через where():
Код

    $subject = SubjectModel::where( '_id', '=', '551d4530bfef316a3c8b7949' )->get();

Возвращается фигня. var_dump() выдаёт следующее:
Код

object(Illuminate\Database\Eloquent\Collection)#174 (1) {
  ["items":protected]=>
  array(0) {
  }
}

Хотя объект под таким _id есть в коллекции, и через консоль Robomongo прекрасно ищется.
Помогите пожалуйста найти решение проблемы, или хотя бы подскажите в какую сторону смотреть.
Заранее спасибо.

Автор: doctor2k 11.8.2016, 12:17
Решил проблему. Переопределил метод find() в модели, стало так (на примере UserModel.php):

Код

namespace App;

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class UserModel extends Eloquent
{
    protected $collection = 'user';

    public static function find( $mongo_id )
    {
        if( !is_string( $mongo_id )
            OR !mb_strlen( $mongo_id )
            OR !ctype_xdigit( $mongo_id )
            ):
            return FALSE;
        endif;

        return Self::whereRaw( [ '_id' => $mongo_id ] )->first();
    }
}


Не претендую на абсолютную правильность решения, но меня устраивает.

Автор: _zorn_ 20.1.2017, 15:02
Цитата(doctor2k @  8.8.2016,  18:39 Найти цитируемый пост)
 if (is_string($id) and strlen($id) === 24 and ctype_xdigit($id))

Само по себе использование "and" вместо "&&" (интересно зачем ?) чревато подводными камнями (приоритеты операторов).
А если разработчик их использует, значит полюбому где нибудь и наткнется. Короче нет доверия этому коду )

http://stackoverflow.com/questions/2803321/and-vs-as-operator
Цитата

$this = true;
$that = false;

$truthiness = $this and $that;
var_dump($truthiness); //bool(true)


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)