martynbiz/php-mongo

PHP 的 MongoDB ODM。

v0.0.0 2016-05-30 10:10 UTC

This package is not auto-updated.

Last update: 2024-09-14 18:20:41 UTC


README

使用 composer 安装

$ composer require martynbiz/php-mongo

入门

创建连接

\MartynBiz\Mongo\Connection::getInstance()->init(array(
    'db' => 'mydb',
    'username' => 'myuser',
    'password' => '89dD7HH7di!89',
    'classmap' => array(
        'users' => '\\App\\Model\\User',
    ),
));

创建模型

通过扩展 Mongo 类创建模型,确保定义 $collection 和 $whitelist

<?php

use MartynBiz\Mongo;

class User extends Mongo
{
    // required - collection this model refers to
    protected static $collection = 'users';

    // required - define on the fields that can be saved
    protected static $whitelist = array(
        'name',
        'email',
        'username',
        'password',
    );
}

创建多个连接

如果只使用单个数据库,这并不必要。但是,如果您需要连接到多个数据库,请给每个连接一个唯一的名称

Connection::getInstance('conn1')->init(array(
    ...
));

// also, checking if an instance exists
if (! Connection::hasInstance('conn2')) {
    Connection::getInstance('conn2')->init(array(
        ...
    ));
}

另外,请记住在模型中声明哪个 $conn

<?php

use MartynBiz\Mongo;

class User extends mongo
{
    // optional - if using multiple connections/databases
    protected static $conn = 'conn1';

    .
    .
    .
}

查询

通过 mongo 查询查找

// statically
$users = User::find(array(
    'status' => 1,
));

// dynamically
$col = new User();
$users = $col->find(array(
    'status' => 1,
));

通过 mongo 查询查找一个

// statically
$user = User::findOne(array(
    'email' => 'info@examle.com',
));

// dynamically
$col = new User();
$user = $col->findOne(array(
    'email' => 'info@examle.com',
));

通过对象查找

模型实例也可以传递,find 方法会将其内部转换为 DBRef(例如 'friend' => $friend 将与 'friend' => $friend->getDBRef() 相同)

$friend = User::findOne(array(
    //...
));

$user = User::find(array(
    'friend' => $friend,
));

获取和设置值

// setting

// on instantiation -- will be filtered against $whitelist
$article = new Article(array(
    'title' => 'My title',
));

$author = User::findOne(array(
    //...
));

// single value properties -- no param filtering
$article->status = 2;
$article->author = $author;

// AND/OR set() method, with Mongo instance -- suited for unit testing, no param filtering
$user = User::findOne(array(
    //...
));
$article->set('author', $author);

// set value as query result (will be stored as an array of dbrefs)
$tags = Tag::find(array(
    //...
));
$article->tags = $tags;

// lastly, params can be passed with save() -- will be filtered against $whitelist
$article->save(array(
    'content' => $text,
))
// getting

$article = Article::findOne(array(
    //...
));

// single value properties -- no param filtering
echo $article->status;
echo $article->author->name;
echo $article->tags[0]->name;
echo $article->get('author');

插入

save 方法用于模型类的实例化对象。它可以在分配属性值之后调用,或者通过传递名称/值作为参数。注意:当传递名称/值时,值将被白名单化

$user->name = 'Jim';
$user->save();
$user->save(array(
    'name' => 'Jim',
));

create 方法不需要实例,但它将接受名称\值并在其中插入到集合中。它将返回创建的文档的实例。注意:当传递名称/值时,值将被白名单化

// statically
$user = User::create(array(
    'name' => 'Jim',
));

// dynamically (e.g. service locator pattern, or DI)
$col = new User();
$user = $col->create(array(
    'name' => 'Jim',
));

工厂方法实际上不插入,但会生成具有值的实例。然后可以使用它的 save 方法对其进行修改和插入

// statically
$user = User::factory(array(
    'name' => 'Jim',
));

// dynamically
$col = new User();
$user = $col->factory(array(
    'name' => 'Jim',
));

$user->save();

虽然看起来有多种方法,但它确实提供了保持代码整洁和测试时模拟方法的灵活性。

推送

注意:push with $each 是这里的默认行为,尽管这可以通过 options 数组中的 'each' => false 覆盖

// push one object, will convert to DBRef
$user->push(array(
    'friends' => $friend,
));

// push multi object, will convert to DBRef
$user->push(array(
    'friends' => array(
        $friend,
        $friend2,
    ),
));

// push MongoIterator object (from find() call)
$user->push(array(
    'friends' => $friends,
));

// push multiple properties at once
$user->push(array(
    'friends' => $friends,
    'enemies' => $enemies,
));

// push without $each setting, will push the whole array as a single element
$user->push(array(
    'friends' => array(
        $friend,
        $friend2,
    ),
), array('each' => false));

删除

一个实例可以使用 delete 方法从数据库中删除自己

$user->delete();

要使用查询从集合中删除多个文档,请使用 remove 方法

User::remove(array(
    'type' => 'boring',
), $options);

转换为数组

$user->toArray(3); // convert nested 3 deep to array (optional)

验证

在保存到数据库之前,会调用 validate 方法。如果它返回 false,则数据将不会保存。

class User extends mongo
{
    .
    .
    .
    public function validate()
    {
        $this->resetErrors();

        if (empty($this->data['name'])) {
            $this->setError('Name is missing.');
        }

        return empty( $this->getErrors() ); // true if none
    }
}

以下示例使用 martynbiz/php-validator 库。

<?php

use MartynBiz\Validator;

class User extends mongo
{
    .
    .
    .
    public function validate()
    {
        $this->resetErrors();

        $validator = new Validator($this->data);

        $validator->check('name')
            ->isNotEmpty('Name is missing');

        $validator->check('email')
            ->isNotEmpty('Email address is missing')
            ->isEmail('Invalid email address');

        $message = 'Password must contain upper and lower case characters, and have more than 8 characters';
        $validator->check('password')
            ->isNotEmpty($message)
            ->hasLowerCase($message)
            ->hasUpperCase($message)
            ->hasNumber($message)
            ->isMinimumLength($message, 8);

        // update the model's errors with the validators
        $this->setError( $validator->getErrors() );

        return empty($this->getErrors());
    }
}

自定义 Getter/ Setter

要自动在获取时转换值,您可以定义自定义方法来自动转换属性的值。这可能在对字符串进行格式化时很有用,例如将日期格式化为人类可读格式。

<?php

use MartynBiz\Mongo;

class User extends Mongo
{
    .
    .
    .

    public function getCreatedAt($value)
    {
        return date('Y-M-d h:i:s', $this->data['created_at']->sec);
    }

    public function setPassword($value)
    {
        return password_hash($value, PASSWORD_BCRYPT);
    }
}

TODO

  • 支持点符号语法?find(array('model.name' => 'Martyn')), set/get(array(model.name' => 'Martyn'))