Skip to content

Commit d158fe3

Browse files
committed
Allow Controller to automatically instantiate classes in $model
1 parent 4ce0b32 commit d158fe3

File tree

3 files changed

+51
-13
lines changed

3 files changed

+51
-13
lines changed

src/Controller.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Framework\HTTP\Request;
1313
use Framework\HTTP\Response;
1414
use Framework\Routing\RouteActions;
15+
use LogicException;
1516
use ReflectionNamedType;
1617
use ReflectionProperty;
1718

@@ -57,20 +58,19 @@ public function __construct(Request $request, Response $response)
5758
*/
5859
protected function prepareModel() : static
5960
{
61+
if ( ! \property_exists($this, 'model')) {
62+
return $this;
63+
}
6064
$property = new ReflectionProperty($this, 'model');
6165
$type = $property->getType();
62-
// @phpstan-ignore-next-line
63-
$types = $type instanceof ReflectionNamedType ? [$type] : $type->getTypes();
64-
if (\count($types) > 1) {
65-
foreach ($types as $type) {
66-
$name = $type->getName();
67-
if ($name === ModelInterface::class) {
68-
continue;
69-
}
70-
$this->model = new $name(); // @phpstan-ignore-line
71-
break;
72-
}
66+
if ( ! $type instanceof ReflectionNamedType || $type->isBuiltin()) {
67+
throw new LogicException(
68+
'The ' . static::class
69+
. '::$model property must have one type to be instantiated'
70+
);
7371
}
72+
$name = $type->getName();
73+
$this->model = new $name();
7474
return $this;
7575
}
7676

tests/ControllerMock.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,10 @@
1212
use Framework\HTTP\Request;
1313
use Framework\HTTP\Response;
1414
use Framework\MVC\Controller;
15-
use Framework\MVC\ModelInterface;
1615

1716
class ControllerMock extends Controller
1817
{
19-
public ModelInterface | ModelMock $model;
18+
public ModelMock $model;
2019

2120
public function __construct()
2221
{

tests/ControllerTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,45 @@ public function testModelInstance() : void
3939
self::assertInstanceOf(ModelMock::class, $this->controller->model);
4040
}
4141

42+
protected function expectModelPropertyException() : void
43+
{
44+
$this->expectException(\LogicException::class);
45+
$this->expectExceptionMessageMatches(
46+
'#The (.+)::\$model property must have one type to be instantiated#'
47+
);
48+
}
49+
50+
public function testModelPropertyUndefined() : void
51+
{
52+
$controller = new class(App::request(), App::response()) extends Controller {
53+
};
54+
self::assertFalse(\property_exists($controller, 'model'));
55+
}
56+
57+
public function testModelPropertyWithoutType() : void
58+
{
59+
$this->expectModelPropertyException();
60+
new class(App::request(), App::response()) extends Controller {
61+
protected $model; // @phpstan-ignore-line
62+
};
63+
}
64+
65+
public function testModelPropertyWithBuiltinType() : void
66+
{
67+
$this->expectModelPropertyException();
68+
new class(App::request(), App::response()) extends Controller {
69+
protected int $model;
70+
};
71+
}
72+
73+
public function testModelPropertyWithManyTypes() : void
74+
{
75+
$this->expectModelPropertyException();
76+
new class(App::request(), App::response()) extends Controller {
77+
protected ModelMock | \stdClass $model;
78+
};
79+
}
80+
4281
public function testRender() : void
4382
{
4483
self::assertSame(

0 commit comments

Comments
 (0)