Skip to content

Commit a470a4e

Browse files
AZabolotnikovclaude
andcommitted
fix: exclude wildcard from ModelTrait::getFields result
Laravel's default $guarded = ['*'] was being merged directly into getFields(), leaking '*' into consumers like getOrderableFields. Now guarded wildcard is filtered out and merged sources are deduped. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 8169db7 commit a470a4e

5 files changed

Lines changed: 93 additions & 4 deletions

File tree

src/Traits/ModelTrait.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ public static function getFields(): array
1717
$model = (new static());
1818

1919
$keyName = $model->getKeyName();
20-
$guarded = $model->getGuarded();
20+
$guarded = array_diff($model->getGuarded(), ['*']);
2121
$fillable = $model->getFillable();
2222
$timeStamps = ($model->timestamps) ? ['created_at', 'updated_at'] : [];
2323

2424
array_unshift($fillable, $keyName);
2525

26-
return array_merge($fillable, $guarded, $timeStamps);
26+
$result = array_merge($fillable, $guarded, $timeStamps);
27+
28+
return array_values(array_unique($result));
2729
}
2830

2931
public function getAllFieldsWithTable(): array

tests/BaseRequestTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function testGetOrderableFields()
1616
{
1717
$result = $this->callEncapsulatedMethod(new BaseRequest(), 'getOrderableFields', TestModel::class);
1818

19-
$expectedResult = 'id,name,json_field,custom_cast_field,castable_field,*,created_at,updated_at';
19+
$expectedResult = 'id,name,json_field,custom_cast_field,castable_field,created_at,updated_at';
2020

2121
$this->assertEquals($expectedResult, $result);
2222
}
@@ -30,7 +30,7 @@ public function testGetOrderableFieldsWithAdditionalFields()
3030

3131
$result = $this->callEncapsulatedMethod(new BaseRequest(), 'getOrderableFields', ...$args);
3232

33-
$expectedResult = 'id,name,json_field,custom_cast_field,castable_field,*,created_at,updated_at,additional_field_1,additional_field_2';
33+
$expectedResult = 'id,name,json_field,custom_cast_field,castable_field,created_at,updated_at,additional_field_1,additional_field_2';
3434

3535
$this->assertEquals($expectedResult, $result);
3636
}

tests/ModelTraitTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace RonasIT\Support\Tests;
4+
5+
use RonasIT\Support\Tests\Support\Mock\Models\TestModel;
6+
use RonasIT\Support\Tests\Support\Mock\Models\TestModelWithGuardedFields;
7+
use RonasIT\Support\Tests\Support\Mock\Models\TestModelWithGuardedWildcard;
8+
use RonasIT\Support\Tests\Support\Mock\Models\TestModelWithoutTimestamps;
9+
10+
class ModelTraitTest extends TestCase
11+
{
12+
public function testGetFieldsDoesNotContainWildcard()
13+
{
14+
$fields = TestModel::getFields();
15+
16+
$this->assertNotContains('*', $fields);
17+
18+
$this->assertEquals([
19+
'id',
20+
'name',
21+
'json_field',
22+
'custom_cast_field',
23+
'castable_field',
24+
'created_at',
25+
'updated_at',
26+
], $fields);
27+
}
28+
29+
public function testGetFieldsWithGuardedWildcardOnly()
30+
{
31+
$fields = TestModelWithGuardedWildcard::getFields();
32+
33+
$this->assertNotContains('*', $fields);
34+
35+
$this->assertEquals(['id', 'created_at', 'updated_at'], $fields);
36+
}
37+
38+
public function testGetFieldsWithGuardedFields()
39+
{
40+
$fields = TestModelWithGuardedFields::getFields();
41+
42+
$this->assertEquals(['id', 'name', 'secret_field', 'created_at', 'updated_at'], $fields);
43+
}
44+
45+
public function testGetFieldsDoesNotContainDuplicates()
46+
{
47+
$fields = TestModelWithoutTimestamps::getFields();
48+
49+
$this->assertEquals(['id', 'name', 'created_at'], $fields);
50+
}
51+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace RonasIT\Support\Tests\Support\Mock\Models;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use RonasIT\Support\Traits\ModelTrait;
7+
8+
class TestModelWithGuardedFields extends Model
9+
{
10+
use ModelTrait;
11+
12+
protected $table = 'test_models';
13+
14+
protected $fillable = [
15+
'name',
16+
];
17+
18+
protected $guarded = [
19+
'secret_field',
20+
];
21+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace RonasIT\Support\Tests\Support\Mock\Models;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use RonasIT\Support\Traits\ModelTrait;
7+
8+
class TestModelWithGuardedWildcard extends Model
9+
{
10+
use ModelTrait;
11+
12+
protected $table = 'test_models';
13+
14+
protected $guarded = ['*'];
15+
}

0 commit comments

Comments
 (0)