wasabi-web/mongodm

MongoDB ORM,支持引用、内嵌和多级继承。

1.5.0 2023-06-12 09:33 UTC

This package is auto-updated.

Last update: 2024-09-16 15:53:37 UTC


README

SensioLabsInsight Build Status Latest Stable Version Total Downloads License

介绍

Mongodm 是一个 MongoDB ORM,支持引用、内嵌甚至多级继承。它是 purekid/mongodm 的维护分支。

特性

  • ORM
  • 简单灵活
  • 支持内嵌
  • 支持引用(懒加载)
  • 支持多级继承
  • 支持本地集合操作

要求

  • PHP 5.3 或更高版本(已测试 5.5、5.6、7.0、7.1)
  • Mongodb 1.3 或更高版本
  • PHP Mongo 扩展

安装

1. 在 composer.json 中设置

	{
		"require": {
		    "wasabi-web/mongodm": "master"
		}
	}

2. 使用 composer 安装

$ php composer.phar update

数据库设置

数据库配置文件(默认位于 /vendor/wasabi-web/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 方法设置配置。

\WasabiWeb\Mongodm\MongoDB::setConfigBlock('default', array(
    'connection' => array(
        'hostnames' => 'localhost',
        'database'  => 'default',
        'options'  => array()
    )
));

//
\WasabiWeb\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。

创建一个模型并享受它

    class User extends \WasabiWeb\Mongodm\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'=>'WasabiWeb\Mongodm\Test\Model\Book','type'=>'reference'),
             // 1 to many references
            'books' => array('model'=>'WasabiWeb\Mongodm\Test\Model\Book','type'=>'references'),
            // you can define default value for attribute
            'age' => array('default'=>16,'type'=>'integer'),
            'money' => array('default'=>20.0,'type'=>'double'),
            'hobbies' => array('default'=>array('love'),'type'=>'array'),
            'born_time' => array('type'=>'timestamp'),
            'family'=>array('type'=>'object'),
            'pet_fav' => array('model'=>'WasabiWeb\Mongodm\Test\Model\Pet','type'=>'embed'),
            'pets' => array('model'=>'WasabiWeb\Mongodm\Test\Model\Pet','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);
        }

    }

模型属性支持的类型

	$types = [
	    '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'
	]

如果您将对象实例放入模型属性中,并且此属性在模型类的 $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([
		'name' => 'michael'
	]);
	echo $user->book_fav->name;

	// or, find the parent by a known reference
	$user = User::one([
		'book_fav' => $book
	]);

懒加载 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 WasabiWeb\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 \WasabiWeb\Mongodm\Model
{
    protected static $useType = false;

    protected static $collection = 'Student';
}

确保设置一个集合,否则您将获得包含每个_type的结果。

模型中的其他静态方法

	User::drop() // Drop collection
	User::ensureIndex()  // Add index for collection

模型钩子

以下钩子可用

__init__()

在构造函数完成后执行

__preInsert__()

在保存新记录之前执行

__postInsert__()

在保存新记录后执行

__preUpdate__()

在保存现有记录之前执行

__postUpdate__()

在保存现有记录后执行

__preSave__()

在保存记录之前执行

__postSave__()

在保存记录后执行

__preDelete__()

在删除记录之前执行

__postDelete__()

在删除记录后执行

特别感谢

mikelbring Paul Hrimiuc