Skip to content

Commit 64d80c0

Browse files
committed
Merge branch 'iamgergo/7.x' into 7.x
2 parents 677afee + 0c1c195 commit 64d80c0

File tree

4 files changed

+51
-1
lines changed

4 files changed

+51
-1
lines changed

src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,8 @@ public function getRelationValue($key)
415415
// If the "attribute" exists as a method on the model, we will just assume
416416
// it is a relationship and will load and return results from the query
417417
// and hydrate the relationship's value on the "relationships" array.
418-
if (method_exists($this, $key)) {
418+
if (method_exists($this, $key) ||
419+
(static::$relationResolvers[get_class($this)][$key] ?? null)) {
419420
return $this->getRelationshipFromMethod($key);
420421
}
421422
}

src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Illuminate\Database\Eloquent\Concerns;
44

5+
use Closure;
56
use Illuminate\Database\Eloquent\Builder;
67
use Illuminate\Database\Eloquent\Collection;
78
use Illuminate\Database\Eloquent\Model;
@@ -44,6 +45,28 @@ trait HasRelationships
4445
'belongsToMany', 'morphToMany', 'morphedByMany',
4546
];
4647

48+
/**
49+
* The relation resolver callbacks.
50+
*
51+
* @var array
52+
*/
53+
protected static $relationResolvers = [];
54+
55+
/**
56+
* Define a dynamic relation resolver.
57+
*
58+
* @param string $name
59+
* @param \Closure $callback
60+
* @return void
61+
*/
62+
public static function resolveRelationUsing($name, Closure $callback)
63+
{
64+
static::$relationResolvers = array_replace_recursive(
65+
static::$relationResolvers,
66+
[static::class => [$name => $callback]]
67+
);
68+
}
69+
4770
/**
4871
* Define a one-to-one relationship.
4972
*

src/Illuminate/Database/Eloquent/Model.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,6 +1725,10 @@ public function __call($method, $parameters)
17251725
return $this->$method(...$parameters);
17261726
}
17271727

1728+
if ($resolver = (static::$relationResolvers[get_class($this)][$method] ?? null)) {
1729+
return $resolver($this);
1730+
}
1731+
17281732
return $this->forwardCallTo($this->newQuery(), $method, $parameters);
17291733
}
17301734

tests/Database/DatabaseEloquentRelationTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,20 @@ public function testMacroable()
267267
$result = $relation->foo();
268268
$this->assertSame('foo', $result);
269269
}
270+
271+
public function testRelationResolvers()
272+
{
273+
$model = new EloquentRelationResetModelStub;
274+
$builder = m::mock(Builder::class);
275+
$builder->shouldReceive('getModel')->andReturn($model);
276+
277+
EloquentRelationResetModelStub::resolveRelationUsing('customer', function ($model) use ($builder) {
278+
return new EloquentResolverRelationStub($builder, $model);
279+
});
280+
281+
$this->assertInstanceOf(EloquentResolverRelationStub::class, $model->customer());
282+
$this->assertSame(['key' => 'value'], $model->customer);
283+
}
270284
}
271285

272286
class EloquentRelationResetModelStub extends Model
@@ -329,3 +343,11 @@ class EloquentNoTouchingAnotherModelStub extends Model
329343
'id' => 2,
330344
];
331345
}
346+
347+
class EloquentResolverRelationStub extends EloquentRelationStub
348+
{
349+
public function getResults()
350+
{
351+
return ['key' => 'value'];
352+
}
353+
}

0 commit comments

Comments
 (0)