Skip to content

Commit 605ad1f

Browse files
authored
Merge pull request #3 from DanJFletcher/master
Fix issues with composer parse error and mass assignment exception
2 parents 479c03f + b70b4ff commit 605ad1f

File tree

3 files changed

+62
-32
lines changed

3 files changed

+62
-32
lines changed

composer.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717
"require": {
1818
"php": ">=7.1",
1919
"illuminate/database": "^5.6",
20-
"illuminate/support": "~5.6",
21-
"mockery/mockery": "~1.0",
20+
"illuminate/support": "~5.6"
2221
},
2322
"require-dev": {
2423
"phpunit/phpunit": "~7.0",
25-
"squizlabs/php_codesniffer": "^3.0"
24+
"squizlabs/php_codesniffer": "^3.0",
25+
"mockery/mockery": "~1.0"
2626
},
2727
"autoload": {
2828
"psr-4": {

src/Traits/HasNestedAttributesTrait.php

+9-9
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@
88
use Illuminate\Database\Eloquent\Relations\MorphOne;
99
use Illuminate\Database\Eloquent\Relations\HasMany;
1010
use Illuminate\Database\Eloquent\Relations\MorphMany;
11-
use Illuminate\Database\Eloquent\Builder;
1211

1312
trait HasNestedAttributesTrait
1413
{
1514
/**
16-
* Defined nested attributes
15+
* Defined nested attributes
1716
*
1817
* @var array
1918
*/
@@ -53,12 +52,13 @@ public function fill(array $attributes)
5352
foreach ($this->nested as $attr) {
5453
if (isset($attributes[$attr])) {
5554
$this->acceptNestedAttributesFor[$attr] = $attributes[$attr];
55+
unset($attributes[$attr]);
5656
}
5757
}
5858
}
5959
return parent::fill($attributes);
6060
}
61-
61+
6262
/**
6363
* Save the model to the database.
6464
*
@@ -75,7 +75,7 @@ public function save(array $options = [])
7575

7676
foreach ($this->getAcceptNestedAttributesFor() as $attribute => $stack) {
7777
$methodName = lcfirst(join(array_map('ucfirst', explode('_', $attribute))));
78-
78+
7979
if (!method_exists($this, $methodName)) {
8080
throw new Exception('The nested atribute relation "' . $methodName . '" does not exists.');
8181
}
@@ -86,7 +86,7 @@ public function save(array $options = [])
8686
if (!$this->saveNestedAttributes($relation, $stack)) {
8787
return false;
8888
}
89-
} else if ($relation instanceof HasMany || $relation instanceof MorphMany) {
89+
} elseif ($relation instanceof HasMany || $relation instanceof MorphMany) {
9090
foreach ($stack as $params) {
9191
if (!$this->saveManyNestedAttributes($this->$methodName(), $params)) {
9292
return false;
@@ -115,7 +115,7 @@ protected function saveNestedAttributes($relation, array $params)
115115
return $model->delete();
116116
}
117117
return $model->update($stack);
118-
} else if ($relation->create($stack)) {
118+
} elseif ($relation->create($stack)) {
119119
return true;
120120
}
121121
return false;
@@ -135,9 +135,9 @@ protected function saveManyNestedAttributes($relation, array $params)
135135

136136
if ($this->allowDestroyNestedAttributes($params)) {
137137
return $model->delete();
138-
}
138+
}
139139
return $model->update($params);
140-
} else if ($relation->create($params)) {
140+
} elseif ($relation->create($params)) {
141141
return true;
142142
}
143143
return false;
@@ -153,4 +153,4 @@ protected function allowDestroyNestedAttributes(array $params)
153153
{
154154
return isset($params[$this->destroyNestedKey]) && (bool) $params[$this->destroyNestedKey] == true;
155155
}
156-
}
156+
}

tests/HasNestedAttributesTraitTest.php

+50-20
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ public function setUp()
1313
// Mock the Model that uses the custom traits
1414
$this->model = Mockery::mock('ModelEloquentStub');
1515
$this->model->makePartial();
16+
17+
// Mock the Model without fillable array set
18+
$this->modelWithoutFillable = Mockery::mock('ModelEloquentStubWithoutFillable');
19+
$this->modelWithoutFillable->makePartial();
20+
21+
// Default payload for Model
22+
$this->payload = [
23+
'model_bar' => ['text' => 'bar'],
24+
'model_foos' => [
25+
['text' => 'foo1'],
26+
['text' => 'foo2'],
27+
]
28+
];
1629
}
1730

1831
/**
@@ -28,55 +41,72 @@ public function tearDown()
2841
*/
2942
public function testFillable()
3043
{
31-
$payload = [
32-
'title' => 'foo',
33-
'not_exists' => [],
44+
$this->model->fill(array_merge($this->payload, ['title' => 'foo', 'not_exists' => []]));
45+
46+
$this->assertEquals(['title' => 'foo'], $this->model->getAttributes());
47+
$this->assertEquals([
3448
'model_bar' => ['text' => 'bar'],
3549
'model_foos' => [
3650
['text' => 'foo1'],
37-
['text' => 'foo2'],
51+
['text' => 'foo2']
3852
]
39-
];
53+
], $this->model->getAcceptNestedAttributesFor());
54+
}
4055

41-
$this->model->fill($payload);
56+
/**
57+
* Test that a model with nested attributes can still save without fillable array.
58+
*/
59+
public function testModelWithNestedAttributesCanSaveWithoutFillableArraySet()
60+
{
61+
$this->modelWithoutFillable->fill($this->payload);
4262

43-
$this->assertEquals(['title' => 'foo'], $this->model->getAttributes());
4463
$this->assertEquals([
4564
'model_bar' => ['text' => 'bar'],
4665
'model_foos' => [
47-
['text' => 'foo1'],
66+
['text' => 'foo1'],
4867
['text' => 'foo2']
4968
]
50-
], $this->model->getAcceptNestedAttributesFor());
69+
], $this->modelWithoutFillable->getAcceptNestedAttributesFor());
5170
}
5271
}
5372

54-
class ModelEloquentStub extends Model {
73+
class ModelEloquentStubWithoutFillable extends Model
74+
{
5575
protected $table = 'stubs';
56-
protected $fillable = ['title'];
5776
protected $nested = ['model_bar', 'model_foos' ];
58-
59-
public function modelBar() {
77+
78+
public function modelBar()
79+
{
6080
return $this->hasOne(ModelBarStub::class);
6181
}
6282

63-
public function modelFoos() {
83+
public function modelFoos()
84+
{
6485
return $this->hasOne(ModelFooStub::class);
6586
}
6687
}
6788

68-
class ModelBarStub extends Model {
89+
class ModelEloquentStub extends ModelEloquentStubWithoutFillable
90+
{
91+
protected $fillable = ['title'];
92+
}
93+
94+
class ModelBarStub extends Model
95+
{
6996
protected $fillable = ['text'];
70-
71-
public function parent() {
97+
98+
public function parent()
99+
{
72100
return $this->belongsTo(ModelEloquentStub::class);
73101
}
74102
}
75103

76-
class ModelFooStub extends Model {
104+
class ModelFooStub extends Model
105+
{
77106
protected $fillable = ['text'];
78107

79-
public function parent() {
108+
public function parent()
109+
{
80110
return $this->belongsTo(ModelEloquentStub::class);
81111
}
82-
}
112+
}

0 commit comments

Comments
 (0)