Skip to content
This repository was archived by the owner on Jun 29, 2024. It is now read-only.

Mongo_Document

colinmollenhour edited this page Sep 13, 2010 · 9 revisions

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.
Clone this wiki locally