-
Notifications
You must be signed in to change notification settings - Fork 50
Mongo_Document
This class objectifies a Mongo document. It must be extended with your own class and used alongside a Mongo_Collection
where the database configuration name (optional) and collection name are specified. Classes which extend Mongo_Document are intended
to contain only methods which pertain to documents (e.g. validation) whereas classes which extend Mongo_Collection are
intended to contain methods which pertain to the collection as a whole (e.g. advanced queries). The most basic use of this
class is an empty extension, but all extensions of Mongo_Document must be accompanied by an extension of Mongo_Collection which
by convention is named after the document with _Collection appended (override to collection()
method to change this behavior):
class Model_Document extends Mongo_Document {}
class Model_Document_Collection extends Mongo_Collection {
public $name = 'test';
}
$document = new Model_Document();
$document->name = 'Mongo';
$document->type = 'db';
$document->save();
// db.test.save({"name":"Mongo","type":"db"});
The id field is aliased to id by default. Other aliases can also be defined using the @$aliases@ protected property. Aliases can be used
anywhere that a field name can be used including dot-notation for nesting.
$id = $document->id; // MongoId
$document->load('{name:"Mongo"}');
// db.test.findOne({"name":"Mongo"});
Methods which are intended to be overridden are {before,after}_{save,load,delete} so that special actions may be
taken when these events occur:
public function before_save()
{
$this->inc('visits');
$this->last_visit = time();
}
When a document is saved, update will be used if the document already exists, otherwise insert will be used, determined
by the presence of an _id. A document can be modified without being loaded from the database if an _id is passed to the constructor:
$doc = new Model_Document($id);
Atomic operations and updates are not executed until save() is called and operations are chainable. Example:
$doc->inc('uses.boing');
->push('used',array('type' => 'sound', 'desc' => 'boing'));
$doc->inc('uses.bonk');
->push('used',array('type' => 'sound', 'desc' => 'bonk'));
->save();
// db.test.update(
// {"_id":"one"},
// {"$inc":{"uses.boing":1,"uses.bonk":1},"$pushAll":{"used":[{"type":"sound","desc":"boing"},{"type":"sound","desc":"bonk"}]}}
// );
Documents are loaded lazily so if a property is accessed and the document is not yet loaded, it will be loaded on the first property access:
echo "$doc->name rocks!";
// Mongo rocks!
Documents are reloaded when accessing a property that was modified with an operator and then saved:
in_array($doc->roles,'admin');
// TRUE
$doc->pull('roles','admin');
in_array($doc->roles,'admin');
// TRUE
$doc->save();
in_array($doc->roles,'admin');
// FALSE
Documents can have references to other documents which will be loaded lazily and saved automatically.
class Model_Post extends Mongo_Document { protected $_references = array('user' => array('model' => 'user')); }
class Model_User extends Mongo_Document { }
$user = Mongo_Document::factory('user')->set('id','colin')->set('email','[email protected]'); $post = Mongo_Document::factory('post'); $post->user = $user; $post->title = 'MongoDb'; $post->save() // save({"_id":"colin","email":"[email protected]"}) // save({"_id":Object,"_user":"colin","title":"MongoDb"})
$post = new Model_Post($id); $post->_user; // "colin" - the post was loaded lazily. $post->user->id; // "colin" - the user object was created lazily but not loaded. $post->user->email; // "[email protected]" - now the user document was loaded as well.