mawelous / yamop
PHP的另一个MongoDB ODM。没有不必要的功能,易于连接。
Requires
- php: >=5.3.0
This package is not auto-updated.
Last update: 2024-09-28 13:35:31 UTC
README
PHP的另一个MongoDB ODM
这是什么?
这是另一个开源且非常简单的MongoDB ODM。它的工作方式与标准的MongoDB PHP扩展接口相同,但返回对象而不是数组(作为ODM)。查询保持不变。它最酷的功能之一是连接,允许您查询相关对象。
功能列表
- 字符串ID(在视图中更容易链接)
- 内嵌对象
- 相关对象(执行“连接类似”操作)
- JSON格式
- 分页器
- 时间戳(根据需要添加created_at和updated_at字段)
- 打印日期和时间
- 事务(仅支持PHP错误)
需求
- PHP 5.3+
- PHP MongoDB 扩展
安装
在composer.json
文件中的require
键中添加以下内容
"mawelous/yamop": "dev-master"
保存并运行Composer更新命令
$ composer update
Composer完成后,您只需要将以下行添加到您的代码中
$connection = new \MongoClient( 'your_host' ); \Mawelous\Yamop\Mapper::setDatabase( $connection->your_db_name );
您可以将任何MongoDB
实例传递给setDatabase
函数。
现在,在您的任何模型中扩展Mawelous\Yamop\Model
class User extends \Mawelous\Yamop\Model { protected static $_collectionName = 'users'; }
就这样!
每个对象都有一个_id
,它是一个MongoId
,以及一个id
键,它是其字符串表示。
MongoDB
中的每个文档都作为对象返回,每个键都是一个属性——以下是一个MongoDB
中的示例文档
{ "_id": ObjectId("51b6ea4fb7846c9410000001"), "name": "John Doe", "birthdate": ISODate("2013-05-25T12:15:25.0Z"), "email": "john@something.com" }
上述文档在PHP中的表示如下
object(User)[44] public '_id' => object(MongoId)[46] public '$id' => string '51b6ea4fb7846c9410000001' (length=24) public 'name' => string 'John Doe' (length=8) public 'birthdate' => object(MongoDate)[47] public 'sec' => int 1369484125 public 'usec' => int 0 public 'email' => string 'john@something.com' (length=18) public 'id' => string '51b6ea4fb7846c9410000001' (length=24)
有几种方法可以将属性传递给对象
// properties as array $user = new User( array( 'name' => 'John', 'email' => 'email@email.com' ) ); // or each property separately $user = new User; $user->name = 'John'; $user->email = 'email@email.com';
从版本0.2.1开始(不包括它),当尝试获取不存在的属性时,Yamop返回null
。
获取数据
想要通过id获取文档?有一种简单的方法。
$user = User::findById( '51a61930b7846c400f000002' ) //or $mongoId = new MongoId( '51a61930b7846c400f000002' ); $user = User::findById( $mongoId )
通过查询获取单个文档也很简单。方法findOne
与原生的findOne
完全相同,但返回一个对象。作为第二个参数,您可以传递一个字段数组。这意味着参数和查询保持不变,这非常好!
$user = User::findOne( array( 'email' => 'user@mail.com' ) ); //or $user = User::findOne( array( 'email' => 'user@mail.com' ), array( 'email', 'username', 'birthdate' ) );
介绍Mapper
Yamop中有一个Mapper
类,它负责检索数据。我将它从Model
中分离出来,使其成为一个数据容器。如果您想要创建更复杂的查询,请使用mapper。您可以通过使用getMapper
方法或通过传递模型类字符串创建它的新实例来获取它。
//first possibility $mapper = User::getMapper(); //second possibility $mapper = new Mawelous\Yamop\Mapper( 'User' );
查找方法
前面为Model
引入的findOne
方法是Mapper
的方法。Model
只是引用它。您可以这样调用它
//findOne with Mapper $user = User::getMapper()->findOne( array( 'email' => 'user@mail.com' ) );
存在一个可以获取多个文档的 find
方法。它也像本地 find
一样工作,但返回一个 Mapper
。您可以在其上执行其他操作,如 sort
、limit
、skip
,它们都像本地一样工作。要获取对象数组,请使用 get
方法。
//You can call it directly with Model $messages = Message::find( array( 'to_id' => new MongoId( $stringId ), 'to_status' => Message::STATUS_UNREAD ) ) ->sort( array( 'created_at' => -1 ) ) ->limit( 10 ) ->get(); //or using Mapper itself $messages = Message::getMapper() ->find( array( 'to_id' => new MongoId( $stringId ), 'to_status' => Message::STATUS_UNREAD ) ) ->sort( array( 'created_at' => -1 ) ) ->limit( 10 ) ->get();
findAndModify
与本地 findAndModify
相同,但用于对象。
保存、更新和删除
save
方法用于创建和更新对象。以下代码用于创建新对象并将其写入数据库:
$user = new User( array( 'name' => 'John', 'email' => 'email@email.com' ) ); $user->save();
您可以在 save
后立即获取新创建对象的 _id
。
删除很简单
$user->remove();
这些方法返回的结果与本地 remove
和 save
方法相同。如果您想更新多个文档,请使用本地的函数,例如 这里。
扩展 Mapper
如果您想添加更多方法,可以扩展 Mapper
。例如,我创建了 UserMapper,它有一个在用户的 Facebook 墙上发布消息的方法。只需让 Mapper
知道要使用哪个 Model
类。
class UserMapper extends Mawelous\Yamop\Mapper { protected $_modelClassName = 'User'; public function findActiveUsers( $limit = 10, $sort = 'birthdate' ) { //method code } }
如果您想为模型注册不同的 Mapper
,只需在模型中声明它。
class User extends Model { ... protected static $_mapperClassName = 'UserMapper'; ...
现在只需执行 Mapper
。
$mapper = User::getMapper(); //and then $mapper->findActiveUsers( 5 );
这将返回一个 UserMapper 实例。您也可以创建一个新的 mapper。
$userMapper = new UserMapper; //and then $userMapper->findActiveUsers( 5 );
计数、索引、多更新和其他
所有在 Mapper
上调用但不存在的方法都传递给原始的 MongoCollection
。因此,您可以直接使用本地方法来使用 update
、count
、batchInsert
、ensureIndex
和 drop
。
//count Message::getMapper()->count( array( 'to_id' => $userId, 'to_status' => Message::STATUS_UNREAD ) ); //update Contest::getMapper()->update( array('status' => Contest::STATUS_READY_DRAFT, 'start_date' => array ('$lte' => new MongoDate(strtotime('midnight')) )), array('$set' => array( 'status' => Contest::STATUS_ACTIVE) ), array('multiple' => true) ); //drop Contest::getMapper()->drop();
内嵌对象
您当前对象内部是否有更多对象?Yamop 会自动转换。只需让它知道。
class User extends \Mawelous\Yamop\Model { protected static $_collectionName = 'users'; // One Address object embedded in address property protected static $_embeddedObject = array ( 'address' => 'Address', ); // Many Notification objects embedded in array that is kept ass notifications protected static $_embeddedObjectList = array ( 'notifications' => 'Notification', ); }
然后它将转换 address
字段中嵌入的对象到 Address
PHP 对象,并将 notifications
对象数组转换为 Notification
PHP 对象数组。所有嵌入的对象都可以是纯模型 - 它们只能扩展 \Mawelous\Yamop\Model
。
相关对象
如果对象之间存在关系(有时有),并且您想“连接”它们,这比您预期的要简单,即使是与 MongoDB
一起。您只需要在基本对象中保持相关对象的 MongoId
。
您不需要在任何地方注册它。在我看来,最好明确这样做并避免在后台进行查询。
这是魔法
一个
每个 Model
中的 joinOne
方法接受三个参数。第一个是保存相关对象 MongoId
的属性的名称,第二个是相关对象类,第三个是可选的,它是连接的属性名称。
// contest_id property holds MongoId of related Contest object $user = User::findById( new MongoId( $stringId ) )->joinOne( 'contest_id', 'Contest', 'contest') // and there it is $contest = $user->contest;
多个
每个 Model
中的 joinMany
方法也有三个参数。第一个是保存一个 MongoId
数组的属性的名称,第二个是相关对象类,第三个是可选的,它是连接的属性名称。
// contests field is array of MongoIds $user = User::findById( new MongoId( $stringId ) )->joinMany( 'contests', 'Contest', 'contests') // and you have array of contests there $contests = $user->contests;
如果您想将项目连接到项目列表,请在 Mapper
中使用 join
。参数与 joinOne
中的参数相同。
$commentsList = Comment::getMapper() ->find( array( 'contest_id' => new MongoId( $contestId ) ) ) ->join( 'user_id', 'User', 'author' ) ->limit( 10 ) ->get();
输出格式
默认获取模式将数组转换为对象,但您也可以使用 getArray
和 getJson
获取数组或 JSON。默认情况下,getArray
返回一个键为 MongoId
的字符串的数组。如果您想接收数字数组,请使用带有 false 参数的 getArray(false)
。
//first possibility Comment::getMapper() ->find( array( 'contest_id' => new MongoId( $contestId ) ) ) ->getArray(); Comment::getMapper() ->find( array( 'contest_id' => new MongoId( $contestId ) ) ) ->getJson(); /* second possibility four fetch types as constants in Mapper FETCH_OBJECT FETCH_ARRAY FETCH_NUMERIC_ARRAY FETCH_JSON */ Comment::getMapper( \Mawelous\Yamop\Mapper::FETCH_JSON ) ->find( array( 'contest_id' => new MongoId( $contestId ) ) ) ->get(); /* third possibility */ Comment::getMapper() ->setFetchType(\Mawelous\Yamop\Mapper::FETCH_JSON ) ->find( array( 'contest_id' => new MongoId( $contestId ) ) ) ->get();
您还可以通过调用 getCursor
方法来获取本地的 MongoCursor
。
分页
Yamop 支持分页,需要您的一点点帮助。它有一个 getPaginator
方法,有三个参数。第一个是每页的项目数量,第二个是当前页码,第三个是你可以传递给分页器的变量。这三个参数都是可选的。
User::getMapper() ->find( 'status' => array ( '$ne' => User::STATUS_DELETED )) ) ->sort( array( $field => $direction ) ) ->getPaginator( $perPage, $page, $options );
您的框架可能有自己的分页器。在使用 getPaginator
方法之前,您必须在扩展 Mawelous\Yamop\Mapper
的映射器中实现 _createPaginator
方法。
例如,Laravel 可以这样扩展
<?php class Mapper extends \Mawelous\Yamop\Mapper { protected function _createPaginator($results, $totalCount, $perPage, $page, $options) { return \Paginator::make( $results, $totalCount, $perPage ); } }
时间戳
在我们的对象中通常会有一个 created_at
和 updated_at
键。如果您想自动设置您的 Model
中的它们,只需声明即可
class User extends Model { ... public static $timestamps = true; ....
打印日期和时间
无论您是否有时间戳,您可能仍然想打印日期或时间。建议将日期保持为 MongoDate
,这样您就可以使用 getTime
或 getDate
来打印它,这两个方法都接受两个参数。第一个是 MongoDate
属性名,第二个是一个字符串,表示传递给 PHP date
函数的格式
//date as string $user->getDate( 'birthdate', 'Y/m/d' ); //time as string $user->getTime( 'created_at', 'Y/m/d H:i'); //time as string using default format set in $dateFormat $user->getTime( 'created_at' );
Mawelous\Yamop\Model
在其公共静态属性 $dateFormat
中定义了默认日期格式,在 $timeFormat
中定义了时间格式。如果您愿意,可以覆盖它们。
事务
实验性! - 这是 Yamop 的一个附加功能,它独立工作。它不支持两阶段提交,但至少它可以撤销更改。
这就是 Mawelous\Yamop\Transaction
的用途。首先,您必须处理错误并在其中运行 rollback
方法。
类似于这样
set_error_handler( function($code, $error, $file, $line) { Transaction::rollback(); require_once path('sys').'error'.EXT; Laravel\Error::native($code, $error, $file, $line); });
然后您可以开始使用 add
方法。使用 add
,您可以添加代码来撤销您通过保存或更新所做的更改。您可以使用闭包来完成此操作。
以下是一个示例
User::getMapper()->update( array('_id' => array ( '$in' => $userIds )), array('$inc' => array ('active_contests' => -1 )), array('multiple' => true) ); Transaction::add( function () use ( $userIds ) { User::getMapper()->update( array('_id' => array ( '$in' => $userIds )), array('$inc' => array ('active_contests' => 1 )), array('multiple' => true) ); });
现在当错误发生时,rollback
将调用所有添加的方法。
高级
多连接
为模型设置不同连接很简单。setDatabase
可以接受 MongoDb
或 MongoDbs
的数组作为参数。数组的键是连接名称。
$db1 = ( new \MongoClient( 'your_first_host' ) )->first_db; $db2 = ( new \MongoClient( 'your_second_host' ) )->second_db; \Mawelous\Yamop\Mapper::setDatabase( array( 'default' => $db1, 'special' => $db2 ) );
这是如何在模型中指定连接名称
protected static $_connectionName = 'special';
如果没有指定,模型将使用第一个连接。
问题
如有任何问题或疑问,请在此处报告
许可证
Yamop 是在 MIT 许可证条款下分发的免费软件