Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
L
laravel-mongodb
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sinan
laravel-mongodb
Commits
6c60542a
Commit
6c60542a
authored
Aug 08, 2014
by
Jens Segers
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve embedded relations, and allow nested embedded relations
parent
0e923bca
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
223 additions
and
7 deletions
+223
-7
EmbedsMany.php
src/Jenssegers/Mongodb/Relations/EmbedsMany.php
+22
-3
EmbedsOne.php
src/Jenssegers/Mongodb/Relations/EmbedsOne.php
+20
-2
EmbedsOneOrMany.php
src/Jenssegers/Mongodb/Relations/EmbedsOneOrMany.php
+52
-1
EmbeddedRelationsTest.php
tests/EmbeddedRelationsTest.php
+124
-1
Address.php
tests/models/Address.php
+5
-0
No files found.
src/Jenssegers/Mongodb/Relations/EmbedsMany.php
View file @
6c60542a
...
...
@@ -32,8 +32,16 @@ class EmbedsMany extends EmbedsOneOrMany {
$model
->
setAttribute
(
'_id'
,
new
MongoId
);
}
// For deeply nested documents, let the parent handle the changes.
if
(
$this
->
isNested
())
{
$this
->
associate
(
$model
);
return
$this
->
parent
->
save
();
}
// Push the new model to the database.
$result
=
$this
->
query
->
push
(
$this
->
localKey
,
$model
->
getAttributes
(),
true
);
$result
=
$this
->
getBaseQuery
()
->
push
(
$this
->
localKey
,
$model
->
getAttributes
(),
true
);
// Attach the model to its parent.
if
(
$result
)
$this
->
associate
(
$model
);
...
...
@@ -49,12 +57,23 @@ class EmbedsMany extends EmbedsOneOrMany {
*/
public
function
performUpdate
(
Model
$model
,
array
$values
)
{
// For deeply nested documents, let the parent handle the changes.
if
(
$this
->
isNested
())
{
$this
->
associate
(
$model
);
return
$this
->
parent
->
save
();
}
// Get the correct foreign key value.
$foreignKey
=
$this
->
getForeignKeyValue
(
$model
);
// Use array dot notation for better update behavior.
$values
=
array_dot
(
$model
->
getDirty
(),
$this
->
localKey
.
'.$.'
);
// Update document in database.
$result
=
$this
->
query
->
where
(
$this
->
localKey
.
'.'
.
$model
->
getKeyName
(),
$foreignKey
)
->
update
(
array
(
$this
->
localKey
.
'.$'
=>
$model
->
getAttributes
())
);
$result
=
$this
->
getBaseQuery
()
->
where
(
$this
->
localKey
.
'.'
.
$model
->
getKeyName
(),
$foreignKey
)
->
update
(
$values
);
// Attach the model to its parent.
if
(
$result
)
$this
->
associate
(
$model
);
...
...
src/Jenssegers/Mongodb/Relations/EmbedsOne.php
View file @
6c60542a
...
...
@@ -32,7 +32,15 @@ class EmbedsOne extends EmbedsOneOrMany {
$model
->
setAttribute
(
'_id'
,
new
MongoId
);
}
$result
=
$this
->
query
->
update
(
array
(
$this
->
localKey
=>
$model
->
getAttributes
()));
// For deeply nested documents, let the parent handle the changes.
if
(
$this
->
isNested
())
{
$this
->
associate
(
$model
);
return
$this
->
parent
->
save
();
}
$result
=
$this
->
getBaseQuery
()
->
update
(
array
(
$this
->
localKey
=>
$model
->
getAttributes
()));
// Attach the model to its parent.
if
(
$result
)
$this
->
associate
(
$model
);
...
...
@@ -48,7 +56,17 @@ class EmbedsOne extends EmbedsOneOrMany {
*/
public
function
performUpdate
(
Model
$model
,
array
$values
)
{
$result
=
$this
->
query
->
update
(
array
(
$this
->
localKey
=>
$model
->
getAttributes
()));
if
(
$this
->
isNested
())
{
$this
->
associate
(
$model
);
return
$this
->
parent
->
save
();
}
// Use array dot notation for better update behavior.
$values
=
array_dot
(
$model
->
getDirty
(),
$this
->
localKey
.
'.'
);
$result
=
$this
->
getBaseQuery
()
->
update
(
$values
);
// Attach the model to its parent.
if
(
$result
)
$this
->
associate
(
$model
);
...
...
src/Jenssegers/Mongodb/Relations/EmbedsOneOrMany.php
View file @
6c60542a
...
...
@@ -51,6 +51,7 @@ abstract class EmbedsOneOrMany extends Relation {
// If this is a nested relation, we need to get the parent query instead.
if
(
$parentRelation
=
$this
->
getParentRelation
())
{
//$this->query = $parentRelation->parent->newQuery();
$this
->
query
=
$parentRelation
->
getQuery
();
}
...
...
@@ -66,7 +67,7 @@ abstract class EmbedsOneOrMany extends Relation {
{
if
(
static
::
$constraints
)
{
$this
->
query
->
where
(
$this
->
parent
->
getKeyName
(),
'='
,
$this
->
parent
->
ge
tKey
());
$this
->
query
->
where
(
$this
->
getQualifiedParentKeyName
(),
'='
,
$this
->
getParen
tKey
());
}
}
...
...
@@ -328,4 +329,54 @@ abstract class EmbedsOneOrMany extends Relation {
return
$this
->
parent
->
getParent
();
}
/**
* Check if this relation is nested in another relation.
*
* @return boolean
*/
protected
function
isNested
()
{
return
$this
->
getParentRelation
()
!=
null
;
}
/**
* Get the fully qualified local key name.
*
* @return string
*/
protected
function
getPathHierarchy
(
$glue
=
'.'
)
{
if
(
$parentRelation
=
$this
->
getParentRelation
())
{
return
$parentRelation
->
getPathHierarchy
(
$glue
)
.
$glue
.
$this
->
localKey
;
}
return
$this
->
localKey
;
}
/**
* Get the parent's fully qualified key name.
*
* @return string
*/
protected
function
getQualifiedParentKeyName
()
{
if
(
$parentRelation
=
$this
->
getParentRelation
())
{
return
$parentRelation
->
getPathHierarchy
()
.
'.'
.
$this
->
parent
->
getKeyName
();
}
return
$this
->
parent
->
getKeyName
();
}
/**
* Get the primary key value of the parent.
*
* @return string
*/
protected
function
getParentKey
()
{
return
$this
->
parent
->
getKey
();
}
}
tests/EmbeddedRelationsTest.php
View file @
6c60542a
...
...
@@ -74,6 +74,7 @@ class EmbeddedRelationsTest extends TestCase {
$user
=
User
::
find
(
$user
->
_id
);
$user
->
addresses
()
->
save
(
new
Address
(
array
(
'city'
=>
'Bruxelles'
)));
$this
->
assertEquals
(
array
(
'London'
,
'New York'
,
'Bruxelles'
),
$user
->
addresses
->
lists
(
'city'
));
$address
=
$user
->
addresses
[
1
];
$address
->
city
=
"Manhattan"
;
$user
->
addresses
()
->
save
(
$address
);
...
...
@@ -83,6 +84,29 @@ class EmbeddedRelationsTest extends TestCase {
$this
->
assertEquals
(
array
(
'London'
,
'Manhattan'
,
'Bruxelles'
),
$freshUser
->
addresses
->
lists
(
'city'
));
}
public
function
testEmbedsManySaveModel
()
{
$user
=
User
::
create
(
array
(
'name'
=>
'John Doe'
));
$address
=
new
Address
(
array
(
'city'
=>
'London'
));
$address
->
setEventDispatcher
(
$events
=
Mockery
::
mock
(
'Illuminate\Events\Dispatcher'
));
$events
->
shouldReceive
(
'until'
)
->
once
()
->
with
(
'eloquent.saving: '
.
get_class
(
$address
),
$address
)
->
andReturn
(
true
);
$events
->
shouldReceive
(
'until'
)
->
once
()
->
with
(
'eloquent.creating: '
.
get_class
(
$address
),
$address
)
->
andReturn
(
true
);
$events
->
shouldReceive
(
'fire'
)
->
once
()
->
with
(
'eloquent.created: '
.
get_class
(
$address
),
$address
);
$events
->
shouldReceive
(
'fire'
)
->
once
()
->
with
(
'eloquent.saved: '
.
get_class
(
$address
),
$address
);
$address
->
save
();
$address
->
setEventDispatcher
(
$events
=
Mockery
::
mock
(
'Illuminate\Events\Dispatcher'
));
$events
->
shouldReceive
(
'until'
)
->
once
()
->
with
(
'eloquent.saving: '
.
get_class
(
$address
),
$address
)
->
andReturn
(
true
);
$events
->
shouldReceive
(
'until'
)
->
once
()
->
with
(
'eloquent.updating: '
.
get_class
(
$address
),
$address
)
->
andReturn
(
true
);
$events
->
shouldReceive
(
'fire'
)
->
once
()
->
with
(
'eloquent.updated: '
.
get_class
(
$address
),
$address
);
$events
->
shouldReceive
(
'fire'
)
->
once
()
->
with
(
'eloquent.saved: '
.
get_class
(
$address
),
$address
);
$address
->
city
=
'Paris'
;
$address
->
save
();
}
public
function
testEmbedsToArray
()
{
$user
=
User
::
create
(
array
(
'name'
=>
'John Doe'
));
...
...
@@ -217,6 +241,32 @@ class EmbeddedRelationsTest extends TestCase {
$this
->
assertEquals
(
array
(
'Bristol'
),
$user
->
addresses
->
lists
(
'city'
));
}
public
function
testEmbedsManyDelete
()
{
$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
();
$address
->
setEventDispatcher
(
$events
=
Mockery
::
mock
(
'Illuminate\Events\Dispatcher'
));
$events
->
shouldReceive
(
'until'
)
->
once
()
->
with
(
'eloquent.deleting: '
.
get_class
(
$address
),
Mockery
::
type
(
'Address'
))
->
andReturn
(
true
);
$events
->
shouldReceive
(
'fire'
)
->
once
()
->
with
(
'eloquent.deleted: '
.
get_class
(
$address
),
Mockery
::
type
(
'Address'
));
$address
->
delete
();
$this
->
assertEquals
(
2
,
$user
->
addresses
()
->
count
());
$this
->
assertEquals
(
2
,
$user
->
addresses
->
count
());
$address
->
unsetEventDispatcher
();
$address
=
$user
->
addresses
->
first
();
$address
->
delete
();
$user
=
User
::
where
(
'name'
,
'John Doe'
)
->
first
();
$this
->
assertEquals
(
1
,
$user
->
addresses
()
->
count
());
$this
->
assertEquals
(
1
,
$user
->
addresses
->
count
());
}
public
function
testEmbedsManyDissociate
()
{
$user
=
User
::
create
(
array
());
...
...
@@ -339,7 +389,7 @@ class EmbeddedRelationsTest extends TestCase {
$this
->
assertTrue
(
is_array
(
$user
->
toArray
()[
'addresses'
]));
}
public
function
testEmbedsManyDelete
()
public
function
testEmbedsManyDelete
All
()
{
$user1
=
User
::
create
(
array
(
'name'
=>
'John Doe'
));
$user1
->
addresses
()
->
save
(
new
Address
(
array
(
'city'
=>
'New York'
)));
...
...
@@ -500,4 +550,77 @@ class EmbeddedRelationsTest extends TestCase {
$this
->
assertEquals
(
'Mark Doe'
,
$user
->
father
->
name
);
}
public
function
testNestedEmbedsOne
()
{
$user
=
User
::
create
(
array
(
'name'
=>
'John Doe'
));
$father
=
$user
->
father
()
->
create
(
array
(
'name'
=>
'Mark Doe'
));
$grandfather
=
$father
->
father
()
->
create
(
array
(
'name'
=>
'Steve Doe'
));
$greatgrandfather
=
$grandfather
->
father
()
->
create
(
array
(
'name'
=>
'Tom Doe'
));
$user
->
name
=
'Tim Doe'
;
$user
->
save
();
$father
->
name
=
'Sven Doe'
;
$father
->
save
();
$greatgrandfather
->
name
=
'Ron Doe'
;
$greatgrandfather
->
save
();
$this
->
assertEquals
(
'Tim Doe'
,
$user
->
name
);
$this
->
assertEquals
(
'Sven Doe'
,
$user
->
father
->
name
);
$this
->
assertEquals
(
'Steve Doe'
,
$user
->
father
->
father
->
name
);
$this
->
assertEquals
(
'Ron Doe'
,
$user
->
father
->
father
->
father
->
name
);
$user
=
User
::
where
(
'name'
,
'Tim Doe'
)
->
first
();
$this
->
assertEquals
(
'Tim Doe'
,
$user
->
name
);
$this
->
assertEquals
(
'Sven Doe'
,
$user
->
father
->
name
);
$this
->
assertEquals
(
'Steve Doe'
,
$user
->
father
->
father
->
name
);
$this
->
assertEquals
(
'Ron Doe'
,
$user
->
father
->
father
->
father
->
name
);
}
public
function
testNestedEmbedsMany
()
{
$user
=
User
::
create
(
array
(
'name'
=>
'John Doe'
));
$country1
=
$user
->
addresses
()
->
create
(
array
(
'country'
=>
'France'
));
$country2
=
$user
->
addresses
()
->
create
(
array
(
'country'
=>
'Belgium'
));
$city1
=
$country1
->
addresses
()
->
create
(
array
(
'city'
=>
'Paris'
));
$city2
=
$country2
->
addresses
()
->
create
(
array
(
'city'
=>
'Ghent'
));
$city3
=
$country2
->
addresses
()
->
create
(
array
(
'city'
=>
'Brussels'
));
$city3
->
city
=
'Bruges'
;
$city3
->
save
();
$this
->
assertEquals
(
2
,
$user
->
addresses
()
->
count
());
$this
->
assertEquals
(
1
,
$user
->
addresses
()
->
first
()
->
addresses
()
->
count
());
$this
->
assertEquals
(
2
,
$user
->
addresses
()
->
last
()
->
addresses
()
->
count
());
$user
=
User
::
where
(
'name'
,
'John Doe'
)
->
first
();
$this
->
assertEquals
(
2
,
$user
->
addresses
()
->
count
());
$this
->
assertEquals
(
1
,
$user
->
addresses
()
->
first
()
->
addresses
()
->
count
());
$this
->
assertEquals
(
2
,
$user
->
addresses
()
->
last
()
->
addresses
()
->
count
());
}
public
function
testNestedMixedEmbeds
()
{
$user
=
User
::
create
(
array
(
'name'
=>
'John Doe'
));
$father
=
$user
->
father
()
->
create
(
array
(
'name'
=>
'Mark Doe'
));
$country1
=
$father
->
addresses
()
->
create
(
array
(
'country'
=>
'France'
));
$country2
=
$father
->
addresses
()
->
create
(
array
(
'country'
=>
'Belgium'
));
$country2
->
country
=
'England'
;
$country2
->
save
();
$father
->
name
=
'Steve Doe'
;
$father
->
save
();
$this
->
assertEquals
(
'France'
,
$user
->
father
->
addresses
()
->
first
()
->
country
);
$this
->
assertEquals
(
'England'
,
$user
->
father
->
addresses
()
->
last
()
->
country
);
$this
->
assertEquals
(
'Steve Doe'
,
$user
->
father
->
name
);
$user
=
User
::
where
(
'name'
,
'John Doe'
)
->
first
();
$this
->
assertEquals
(
'France'
,
$user
->
father
->
addresses
()
->
first
()
->
country
);
$this
->
assertEquals
(
'England'
,
$user
->
father
->
addresses
()
->
last
()
->
country
);
$this
->
assertEquals
(
'Steve Doe'
,
$user
->
father
->
name
);
}
}
tests/models/Address.php
View file @
6c60542a
...
...
@@ -6,4 +6,9 @@ class Address extends Eloquent {
protected
static
$unguarded
=
true
;
public
function
addresses
()
{
return
$this
->
embedsMany
(
'Address'
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment