Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<testsuite name="model">
<directory>tests/ModelTest.php</directory>
<directory>tests/RelationsTest.php</directory>
<directory>tests/ObjectIdRelationsTest.php</directory>
</testsuite>
<testsuite name="relations">
<directory>tests/RelationsTest.php</directory>
Expand Down
11 changes: 10 additions & 1 deletion src/Jenssegers/Mongodb/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion src/Jenssegers/Mongodb/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
42 changes: 42 additions & 0 deletions src/Jenssegers/Mongodb/Relations/BelongsTo.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php namespace Jenssegers\Mongodb\Relations;

use Illuminate\Database\Eloquent\Collection;

class BelongsTo extends \Illuminate\Database\Eloquent\Relations\BelongsTo {

/**
Expand Down Expand Up @@ -31,4 +33,44 @@ public function addEagerConstraints(array $models)
$this->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;
}

}
62 changes: 59 additions & 3 deletions src/Jenssegers/Mongodb/Relations/BelongsToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -244,7 +253,7 @@ protected function buildDictionary(Collection $results)
{
foreach ($result->$foreign as $item)
{
$dictionary[$item][] = $result;
$dictionary[(string) $item][] = $result;
}
}

Expand Down Expand Up @@ -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;
}
}
7 changes: 5 additions & 2 deletions src/Jenssegers/Mongodb/Relations/EmbedsOneOrMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Jenssegers\Mongodb\Eloquent\Collection;

abstract class EmbedsOneOrMany extends Relation {
use RelationKeysTrait;

/**
* The local key of the parent model.
Expand Down Expand Up @@ -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);
}

}
2 changes: 2 additions & 0 deletions src/Jenssegers/Mongodb/Relations/HasMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions src/Jenssegers/Mongodb/Relations/HasOne.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
57 changes: 57 additions & 0 deletions src/Jenssegers/Mongodb/Relations/HasOneOrManyTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Jenssegers\Mongodb\Relations;

use Illuminate\Database\Eloquent\Collection;

trait HasOneOrManyTrait
{
/**
* Build model dictionary keyed by the relation's foreign key.
*
* @param \Illuminate\Database\Eloquent\Collection $results
* @return array
*/
protected function buildDictionary(Collection $results)
{
$dictionary = [];

$foreign = $this->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;
}

}
40 changes: 40 additions & 0 deletions src/Jenssegers/Mongodb/Relations/RelationKeysTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
/**
* Created by PhpStorm.
* User: hooman
* Date: 8/29/2015
* Time: 2:06 AM
*/

namespace Jenssegers\Mongodb\Relations;

trait RelationKeysTrait
{
/**
* Get the key value of the parent's local key.
*
* @return mixed
*/
public function getParentKey()
{
$value = $this->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;
}
}
Loading