diff --git a/README.md b/README.md
index d90fdb00a..9aa83a38e 100644
--- a/README.md
+++ b/README.md
@@ -73,31 +73,32 @@ Change your default database connection name in `app/config/database.php`:
And add a new mongodb connection:
```php
-'mongodb' => array(
+'mongodb' => [
'driver' => 'mongodb',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', 27017),
'database' => env('DB_DATABASE', ''),
'username' => env('DB_USERNAME', ''),
'password' => env('DB_PASSWORD', ''),
- 'options' => array(
- 'db' => 'admin' // sets the authentication database required by mongo 3
- )
-),
+ 'options' => [
+ 'db' => 'admin', // sets the authentication database required by mongo 3
+ ]
+ 'mongoid' => true, // sets to use mongoID object instead of mongoID as string in relations.
+],
```
You can connect to multiple servers or replica sets with the following configuration:
```php
-'mongodb' => array(
+'mongodb' => [
'driver' => 'mongodb',
- 'host' => array('server1', 'server2'),
+ 'host' => ['server1', 'server2'],
'port' => env('DB_PORT', 27017),
'database' => env('DB_DATABASE', ''),
'username' => env('DB_USERNAME', ''),
'password' => env('DB_PASSWORD', ''),
- 'options' => array('replicaSet' => 'replicaSetName')
-),
+ 'options' => ['replicaSet' => 'replicaSetName']
+],
```
Eloquent
diff --git a/phpunit.xml b/phpunit.xml
index 3f99f229f..aa7d616d7 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -31,6 +31,7 @@
tests/ModelTest.php
tests/RelationsTest.php
+ tests/ObjectIdRelationsTest.php
tests/RelationsTest.php
diff --git a/src/Jenssegers/Mongodb/Eloquent/Builder.php b/src/Jenssegers/Mongodb/Eloquent/Builder.php
index 3b2424709..88fed3114 100644
--- a/src/Jenssegers/Mongodb/Eloquent/Builder.php
+++ b/src/Jenssegers/Mongodb/Eloquent/Builder.php
@@ -171,7 +171,16 @@ protected function addHasWhere(EloquentBuilder $hasQuery, Relation $relation, $o
$query = $hasQuery->getQuery();
// Get the number of related objects for each possible parent.
- $relationCount = array_count_values($query->lists($relation->getHasCompareKey()));
+ $lists = array_map(function ($value) {
+ if($value instanceof \MongoId){
+
+ return (string) $value;
+ }
+
+ return $value;
+ }, $query->lists($relation->getHasCompareKey()));
+
+ $relationCount = array_count_values($lists);
// Remove unwanted related objects based on the operator and count.
$relationCount = array_filter($relationCount, function ($counted) use ($count, $operator)
diff --git a/src/Jenssegers/Mongodb/Model.php b/src/Jenssegers/Mongodb/Model.php
index 449d77529..ffa47e0e1 100644
--- a/src/Jenssegers/Mongodb/Model.php
+++ b/src/Jenssegers/Mongodb/Model.php
@@ -55,7 +55,8 @@ public function getIdAttribute($value)
}
// Convert MongoId's to string.
- if ($value instanceof MongoId)
+ $isObject = config('database.connections.mongodb.mongoid', false);
+ if ($value instanceof MongoId && !$isObject)
{
return (string) $value;
}
diff --git a/src/Jenssegers/Mongodb/Relations/BelongsTo.php b/src/Jenssegers/Mongodb/Relations/BelongsTo.php
index 12ab4581e..ae0c4de55 100644
--- a/src/Jenssegers/Mongodb/Relations/BelongsTo.php
+++ b/src/Jenssegers/Mongodb/Relations/BelongsTo.php
@@ -1,5 +1,7 @@
query->whereIn($key, $this->getEagerModelKeys($models));
}
+ /**
+ * Match the eagerly loaded results to their parents.
+ *
+ * @param array $models
+ * @param \Illuminate\Database\Eloquent\Collection $results
+ * @param string $relation
+ * @return array
+ */
+ public function match(array $models, Collection $results, $relation)
+ {
+ $foreign = $this->foreignKey;
+
+ $other = $this->otherKey;
+
+ // First we will get to build a dictionary of the child models by their primary
+ // key of the relationship, then we can easily match the children back onto
+ // the parents using that dictionary and the primary key of the children.
+ $dictionary = [];
+
+ foreach ($results as $result) {
+ $dictionary[(string) $result->getAttribute($other)] = $result;
+ }
+
+ // Once we have the dictionary constructed, we can loop through all the parents
+ // and match back onto their children using these keys of the dictionary and
+ // the primary key of the children to map them onto the correct instances.
+ foreach ($models as $model) {
+ if(\MongoId::isValid((string) $model->$foreign)){
+ $modelForeign = (string) $model->$foreign;
+ }else{
+ $modelForeign = $model->$foreign;
+ }
+ if (isset($dictionary[$modelForeign])) {
+ $model->setRelation($relation, $dictionary[$modelForeign]);
+ }
+ }
+
+ return $models;
+ }
+
}
diff --git a/src/Jenssegers/Mongodb/Relations/BelongsToMany.php b/src/Jenssegers/Mongodb/Relations/BelongsToMany.php
index c53d73ea6..42ff04944 100644
--- a/src/Jenssegers/Mongodb/Relations/BelongsToMany.php
+++ b/src/Jenssegers/Mongodb/Relations/BelongsToMany.php
@@ -126,7 +126,16 @@ public function sync($ids, $detaching = true)
{
$this->detach($detach);
- $changes['detached'] = (array) array_map(function ($v) { return (int) $v; }, $detach);
+ $changes['detached'] = (array) array_map(function ($v) {
+
+ $isObject = config('database.connections.mongodb.mongoid', false);
+ if($isObject && $v instanceof \MongoId){
+
+ return (string) $v;
+ }
+
+ return (int) $v;
+ }, $detach);
}
// Now we are finally ready to attach the new records. Note that we'll disable
@@ -169,7 +178,7 @@ public function attach($id, array $attributes = [], $touch = true)
{
$model = $id;
- $id = $model->getKey();
+ $id = [$model->getKey()];
// Attach the new parent id to the related model.
$model->push($this->foreignKey, $this->parent->getKey(), true);
@@ -244,7 +253,7 @@ protected function buildDictionary(Collection $results)
{
foreach ($result->$foreign as $item)
{
- $dictionary[$item][] = $result;
+ $dictionary[(string) $item][] = $result;
}
}
@@ -280,4 +289,51 @@ public function getForeignKey()
{
return $this->foreignKey;
}
+
+ /**
+ * Match the eagerly loaded results to their parents.
+ *
+ * @param array $models
+ * @param \Illuminate\Database\Eloquent\Collection $results
+ * @param string $relation
+ * @return array
+ */
+ public function match(array $models, Collection $results, $relation)
+ {
+ $dictionary = $this->buildDictionary($results);
+
+ // Once we have an array dictionary of child objects we can easily match the
+ // children back to their parent using the dictionary and the keys on the
+ // the parent models. Then we will return the hydrated models back out.
+ foreach ($models as $model) {
+ if (isset($dictionary[$key = (string) $model->getKey()])) {
+ $collection = $this->related->newCollection($dictionary[$key]);
+
+ $model->setRelation($relation, $collection);
+ }
+ }
+
+ return $models;
+ }
+
+ /**
+ * Format the sync list so that it is keyed by ID.
+ *
+ * @param array $records
+ * @return array
+ */
+ protected function formatSyncList(array $records)
+ {
+ $results = [];
+
+ foreach ($records as $id => $attributes) {
+ if (! is_array($attributes)) {
+ list($id, $attributes) = [$attributes, []];
+ }
+
+ $results[(string) $id] = $attributes;
+ }
+
+ return $results;
+ }
}
diff --git a/src/Jenssegers/Mongodb/Relations/EmbedsOneOrMany.php b/src/Jenssegers/Mongodb/Relations/EmbedsOneOrMany.php
index db6066082..16af47fa5 100644
--- a/src/Jenssegers/Mongodb/Relations/EmbedsOneOrMany.php
+++ b/src/Jenssegers/Mongodb/Relations/EmbedsOneOrMany.php
@@ -7,6 +7,7 @@
use Jenssegers\Mongodb\Eloquent\Collection;
abstract class EmbedsOneOrMany extends Relation {
+ use RelationKeysTrait;
/**
* The local key of the parent model.
@@ -401,9 +402,11 @@ public function getQualifiedParentKeyName()
*
* @return string
*/
- protected function getParentKey()
+ public function getParentKey()
{
- return $this->parent->getKey();
+ $value = $this->parent->getKey();
+
+ return $this->evaluateObjectID($value);
}
}
diff --git a/src/Jenssegers/Mongodb/Relations/HasMany.php b/src/Jenssegers/Mongodb/Relations/HasMany.php
index c59065639..19a86d245 100644
--- a/src/Jenssegers/Mongodb/Relations/HasMany.php
+++ b/src/Jenssegers/Mongodb/Relations/HasMany.php
@@ -4,6 +4,8 @@
use Illuminate\Database\Eloquent\Relations\HasMany as EloquentHasMany;
class HasMany extends EloquentHasMany {
+ use RelationKeysTrait;
+ use HasOneOrManyTrait;
/**
* Add the constraints for a relationship count query.
diff --git a/src/Jenssegers/Mongodb/Relations/HasOne.php b/src/Jenssegers/Mongodb/Relations/HasOne.php
index fb62a8386..51662ce3b 100644
--- a/src/Jenssegers/Mongodb/Relations/HasOne.php
+++ b/src/Jenssegers/Mongodb/Relations/HasOne.php
@@ -4,6 +4,8 @@
use Illuminate\Database\Eloquent\Relations\HasOne as EloquentHasOne;
class HasOne extends EloquentHasOne {
+ use RelationKeysTrait;
+ use HasOneOrManyTrait;
/**
* Add the constraints for a relationship count query.
diff --git a/src/Jenssegers/Mongodb/Relations/HasOneOrManyTrait.php b/src/Jenssegers/Mongodb/Relations/HasOneOrManyTrait.php
new file mode 100644
index 000000000..3a6e5f532
--- /dev/null
+++ b/src/Jenssegers/Mongodb/Relations/HasOneOrManyTrait.php
@@ -0,0 +1,57 @@
+getPlainForeignKey();
+
+ foreach ($results as $result) {
+ $dictionary[(string) $result->{$foreign}][] = $result;
+ }
+
+ return $dictionary;
+ }
+
+ /**
+ * Match the eagerly loaded results to their many parents.
+ *
+ * @param array $models
+ * @param \Illuminate\Database\Eloquent\Collection $results
+ * @param string $relation
+ * @param string $type
+ * @return array
+ */
+ protected function matchOneOrMany(array $models, Collection $results, $relation, $type)
+ {
+ $dictionary = $this->buildDictionary($results);
+
+ // Once we have the dictionary we can simply spin through the parent models to
+ // link them up with their children using the keyed dictionary to make the
+ // matching very convenient and easy work. Then we'll just return them.
+ foreach ($models as $model) {
+ $key = (string) $model->getAttribute($this->localKey);
+
+ if (isset($dictionary[$key])) {
+ $value = $this->getRelationValue($dictionary, $key, $type);
+
+ $model->setRelation($relation, $value);
+ }
+ }
+
+ return $models;
+ }
+
+}
diff --git a/src/Jenssegers/Mongodb/Relations/RelationKeysTrait.php b/src/Jenssegers/Mongodb/Relations/RelationKeysTrait.php
new file mode 100644
index 000000000..7a431f6ef
--- /dev/null
+++ b/src/Jenssegers/Mongodb/Relations/RelationKeysTrait.php
@@ -0,0 +1,40 @@
+parent->getAttribute($this->localKey);
+
+ return $this->evaluateObjectID($value);
+ }
+
+ /**
+ * Get the key value of the parent's local key.
+ *
+ * @param $value
+ * @return mixed
+ */
+ public function evaluateObjectID($value)
+ {
+ $isObject = config('database.connections.mongodb.mongoid', false);
+ if ($isObject && \MongoId::isValid($value)) {
+ return new \MongoId($value);
+ }
+
+ return $value;
+ }
+}
diff --git a/tests/ObjectIdRelationsTest.php b/tests/ObjectIdRelationsTest.php
new file mode 100644
index 000000000..49d3c80cc
--- /dev/null
+++ b/tests/ObjectIdRelationsTest.php
@@ -0,0 +1,531 @@
+ 'George R. R. Martin']);
+ Book::create(['title' => 'A Game of Thrones', 'author_id' => $author->_id]);
+ Book::create(['title' => 'A Clash of Kings', 'author_id' => $author->_id]);
+
+ $books = $author->books;
+ $this->assertEquals(2, count($books));
+
+ $user = User::create(['name' => 'John Doe']);
+ Item::create(['type' => 'knife', 'user_id' => $user->_id]);
+ Item::create(['type' => 'shield', 'user_id' => $user->_id]);
+ Item::create(['type' => 'sword', 'user_id' => $user->_id]);
+ Item::create(['type' => 'bag', 'user_id' => null]);
+
+ $items = $user->items;
+ $this->assertEquals(3, count($items));
+ }
+
+ public function testBelongsTo()
+ {
+ $user = User::create(['name' => 'George R. R. Martin']);
+ Book::create(['title' => 'A Game of Thrones', 'author_id' => $user->_id]);
+ $book = Book::create(['title' => 'A Clash of Kings', 'author_id' => $user->_id]);
+
+ $author = $book->author;
+ $this->assertEquals('George R. R. Martin', $author->name);
+
+ $user = User::create(['name' => 'John Doe']);
+ $item = Item::create(['type' => 'sword', 'user_id' => $user->_id]);
+
+ $owner = $item->user;
+ $this->assertEquals('John Doe', $owner->name);
+
+ $book = Book::create(['title' => 'A Clash of Kings']);
+ $this->assertEquals(null, $book->author);
+ }
+
+ public function testHasOne()
+ {
+ $user = User::create(['name' => 'John Doe']);
+ Role::create(['type' => 'admin', 'user_id' => $user->_id]);
+
+ $role = $user->role;
+ $this->assertEquals('admin', $role->type);
+ $this->assertEquals($user->_id, $role->user_id);
+
+ $user = User::create(['name' => 'Jane Doe']);
+ $role = new Role(['type' => 'user']);
+ $user->role()->save($role);
+
+ $role = $user->role;
+ $this->assertEquals('user', $role->type);
+ $this->assertEquals($user->_id, $role->user_id);
+
+ $user = User::where('name', 'Jane Doe')->first();
+ $role = $user->role;
+ $this->assertEquals('user', $role->type);
+ $this->assertEquals($user->_id, $role->user_id);
+ }
+
+ public function testWithBelongsTo()
+ {
+ $user = User::create(['name' => 'John Doe']);
+ Item::create(['type' => 'knife', 'user_id' => $user->_id]);
+ Item::create(['type' => 'shield', 'user_id' => $user->_id]);
+ Item::create(['type' => 'sword', 'user_id' => $user->_id]);
+ Item::create(['type' => 'bag', 'user_id' => null]);
+
+ $items = Item::with('user')->orderBy('user_id', 'desc')->get();
+
+ $user = $items[0]->getRelation('user');
+ $this->assertInstanceOf('User', $user);
+ $this->assertEquals('John Doe', $user->name);
+ $this->assertEquals(1, count($items[0]->getRelations()));
+ $this->assertEquals(null, $items[3]->getRelation('user'));
+ }
+
+ public function testWithHashMany()
+ {
+ $user = User::create(['name' => 'John Doe']);
+ Item::create(['type' => 'knife', 'user_id' => $user->_id]);
+ Item::create(['type' => 'shield', 'user_id' => $user->_id]);
+ Item::create(['type' => 'sword', 'user_id' => $user->_id]);
+ Item::create(['type' => 'bag', 'user_id' => null]);
+
+ $user = User::with('items')->find($user->_id);
+
+ $items = $user->getRelation('items');
+ $this->assertEquals(3, count($items));
+ $this->assertInstanceOf('Item', $items[0]);
+ }
+
+ public function testWithHasOne()
+ {
+ $user = User::create(['name' => 'John Doe']);
+ Role::create(['type' => 'admin', 'user_id' => $user->_id]);
+ Role::create(['type' => 'guest', 'user_id' => $user->_id]);
+
+ $user = User::with('role')->find($user->_id);
+
+ $role = $user->getRelation('role');
+ $this->assertInstanceOf('Role', $role);
+ $this->assertEquals('admin', $role->type);
+ }
+
+ public function testEasyRelation()
+ {
+ // Has Many
+ $user = User::create(['name' => 'John Doe']);
+ $item = Item::create(['type' => 'knife']);
+ $user->items()->save($item);
+
+ $user = User::find($user->_id);
+ $items = $user->items;
+ $this->assertEquals(1, count($items));
+ $this->assertInstanceOf('Item', $items[0]);
+ $this->assertEquals($user->_id, $items[0]->user_id);
+
+ // Has one
+ $user = User::create(['name' => 'John Doe']);
+ $role = Role::create(['type' => 'admin']);
+ $user->role()->save($role);
+
+ $user = User::find($user->_id);
+ $role = $user->role;
+ $this->assertInstanceOf('Role', $role);
+ $this->assertEquals('admin', $role->type);
+ $this->assertEquals($user->_id, $role->user_id);
+ }
+
+ public function testBelongsToMany()
+ {
+ $user = User::create(['name' => 'John Doe']);
+
+ // Add 2 clients
+ $user->clients()->save(new Client(['name' => 'Pork Pies Ltd.']));
+ $user->clients()->create(['name' => 'Buffet Bar Inc.']);
+
+ // Refetch
+ $user = User::with('clients')->find($user->_id);
+ $client = Client::with('users')->first();
+
+ // Check for relation attributes
+ $this->assertTrue(array_key_exists('user_ids', $client->getAttributes()));
+ $this->assertTrue(array_key_exists('client_ids', $user->getAttributes()));
+
+ $clients = $user->getRelation('clients');
+ $users = $client->getRelation('users');
+
+ $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $users);
+ $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $clients);
+ $this->assertInstanceOf('Client', $clients[0]);
+ $this->assertInstanceOf('User', $users[0]);
+ $this->assertCount(2, $user->clients);
+ $this->assertCount(1, $client->users);
+
+ // Now create a new user to an existing client
+ $user = $client->users()->create(['name' => 'Jane Doe']);
+
+ $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $user->clients);
+ $this->assertInstanceOf('Client', $user->clients->first());
+ $this->assertCount(1, $user->clients);
+
+ // Get user and unattached client
+ $user = User::where('name', '=', 'Jane Doe')->first();
+ $client = Client::Where('name', '=', 'Buffet Bar Inc.')->first();
+
+ // Check the models are what they should be
+ $this->assertInstanceOf('Client', $client);
+ $this->assertInstanceOf('User', $user);
+
+ // Assert they are not attached
+ $this->assertFalse(in_array($client->_id, $user->client_ids));
+ $this->assertFalse(in_array($user->_id, $client->user_ids));
+ $this->assertCount(1, $user->clients);
+ $this->assertCount(1, $client->users);
+
+ // Attach the client to the user
+ $user->clients()->attach($client);
+
+ // Get the new user model
+ $user = User::where('name', '=', 'Jane Doe')->first();
+ $client = Client::Where('name', '=', 'Buffet Bar Inc.')->first();
+
+ // Assert they are attached
+ $this->assertTrue(in_array($client->_id, $user->client_ids));
+ $this->assertTrue(in_array($user->_id, $client->user_ids));
+ $this->assertCount(2, $user->clients);
+ $this->assertCount(2, $client->users);
+
+ // Detach clients from user
+ $user->clients()->sync([]);
+
+ // Get the new user model
+ $user = User::where('name', '=', 'Jane Doe')->first();
+ $client = Client::Where('name', '=', 'Buffet Bar Inc.')->first();
+
+ // Assert they are not attached
+ $this->assertFalse(in_array($client->_id, $user->client_ids));
+ $this->assertFalse(in_array($user->_id, $client->user_ids));
+ $this->assertCount(0, $user->clients);
+ $this->assertCount(1, $client->users);
+ }
+
+ public function testBelongsToManyAttachesExistingModels()
+ {
+ $user = User::create(['name' => 'John Doe', 'client_ids' => ['1234523']]);
+
+ $clients = [
+ Client::create(['name' => 'Pork Pies Ltd.'])->_id,
+ Client::create(['name' => 'Buffet Bar Inc.'])->_id,
+ ];
+
+ $moreClients = [
+ Client::create(['name' => 'synced Boloni Ltd.'])->_id,
+ Client::create(['name' => 'synced Meatballs Inc.'])->_id,
+ ];
+
+ // Sync multiple records
+ $user->clients()->sync($clients);
+
+ $user = User::with('clients')->find($user->_id);
+
+ // Assert non attached ID's are detached succesfully
+ $this->assertFalse(in_array('1234523', $user->client_ids));
+
+ // Assert there are two client objects in the relationship
+ $this->assertCount(2, $user->clients);
+
+ // Add more clients
+ $user->clients()->sync($moreClients);
+
+ // Refetch
+ $user = User::with('clients')->find($user->_id);
+
+ // Assert there are now still 2 client objects in the relationship
+ $this->assertCount(2, $user->clients);
+
+ // Assert that the new relationships name start with synced
+ $this->assertStringStartsWith('synced', $user->clients[0]->name);
+ $this->assertStringStartsWith('synced', $user->clients[1]->name);
+ }
+
+ public function testBelongsToManySync()
+ {
+ // create test instances
+ $user = User::create(['name' => 'John Doe']);
+ $client1 = Client::create(['name' => 'Pork Pies Ltd.'])->_id;
+ $client2 = Client::create(['name' => 'Buffet Bar Inc.'])->_id;
+
+ // Sync multiple
+ $user->clients()->sync([$client1, $client2]);
+ $this->assertCount(2, $user->clients);
+
+ // Refresh user
+ $user = User::where('name', '=', 'John Doe')->first();
+
+ // Sync single
+ $user->clients()->sync([$client1]);
+ $this->assertCount(1, $user->clients);
+ }
+
+ public function testBelongsToManyAttachArray()
+ {
+ $user = User::create(['name' => 'John Doe']);
+ $client1 = Client::create(['name' => 'Test 1'])->_id;
+ $client2 = Client::create(['name' => 'Test 2'])->_id;
+
+ $user = User::where('name', '=', 'John Doe')->first();
+ $user->clients()->attach([$client1, $client2]);
+ $this->assertCount(2, $user->clients);
+ }
+
+ public function testBelongsToManySyncAlreadyPresent()
+ {
+ $user = User::create(['name' => 'John Doe']);
+ $client1 = Client::create(['name' => 'Test 1'])->_id;
+ $client2 = Client::create(['name' => 'Test 2'])->_id;
+
+ $user->clients()->sync([$client1, $client2]);
+ $this->assertCount(2, $user->clients);
+
+ $user = User::where('name', '=', 'John Doe')->first();
+ $user->clients()->sync([$client1]);
+ $this->assertCount(1, $user->clients);
+
+ $user = User::where('name', '=', 'John Doe')->first()->toArray();
+ $this->assertCount(1, $user['client_ids']);
+ }
+
+ public function testBelongsToManyCustom()
+ {
+ $user = User::create(['name' => 'John Doe']);
+ $group = $user->groups()->create(['name' => 'Admins']);
+
+ // Refetch
+ $user = User::find($user->_id);
+ $group = Group::find($group->_id);
+
+ // Check for custom relation attributes
+ $this->assertTrue(array_key_exists('users', $group->getAttributes()));
+ $this->assertTrue(array_key_exists('groups', $user->getAttributes()));
+
+ // Assert they are attached
+ $this->assertTrue(in_array($group->_id, $user->groups));
+ $this->assertTrue(in_array($user->_id, $group->users));
+ $this->assertEquals($group->_id, $user->groups()->first()->_id);
+ $this->assertEquals($user->_id, $group->users()->first()->_id);
+ }
+
+ public function testMorph()
+ {
+ $user = User::create(['name' => 'John Doe']);
+ $client = Client::create(['name' => 'Jane Doe']);
+
+ $photo = Photo::create(['url' => 'http://graph.facebook.com/john.doe/picture']);
+ $photo = $user->photos()->save($photo);
+
+ $this->assertEquals(1, $user->photos->count());
+ $this->assertEquals($photo->id, $user->photos->first()->id);
+
+ $user = User::find($user->_id);
+ $this->assertEquals(1, $user->photos->count());
+ $this->assertEquals($photo->id, $user->photos->first()->id);
+
+ $photo = Photo::create(['url' => 'http://graph.facebook.com/jane.doe/picture']);
+ $client->photo()->save($photo);
+
+ $this->assertNotNull($client->photo);
+ $this->assertEquals($photo->id, $client->photo->id);
+
+ $client = Client::find($client->_id);
+ $this->assertNotNull($client->photo);
+ $this->assertEquals($photo->id, $client->photo->id);
+
+ $photo = Photo::first();
+ $this->assertEquals($photo->imageable->name, $user->name);
+
+ //todo need to fix the morph relations
+// $user = User::with('photos')->find($user->_id);
+// $relations = $user->getRelations();
+// $this->assertTrue(array_key_exists('photos', $relations));
+// $this->assertEquals(1, $relations['photos']->count());
+
+// $photos = Photo::with('imageable')->get();
+// $relations = $photos[0]->getRelations();
+// $this->assertTrue(array_key_exists('imageable', $relations));
+// $this->assertInstanceOf('User', $relations['imageable']);
+//
+// $relations = $photos[1]->getRelations();
+// $this->assertTrue(array_key_exists('imageable', $relations));
+// $this->assertInstanceOf('Client', $relations['imageable']);
+ }
+
+ public function testHasManyHas()
+ {
+ $author1 = User::create(['name' => 'George R. R. Martin']);
+ $author1->books()->create(['title' => 'A Game of Thrones', 'rating' => 5]);
+ $author1->books()->create(['title' => 'A Clash of Kings', 'rating' => 5]);
+ $author2 = User::create(['name' => 'John Doe']);
+ $author2->books()->create(['title' => 'My book', 'rating' => 2]);
+ User::create(['name' => 'Anonymous author']);
+ Book::create(['title' => 'Anonymous book', 'rating' => 1]);
+
+ $authors = User::has('books')->get();
+ $this->assertCount(2, $authors);
+ $this->assertEquals('George R. R. Martin', $authors[0]->name);
+ $this->assertEquals('John Doe', $authors[1]->name);
+
+ $authors = User::has('books', '>', 1)->get();
+ $this->assertCount(1, $authors);
+
+ $authors = User::has('books', '<', 5)->get();
+ $this->assertCount(3, $authors);
+
+ $authors = User::has('books', '>=', 2)->get();
+ $this->assertCount(1, $authors);
+
+ $authors = User::has('books', '<=', 1)->get();
+ $this->assertCount(2, $authors);
+
+ $authors = User::has('books', '=', 2)->get();
+ $this->assertCount(1, $authors);
+
+ $authors = User::has('books', '!=', 2)->get();
+ $this->assertCount(2, $authors);
+
+ $authors = User::has('books', '=', 0)->get();
+ $this->assertCount(1, $authors);
+
+ $authors = User::has('books', '!=', 0)->get();
+ $this->assertCount(2, $authors);
+
+ $authors = User::whereHas('books', function ($query)
+ {
+ $query->where('rating', 5);
+
+ })->get();
+ $this->assertCount(1, $authors);
+
+ $authors = User::whereHas('books', function ($query)
+ {
+ $query->where('rating', '<', 5);
+
+ })->get();
+ $this->assertCount(1, $authors);
+ }
+
+ public function testHasOneHas()
+ {
+ $user1 = User::create(['name' => 'John Doe']);
+ $user1->role()->create(['title' => 'admin']);
+ $user2 = User::create(['name' => 'Jane Doe']);
+ $user2->role()->create(['title' => 'reseller']);
+ User::create(['name' => 'Mark Moe']);
+ Role::create(['title' => 'Customer']);
+
+ $users = User::has('role')->get();
+ $this->assertCount(2, $users);
+ $this->assertEquals('John Doe', $users[0]->name);
+ $this->assertEquals('Jane Doe', $users[1]->name);
+
+ $users = User::has('role', '=', 0)->get();
+ $this->assertCount(1, $users);
+
+ $users = User::has('role', '!=', 0)->get();
+ $this->assertCount(2, $users);
+ }
+
+ public function testNestedKeys()
+ {
+ $client = Client::create([
+ 'data' => [
+ 'client_id' => 35298,
+ 'name' => 'John Doe',
+ ],
+ ]);
+
+ $address = $client->addresses()->create([
+ 'data' => [
+ 'address_id' => 1432,
+ 'city' => 'Paris',
+ ],
+ ]);
+
+ $client = Client::where('data.client_id', 35298)->first();
+ $this->assertEquals(1, $client->addresses->count());
+
+ $address = $client->addresses->first();
+ $this->assertEquals('Paris', $address->data['city']);
+
+ $client = Client::with('addresses')->first();
+ $this->assertEquals('Paris', $client->addresses->first()->data['city']);
+ }
+
+ public function testDoubleSaveOneToMany()
+ {
+ $author = User::create(['name' => 'George R. R. Martin']);
+ $book = Book::create(['title' => 'A Game of Thrones']);
+
+ $author->books()->save($book);
+ $author->books()->save($book);
+ $author->save();
+ $this->assertEquals(1, $author->books()->count());
+ $this->assertEquals($author->_id, $book->author_id);
+
+ $author = User::where('name', 'George R. R. Martin')->first();
+ $book = Book::where('title', 'A Game of Thrones')->first();
+ $this->assertEquals(1, $author->books()->count());
+ $this->assertEquals($author->_id, $book->author_id);
+
+ $author->books()->save($book);
+ $author->books()->save($book);
+ $author->save();
+ $this->assertEquals(1, $author->books()->count());
+ $this->assertEquals($author->_id, $book->author_id);
+ }
+
+ public function testDoubleSaveManyToMany()
+ {
+ $user = User::create(['name' => 'John Doe']);
+ $client = Client::create(['name' => 'Admins']);
+
+ $user->clients()->save($client);
+ $user->clients()->save($client);
+ $user->save();
+
+ $this->assertEquals(1, $user->clients()->count());
+ $this->assertEquals([$user->_id], $client->user_ids);
+ $this->assertEquals([$client->_id], $user->client_ids);
+
+ $user = User::where('name', 'John Doe')->first();
+ $client = Client::where('name', 'Admins')->first();
+ $this->assertEquals(1, $user->clients()->count());
+ $this->assertEquals([$user->_id], $client->user_ids);
+ $this->assertEquals([$client->_id], $user->client_ids);
+
+ $user->clients()->save($client);
+ $user->clients()->save($client);
+ $user->save();
+ $this->assertEquals(1, $user->clients()->count());
+ $this->assertEquals([$user->_id], $client->user_ids);
+ $this->assertEquals([$client->_id], $user->client_ids);
+ }
+
+}