A Document object's fields can represent a collection of both simple and complex data types,
as well as other Document objects. Given the following data (document) structure:
{{{
{
_id: 12345.
name: 'Acme, Inc.',
employees: {
'Larry': { email: 'larry@acme.com' },
'Curly': { email: 'curly@acme.com' },
'Moe': { email: 'moe@acme.com' }
}
}
}}}
You can query the object as follows:
{{{$acme = Company::find(12345);}}}
This returns a Document object, populated with the raw representation of the data.
{{{print_r($acme->to('array'));
Yields:
array(
'_id' => 12345,
'name' => 'Acme, Inc.',
'employees' => array(
'Larry' => array('email' => 'larry@acme.com'),
'Curly' => array('email' => 'curly@acme.com'),
'Moe' => array('email' => 'moe@acme.com')
)
)}}}
As with other database objects, a Document exposes its fields as object properties, like so:
{{{echo $acme->name; // echoes 'Acme, Inc.'}}}
However, accessing a field containing a data set will return that data set wrapped in a
sub-Document object., i.e.:
{{{$employees = $acme->employees;
returns a Document object with the data in 'employees'}}}
/** * __call * * The heart of the DocumentProxy. The method and params go in, the result is then cached and servered next time. * * @param string $method * @param array $params * @return mixed */ public function __call($method, $params) { // Is filterable? if (!in_array($method, Memoize::$objectNames[$this->_model])) { return parent::__call($method, $params); } // Variables $hash = Memoize::hashArgs($params); // Create array if it doesn't exist if (!isset($this->_memoizeResults[$method])) { $this->_memoizeResults[$method] = array(); } // Check if method + params have been ran already if (isset($this->_memoizeResults[$method][$hash])) { return $this->_memoizeResults[$method][$hash]; } // Set and return return $this->_memoizeResults[$method][$hash] = parent::__call($method, $params); }
/** * Saves model data to the database. * * @return array */ public function save() { $this->saveRelationships(); $this->appendRelationshipData(); $type = $this->exists() ? 'update' : 'create'; $doc = new Document(); $doc->set($this->to_a()); $query = new Query(array('entity' => $doc, 'model' => get_class($this), 'conditions' => array($this->primaryKey => $this->{$this->primaryKey}))); $db = static::connection(); $result = $db->{$type}($query); $exported = $doc->export(); $this->exists(true); $this->data[$this->primaryKey] = $exported['update'][$this->primaryKey]; return $result; }
/** * Tests that a modified `Document` exports the proper fields in a newly-appended nested * `Document`. * * @return void */ public function testModifiedExport() { $database = new MockDocumentSource(); $model = $this->_model; $data = array('foo' => 'bar', 'baz' => 'dib'); $doc = new Document(compact('model', 'data')); $doc->nested = array('more' => 'data'); $newData = $doc->export($database); $expected = array('foo' => 'bar', 'baz' => 'dib', 'nested' => array('more' => 'data')); $this->assertEqual($expected, $newData); $doc = new Document(array('model' => $model, 'exists' => true, 'data' => array('foo' => 'bar', 'baz' => 'dib'))); $this->assertFalse($doc->export($database)); $doc->nested = array('more' => 'data'); $this->assertEqual('data', $doc->nested->more); $modified = $doc->export($database); $this->assertEqual(array('nested' => array('more' => 'data')), $modified); $doc->update(); $this->assertFalse($doc->export($database)); $doc->more = 'cowbell'; $doc->nested->evenMore = 'cowbell'; $modified = $doc->export($database); $expected = array('nested' => array('evenMore' => 'cowbell'), 'more' => 'cowbell'); $this->assertEqual($expected, $modified); $doc->update(); $doc->nested->evenMore = 'foo!'; $this->assertEqual(array('nested' => array('evenMore' => 'foo!')), $doc->export($database)); }
/** * Ensures that the data returned from the `data()` method matches the * internal state of the object. */ public function testEnsureArrayExportFidelity() { $data = array('department_3' => 0, 4 => 0, 5 => 0, 6 => 0, '6x' => 0, 7 => 0, 8 => 0, 10 => 0, 12 => 0); $doc = new Document(compact('data')); $this->assertIdentical($data, $doc->data()); }
public function testHandlers() { $model = $this->_model; $schema = new DocumentSchema(array('fields' => array('_id' => array('type' => 'id'), 'date' => array('type' => 'date')), 'types' => array('date' => 'date'), 'handlers' => array('date' => function ($v) { return (object) $v; }))); $handlers = array('stdClass' => function ($value) { return date('d/m/Y H:i', strtotime($value->scalar)); }); $array = new Document(compact('model', 'schema', 'handlers') + array('data' => array('_id' => '2', 'date' => '2013-06-06 13:00:00'))); $expected = array('_id' => '2', 'date' => '06/06/2013 13:00'); $this->assertIdentical($expected, $array->to('array', array('indexed' => false))); }
public function testIndexesOnExportingDocument() { $schema = new Schema(array('fields' => array('_id' => array('type' => 'id'), 'accounts' => array('type' => 'object', 'array' => true), 'accounts._id' => array('type' => 'id'), 'accounts.name' => array('type' => 'string')))); $data = array('_id' => '4c8f86167675abfabd970300', 'accounts' => array(array('_id' => "4fb6e2dd3e91581fe6e75736", 'name' => 'Foo1'), array('_id' => "4fb6e2df3e91581fe6e75737", 'name' => 'Bar1'))); $model = $this->_model; $document = new Document(compact('model', 'schema', 'data')); $this->assertTrue($document->accounts instanceof DocumentSet); $this->assertTrue($document->accounts instanceof DocumentSet); $export = $document->export(); $result = Exporter::get('create', $document->export()); $this->assertTrue(isset($result['create']['accounts'][0])); $this->assertTrue(isset($result['create']['accounts'][1])); $export['data'] = array(); $result = Exporter::get('update', $export); $this->assertTrue(isset($result['update']['accounts'][0])); $this->assertTrue(isset($result['update']['accounts'][1])); }
/** * Tests that a nested key on a previously saved document gets updated properly. */ public function testExistingNestedKeyOverwrite() { $doc = new Document(array('model' => $this->_model)); $doc->{'this.that'} = 'value1'; $this->assertEqual(array('this' => array('that' => 'value1')), $doc->data()); $result = Exporter::get('create', $doc->export()); $this->assertEqual(array('create' => array('this' => array('that' => 'value1'))), $result); $doc->sync(); $doc->{'this.that'} = 'value2'; $this->assertEqual(array('this' => array('that' => 'value2')), $doc->data()); $result = Exporter::get('update', $doc->export()); $this->assertEqual(array('update' => array('this.that' => 'value2')), $result); }
/** * Tests rendering errors for nested fields. */ public function testNestedFieldError() { $doc = new Document(array('data' => array('foo' => array('bar' => 'value')))); $doc->errors(array('foo.bar' => 'Something bad happened.')); $this->form->create($doc); $result = $this->form->field('foo.bar'); $this->assertTags($result, array(array('div' => array()), 'label' => array('for' => 'FooBar'), 'Foo Bar', '/label', 'input' => array('type' => 'text', 'name' => 'foo[bar]', 'id' => 'FooBar', 'value' => 'value'), 'div' => array('class' => 'error'), 'Something bad happened.', '/div', array('/div' => array()))); }
public function testUpdatingArraysAndExporting() { $new = new Document(array('data' => array('name' => 'Acme, Inc.', 'active' => true))); $expected = array('name' => 'Acme, Inc.', 'active' => true); $result = $new->data(); $this->assertEqual($expected, $result); $new->foo = new DocumentArray(array('data' => array('bar'))); $expected = array('name' => 'Acme, Inc.', 'active' => true, 'foo' => array('bar')); $result = $new->data(); $this->assertEqual($expected, $result); $expected = 'bar'; $result = $new->foo[0]; $this->assertEqual($expected, $result); $new->foo[1] = 'baz'; $expected = 'baz'; $result = $new->data(); $this->assertEqual($expected, $result['foo'][1]); }
public function testWithArraySchema() { $model = $this->_model; $model::schema(array('_id' => array('type' => 'id'), 'list' => array('array' => true), 'list.foo' => array('type' => 'string'), 'list.bar' => array('type' => 'string'))); $doc = new Document(compact('model')); $doc->list[] = array('foo' => '!!', 'bar' => '??'); $data = array('list' => array(array('foo' => '!!', 'bar' => '??'))); $this->assertEqual($data, $doc->data()); $result = Exporter::get('create', $doc->export()); $this->assertEqual($data, $result['create']); $result = Exporter::get('update', $doc->export()); $this->assertEqual($data, $result['update']); $doc = new Document(compact('model')); $doc->list = array(); $doc->list[] = array('foo' => '!!', 'bar' => '??'); $data = array('list' => array(array('foo' => '!!', 'bar' => '??'))); $this->assertEqual($data, $doc->data()); $result = Exporter::get('create', $doc->export()); $this->assertEqual($result['create'], $data); $result = Exporter::get('update', $doc->export()); $this->assertEqual($result['update'], $data); }
public function testWithArraySchemaReusedName() { $model = $this->_model; $schema = array( '_id' => array('type' => 'id'), 'bar' => array('array' => true), 'foo' => array('type' => 'object', 'array' => true), 'foo.foo' => array('type' => 'integer'), 'foo.bar' => array('type' => 'integer') ); $doc = new Document(compact('model', 'schema')); $doc->foo[] = array('foo' => 1, 'bar' => 100); $expected = array('foo' => array(array('foo' => 1, 'bar' => 100))); $this->assertEqual($expected, $doc->data()); }
public function testInitializationWithNestedFields() { $doc = new Document(array('model' => $this->_model, 'data' => array('simple' => 'value', 'nested.foo' => 'first', 'nested.bar' => 'second', 'really.nested.key' => 'value'))); $this->assertEqual('value', $doc->simple); $this->assertEqual('first', $doc->nested->foo); $this->assertEqual('second', $doc->nested->bar); $this->assertEqual('value', $doc->really->nested->key); $result = array_keys($doc->data()); sort($result); $this->assertEqual(array('nested', 'really', 'simple'), $result); }