purekid / mongodm
MongoDB ORM,支持引用、内嵌和多级继承。
Requires
- alcaeus/mongo-php-adapter: 1.0.9
Requires (Dev)
- chriskite/phactory: dev-master
This package is auto-updated.
Last update: 2024-09-11 18:12:39 UTC
README
简介
Mongodm 是一个 MongoDB ORM,支持引用、内嵌和多级继承。
功能
- ORM
- 简单灵活
- 支持内嵌
- 支持引用(懒加载)
- 支持多级继承
- 支持本地集合操作
需求
- PHP 5.3 或更高版本(已测试 5.5、5.6、7.0、7.1)
- Mongodb 1.3 或更高版本
- PHP Mongo 扩展
安装
1. 在 composer.json 中设置
{ "require": { "purekid/mongodm": "dev-master" } }
2. 使用 composer 安装
$ php composer.phar update
设置数据库
数据库配置文件(默认位于 /vendor/purekid/mongodm/config.php)
return array( 'default' => array( 'connection' => array( 'hostnames' => 'localhost', 'database' => 'default', // 'username' => '', // 'password' => '', ) ), 'production' => array( 'connection' => array( 'hostnames' => 'localhost', 'database' => 'production', 'options' => array('replicaSet' => 'rs0') ) ) );
身份验证
身份验证信息通过选项数组传递。如果您没有指定 authSource,则 PHP Mongo 驱动程序将选择 "admin" 数据库。
$config = array( 'connection' => array(
'hostnames' => '<host>:<port>',
'database' => '<databasename>',
'options' => [ "connectTimeoutMS" => 500 , "username" => "admin", "password" => "<password>", "authSource" => "admin"] )
);
在应用程序中设置数据库
1. 您可以使用 MongoDB::setConfigBlock
方法设置配置。
\Purekid\Mongodm\MongoDB::setConfigBlock('default', array( 'connection' => array( 'hostnames' => 'localhost', 'database' => 'default', 'options' => array() ) )); // \Purekid\Mongodm\MongoDB::setConfigBlock('auth', array( 'connection' => array( 'hostnames' => 'localhost', 'database' => 'authDB', 'options' => array() ) ));
2. 或者,您可以将配置文件复制到您的项目中,然后定义一个全局常量 'MONGODM_CONFIG' 来指定其位置。
//in a global initialization place define('MONGODM_CONFIG',__DIR__."/../config/mongodm.php");
使用 APPLICATION_ENV 选择配置部分
Mongodm 使用哪个配置部分?Mongodm 默认选择 'default' 部分。
您有两种方式来指定部分
1. 在模型中设置 '$config' 属性,您可以在下面的示例中找到这个属性。
2. 使用环境常量 'APPLICATION_ENV',这个常量可以通过 web 服务器、您的代码或 shell 环境设置。在这种情况下,您应该设置 $config='default' 或在您自己的模型类中不声明 $config。
创建一个模型并享受它
use Purekid\Mongodm\Model; class User extends Model { static $collection = "user"; /** use specific config section **/ public static $config = 'testing'; /** specific definition for attributes, not necessary! **/ protected static $attrs = array( // 1 to 1 reference 'book_fav' => array('model'=>'Purekid\Mongodm\Test\Model\Book','type'=> Model::DATA_TYPE_REFERENCE), // 1 to many references 'books' => array('model'=>'Purekid\Mongodm\Test\Model\Book','type'=> Model::DATA_TYPE_REFERENCES), // you can define default value for attribute 'age' => array('default'=>16,'type'=> Model::DATA_TYPE_INTEGER), 'money' => array('default'=>20.0,'type'=> Model::DATA_TYPE_DOUBLE), 'hobbies' => array('default'=>array('love'),'type'=> Model::DATA_TYPE_ARRAY), 'born_time' => array('type'=> Model::DATA_TYPE_TIMESTAMP), 'family'=>array('type'=> Model::DATA_TYPE_OBJECT), 'pet_fav' => array('model'=>'Purekid\Mongodm\Test\Model\Pet','type'=> Model::DATA_TYPE_EMBED), 'pets' => array('model'=>'Purekid\Mongodm\Test\Model\Pet','type'=> Model::DATA_TYPE_EMBEDS), ); public function setFirstName($name) { $name = ucfirst(strtolower($name)); $this->__setter('firstName', $name); } public function getLastName($name) { $name = $this->__getter('name'); return strtoupper($name); } }
模型属性支持的数据类型
[ 'mixed', // mixed type 'string', 'reference', // 1 : 1 reference 'references', // 1 : many references 'embed', 'embeds', 'integer', 'int', // alias of 'integer' 'double', // float 'timestamp', // store as MongoTimestamp in Mongodb 'date', // store as DateTime 'boolean', // true or false 'array', 'object' ]; const DATA_TYPE_ARRAY = 'array'; const DATA_TYPE_BOOL = 'bool'; const DATA_TYPE_BOOLEAN = 'boolean'; const DATA_TYPE_DATE = 'date'; const DATA_TYPE_DBL = 'dbl'; const DATA_TYPE_DOUBLE = 'double'; const DATA_TYPE_FLT = 'flt'; const DATA_TYPE_FLOAT = 'float'; const DATA_TYPE_EMBED = 'embed'; const DATA_TYPE_EMBEDS = 'embeds'; const DATA_TYPE_INT = 'int'; const DATA_TYPE_INTEGER = 'integer'; const DATA_TYPE_MIXED = 'mixed'; const DATA_TYPE_REFERENCE = 'reference'; const DATA_TYPE_REFERENCES = 'references'; const DATA_TYPE_STR = 'str'; const DATA_TYPE_STRING = 'string'; const DATA_TYPE_TIMESTAMP = 'timestamp'; const DATA_TYPE_OBJ = 'obj'; const DATA_TYPE_OBJECT = 'object';
如果您将对象实例放入模型属性中,并且该属性在模型类的 $attrs 中未定义,则模型保存时将省略该属性的值。
$object = new \stdClass(); $object->name = 'ooobject'; $user = new User(); $user->name = 'michael'; $user->myobject = $object; // this attribute will be omitted when saving to DB $user->save();
模型 CRUD
创建
$user = new User(); $user->name = "Michael"; $user->age = 18; $user->save();
使用初始值创建
$user = new User( array('name'=>"John") ); $user->age = 20; $user->save();
使用设置方法创建
$user->setLastName('Jones'); // Alias of $user->lastName = 'Jones'; $user->setFirstName('John'); // Implements setFirstName() method
设置和获取值
您可以通过变量 $user->name = "John"
或方法 $user->getName()
来设置/获取值。
使用变量或方法设置
// no "set" method exists $user->lastName = 'Jones'; $user->setLastName('Jones'); // "set" method exists implements setFirstName() $user->firstName = 'jOhn'; // "John" $user->setFirstName('jOhn'); // "John"
使用变量或方法获取
// "get" method exists implements getLastName() print $user->lastName; // "JONES" print $user->getLastName(); // "JONES" // no "get" method print $user->firstName; // "John" print $user->setFirstName('John'); // "John"
更新
$user->age = 19;
通过数组更新属性
$user->update( array('age'=>18,'hobbies'=>array('music','game') ) ); $user->save();
取消设置属性
$user->unset('age'); $user->unset( array('age','hobbies') ); //or unset($user->age);
检索单个记录
$user = User::one( array('name'=>"michael" ) );
通过 MongoId 检索一条记录
$id = "517c850641da6da0ab000004"; $id = new \MongoId('517c850641da6da0ab000004'); //another way $user = User::id( $id );
检索记录
检索名称为 'Michael' 且拥有的书籍账户等于 2 的记录
$params = array( 'name'=>'Michael','books'=>array('$size'=>2) ); $users = User::find($params); // $users is instance of Collection echo $users->count();
检索所有记录
$users = User::all();
计数记录
$count = User::count(array('age'=>16));
删除记录
$user = User::one(); $user->delete();
关系 - 引用
懒加载 1:1 关系记录
$book = new Book(); $book->name = "My Love"; $book->price = 15; $book->save(); // !!!remember you must save book before!!! $user->book_fav = $book; $user->save(); // now you can do this $user = User::one( array('name'=>"michael" ) ); echo $user->book_fav->name;
懒加载 1:n 关系记录
$user = User::one(); $id = $user->getId(); $book1 = new Book(); $book1->name = "book1"; $book1->save(); $book2 = new Book(); $book2->name = "book2"; $book2->save(); $user->books = array($book1,$book2); //also you can $user->books = Collection::make(array($book1,$book2)); $user->save(); //somewhere , load these books $user = User::id($id); $books = $user->books; // $books is a instance of Collection
关系 - 内嵌
单个内嵌
$pet = new Pet(); $pet->name = "putty"; $user->pet_fav = $pet; $user->save(); // now you can do this $user = User::one( array('name'=>"michael" ) ); echo $user->pet_fav->name;
内嵌
$user = User::one(); $id = $user->getId(); $pet_dog = new Pet(); $pet_dog->name = "puppy"; $pet_dog->save(); $pet_cat = new Pet(); $pet_cat->name = "kitty"; $pet_cat->save(); $user->pets = array($pet_cat,$pet_dog); //also you can $user->pets = Collection::make(array($pet_cat,$pet_dog)); $user->save(); $user = User::id($id); $pets = $user->pets;
集合
$users 是集合实例
$users = User::find( array( 'name'=>'Michael','books'=>array('$size'=>2) ) ); $users_other = User::find( array( 'name'=>'John','books'=>array('$size'=>2) ) );
保存
$users->save() ; // foreach($users as $user) { $user->save(); }
删除
$users->delete() ; // foreach($users as $user) { $user->delete(); }
计数
$users->count(); $users->isEmpty();
迭代
foreach($users as $user) { } // OR use Closure $users->each(function($user){ })
排序
//sort by age desc $users->sortBy(function($user){ return $user->age; }); //sort by name asc $users->sortBy(function($user){ return $user->name; } , true); //reverse collection items $users->reverse();
切片和取
$users->slice(0,1); $users->take(2);
映射
$func = function($user){ if( $user->age >= 18 ){ $user->is_adult = true; } return $user; }; $users->map($func)->save();
过滤
$func = function($user){ if( $user->age >= 18 ){ return true; } } $adults = $users->filter($func); // $adults is a new collection
通过对象实例确定记录是否存在于集合中
$john = User::one(array("name"=>"John")); $users->has($john)
通过数字索引确定记录是否存在于集合中
$users->has(0)
通过 MongoID 确定记录是否存在于集合中
$users->has('518c6a242d12d3db0c000007')
通过数字索引获取记录
$users->get(0)
通过 MongoID 获取记录
$users->get('518c6a242d12d3db0c000007')
通过数字索引删除记录
$users->remove(0)
通过 MongoID 删除记录
$users->remove('518c6a242d12d3db0c000007')
将单个记录添加到集合
$bob = new User( array("name"=>"Bob")); $bob->save(); $users->add($bob);
将记录添加到集合
$bob = new User( array("name"=>"Bob")); $bob->save(); $lisa = new User( array("name"=>"Lisa")); $lisa->save(); $users->add( array($bob,$lisa) );
合并两个集合
$users->add($users_other); // the collection $users_other appends to end of $users
将数据导出到数组
$users->toArray();
继承
定义可多级继承的模型
use Purekid\Mongodm\Model; namespace Demo; class Human extends Model{ static $collection = "human"; protected static $attrs = array( 'name' => array('default'=>'anonym','type'=>'string'), 'age' => array('type'=>'integer'), 'gender' => array('type'=>'string'), 'dad' => array('type'=>'reference','model'=>'Demo\Human'), 'mum' => array('type'=>'reference','model'=>'Demo\Human'), 'friends' => array('type'=>'references','model'=>'Demo\Human'), ) } class Student extends Human{ protected static $attrs = array( 'grade' => array('type'=>'string'), 'classmates' => array('type'=>'references','model'=>'Demo\Student'), ) }
使用
$bob = new Student( array('name'=>'Bob','age'=> 17 ,'gender'=>'male' ) ); $bob->save(); $john = new Student( array('name'=>'John','age'=> 16 ,'gender'=>'male' ) ); $john->save(); $lily = new Student( array('name'=>'Lily','age'=> 16 ,'gender'=>'female' ) ); $lily->save(); $lisa = new Human( array('name'=>'Lisa','age'=>41 ,'gender'=>'female' ) ); $lisa->save(); $david = new Human( array('name'=>'David','age'=>42 ,'gender'=>'male') ); $david->save(); $bob->dad = $david; $bob->mum = $lisa; $bob->classmates = array( $john, $lily ); $bob->save();
检索和检查值
$bob = Student::one( array("name"=>"Bob") ); echo $bob->dad->name; // David $classmates = $bob->classmates; echo $classmates->count(); // 2 var_dump($classmates->get(0)); // john
检索子类
检索所有人类记录,由于它是顶级类,因此查询不包含 '_type'。
$humans = Human::all();
检索所有学生记录,由于它是子类,因此查询包含 { "_type":"Student" }。
$students = Student::all();
检索不包含 (不) _type
的子类
要检索不包含 _type
条件(即 { "_type":"Student" }
)的记录
class Student extends \Purekid\Mongodm\Model { protected static $useType = false; protected static $collection = 'Student'; }
请确保设置一个集合,否则您将得到包含所有 _type
的结果。
Model 中的其他静态方法
User::drop() // Drop collection User::ensureIndex() // Add index for collection
模型钩子
以下钩子可用
__init()
在构造函数完成后执行
__preInsert()
在保存新记录之前执行
__postInsert()
在保存新记录后执行
__preUpdate()
在保存现有记录之前执行
__postUpdate()
在保存现有记录后执行
__preSave()
在保存记录之前执行
__postSave()
在保存记录后执行
__preDelete()
在删除记录之前执行
__postDelete()
在删除记录后执行