Commit 177ab042 authored by Jens Segers's avatar Jens Segers

Tweaking embedsMany, check issue #138

parent 828a490d
......@@ -359,6 +359,43 @@ The belongsToMany relation will not use a pivot "table", but will push id's to a
Other relations are not yet supported, but may be added in the future. Read more about these relations on http://four.laravel.com/docs/eloquent#relationships
### EmbedsMany Relations
If you want to embed documents, rather than referencing them, you can use the `embedsMany` relation:
use Jenssegers\Mongodb\Model as Eloquent;
class User extends Eloquent {
public function books()
{
return $this->embedsMany('Book');
}
}
Now we can access the post's comments through the dynamic property:
$books = User::first()->books;
Inserting and updating embedded documents works just like the `belongsTo` relation:
$book = new Book(array('title' => 'A Game of Thrones'));
$user = User::first();
$book = $user->books()->save($book);
You can remove an embedded document by using the `destroy()` method:
$book = $user->books()->first();
$user->books()->destroy($book->_id);
Again, you may override the conventional local key by passing a second argument to the embedsMany method:
return $this->embedsMany('Book', 'local_key');
### MySQL Relations
If you're using a hybrid MongoDB and SQL setup, you're in luck! The model will automatically return a MongoDB- or SQL-relation based on the type of the related model. Of course, if you want this functionality to work both ways, your SQL-models will need to extend `Jenssegers\Eloquent\Model`. Note that this functionality only works for hasOne, hasMany and belongsTo relations.
......
<?php namespace Jenssegers\Eloquent;
use LogicException;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
......@@ -9,7 +8,6 @@ use Illuminate\Database\Eloquent\Relations\Relation;
use Jenssegers\Mongodb\Relations\BelongsTo;
use Jenssegers\Mongodb\Relations\BelongsToMany;
use Jenssegers\Mongodb\Relations\EmbedsMany;
use Jenssegers\Mongodb\Relations\EmbeddedRelation;
use Jenssegers\Mongodb\Query\Builder as QueryBuilder;
abstract class Model extends \Illuminate\Database\Eloquent\Model {
......@@ -230,36 +228,31 @@ abstract class Model extends \Illuminate\Database\Eloquent\Model {
* @param string $collection
* @return \Illuminate\Database\Eloquent\Relations\EmbedsMany
*/
protected function embedsMany($related, $collection = null)
protected function embedsMany($related, $localKey = null, $foreignKey = null, $relation = null)
{
// If no collection name was provided, we assume that the standard is the
// related model camel_cased, pluralized and suffixed with '_ids'
if (is_null($collection))
if (is_null($localKey))
{
$collection = str_plural(snake_case($related)) . '_ids';
$localKey = snake_case(str_plural($related)) . '_ids';
}
return new EmbedsMany($this, $related, $collection);
}
/**
* Get a relationship value from a method.
*
* @param string $key
* @param string $camelKey
* @return mixed
*/
protected function getRelationshipFromMethod($key, $camelKey)
{
$relations = $this->$camelKey();
if (is_null($foreignKey))
{
$foreignKey = snake_case(class_basename($this));
}
if ( ! $relations instanceof Relation and ! $relations instanceof EmbeddedRelation)
// If no relation name was given, we will use this debug backtrace to extract
// the calling method's name and use that as the relationship name as most
// of the time this will be what we desire to use for the relatinoships.
if (is_null($relation))
{
throw new LogicException('Relationship method must return an object of type '
. 'Illuminate\Database\Eloquent\Relations\Relation or Jenssegers\Mongodb\Relations\EmbeddedRelation');
list(, $caller) = debug_backtrace(false);
$relation = $caller['function'];
}
return $this->relations[$key] = $relations->getResults();
$query = $this->newQuery();
return new EmbedsMany($query, $this, $localKey, $foreignKey, $relation);
}
/**
......
<?php namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Model;
abstract class EmbeddedRelation {
/**
* The parent model instance.
*
* @var \Illuminate\Database\Eloquent\Model
*/
protected $parent;
/**
* The related model class name.
*
* @var string
*/
protected $related;
/**
* Create a new has many relationship instance.
*
* @param \Illuminate\Database\Eloquent\Model $parent
* @param string $related
* @param string $collection
* @return void
*/
public function __construct(Model $parent, $related)
{
$this->parent = $parent;
$this->related = $related;
}
/**
* Get the results of the relationship.
*
* @return mixed
*/
abstract public function getResults();
}
......@@ -269,7 +269,8 @@ class RelationsTest extends PHPUnit_Framework_TestCase {
$client = Client::create(array('name' => 'Jane Doe'));
$photo = Photo::create(array('url' => 'http://graph.facebook.com/john.doe/picture'));
$user->photos()->save($photo);
$photo = $user->photos()->save($photo);
$this->assertEquals(1, $user->photos->count());
$this->assertEquals($photo->id, $user->photos->first()->id);
......@@ -282,49 +283,64 @@ class RelationsTest extends PHPUnit_Framework_TestCase {
$this->assertEquals($photo->imageable->name, $user->name);
}
public function testEmbedsManySaveOneRelated()
public function testEmbedsManySave()
{
$user = User::create(array('name' => 'John Doe'));
$address = new Address(array('city' => 'London'));
$user->addresses()->create(array('city' => 'Paris'));
$user->addresses()->push(new Address(array('city' => 'London')));
$user->addresses()->build(array('city' => 'Bruxelles'));
$user->addresses()->add(new Address(array('city' => 'New-York')));
$address = $user->addresses()->save($address);
$this->assertEquals(array('London'), $user->addresses->lists('city'));
$this->assertInstanceOf('DateTime', $address->created_at);
$this->assertInstanceOf('DateTime', $address->updated_at);
$freshUser = User::find($user->id);
$this->assertEquals(array('Paris', 'London', 'Bruxelles', 'New-York'), $user->addresses->lists('city'));
$this->assertEquals(array('Paris', 'London'), $freshUser->addresses->lists('city'));
$address = $user->addresses()->save(new Address(array('city' => 'Paris')));
$user->save();
$freshUser = User::find($user->id);
$this->assertEquals(array('Paris', 'London', 'Bruxelles', 'New-York'), $freshUser->addresses->lists('city'));
$freshUser = User::find($user->_id);
$this->assertEquals(array('London', 'Paris'), $freshUser->addresses->lists('city'));
$address->city = 'New York';
$freshUser->addresses()->save($address);
$this->assertEquals(2, count($freshUser->addresses));
$this->assertEquals(2, count($freshUser->addresses()->get()));
$this->assertEquals(2, $freshUser->addresses->count());
$this->assertEquals(array('London', 'New York'), $freshUser->addresses->lists('city'));
$address = $freshUser->addresses->first();
$this->assertEquals('London', $address->city);
$this->assertInstanceOf('DateTime', $address->created_at);
$this->assertInstanceOf('DateTime', $address->updated_at);
$this->assertInstanceOf('User', $address->user);
}
public function testEmbedsManySaveManyRelated()
public function testEmbedsManySaveMany()
{
$user = User::create(array('name' => 'John Doe'));
$user->addresses()->createMany(array(array('city' => 'Paris'), array('city' => 'Rouen')));
$user->addresses()->pushMany(array(new Address(array('city' => 'London')), new Address(array('city' => 'Bristol'))));
$user->addresses()->buildMany(array(array('city' => 'Bruxelles')));
$user->addresses()->addMany(new Collection(array(new Address(array('city' => 'New-York')))));
$user->addresses()->saveMany(array(new Address(array('city' => 'London')), new Address(array('city' => 'Bristol'))));
$this->assertEquals(array('London', 'Bristol'), $user->addresses->lists('city'));
$freshUser = User::find($user->id);
$this->assertEquals(array('Paris', 'Rouen', 'London', 'Bristol', 'Bruxelles', 'New-York'), $user->addresses->lists('city'));
$this->assertEquals(array('Paris', 'Rouen', 'London', 'Bristol'), $freshUser->addresses->lists('city'));
$this->assertEquals(array('London', 'Bristol'), $freshUser->addresses->lists('city'));
}
$user->save();
$freshUser = User::find($user->id);
$this->assertEquals(array('Paris', 'Rouen', 'London', 'Bristol', 'Bruxelles', 'New-York'), $freshUser->addresses->lists('city'));
public function testEmbedsManyCreate()
{
$user = new User(array('name' => 'John Doe'));
$user->addresses()->create(array('city' => 'Bruxelles'));
$this->assertEquals(array('Bruxelles'), $user->addresses->lists('city'));
$freshUser = User::find($user->id);
$this->assertEquals(array('Bruxelles'), $freshUser->addresses->lists('city'));
}
public function testEmbedsManyCreateId()
public function testEmbedsManyDestroy()
{
$user = new User(array('name' => 'John Doe'));
$user->addresses()->build(array('city' => 'Bruxelles'));
$this->assertInstanceOf('MongoId', $user->addresses->first()->_id);
$user = User::create(array('name' => 'John Doe'));
$user->addresses()->saveMany(array(new Address(array('city' => 'London')), new Address(array('city' => 'Bristol')), new Address(array('city' => 'Bruxelles'))));
$address = $user->addresses->first();
$user->addresses()->destroy($address->_id);
$this->assertEquals(array('Bristol', 'Bruxelles'), $user->addresses->lists('city'));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment