diff --git a/docs/grid.md b/docs/grid.md index 64a5f52040..5d5ba85b1a 100644 --- a/docs/grid.md +++ b/docs/grid.md @@ -152,7 +152,7 @@ to populate a content: ``` $grid->addModalAction('Details', 'Additional Details', function (View $p, $id) use ($grid) { // $id of the record which was clicked - // $grid->model = $grid->model->load($id); + // $model = $grid->model->load($id); LoremIpsum::addTo($p); }); diff --git a/src/Form/AbstractLayout.php b/src/Form/AbstractLayout.php index 2f15bac45c..bf6d258d22 100644 --- a/src/Form/AbstractLayout.php +++ b/src/Form/AbstractLayout.php @@ -40,7 +40,7 @@ protected function _addControl(Control $control, Field $field): Control public function addControl(string $name, $control = [], array $fieldSeed = []): Control { if ($this->form->entity === null) { - $this->form->entity = (new ProxyModel())->createEntity(); + $this->form->setModel((new ProxyModel())->createEntity()); } $model = $this->form->entity->getModel(); diff --git a/src/Table.php b/src/Table.php index 4a4a7bdcfe..c562303f72 100644 --- a/src/Table.php +++ b/src/Table.php @@ -146,7 +146,7 @@ public function addColumn(?string $name, $columnDecorator = [], $field = []) } if ($this->model === null) { - $this->model = new ProxyModel(); + $this->setModel(new ProxyModel()); } $this->model->assertIsModel(); diff --git a/src/View.php b/src/View.php index 30fb4109b7..b9d657640b 100644 --- a/src/View.php +++ b/src/View.php @@ -104,6 +104,17 @@ public function __construct($label = []) $this->setDefaults($defaults); } + #[\Override] + public function &__get(string $name) + { + // TODO remove in atk4/ui 6.0 + if ($name === 'model' && !(new \ReflectionProperty(self::class, 'model'))->isInitialized($this) && $this->entity !== null) { + throw new Exception('Use View::$entity property instead for entity access'); + } + + return parent::__get($name); + } + /** * Associate this view with a model. Do not place any logic in this class, instead take it * to renderView(). @@ -113,8 +124,8 @@ public function __construct($label = []) */ public function setModel(Model $model): void { - if ($this->model !== null) { - if ($this->model === $model) { + if (((new \ReflectionProperty(self::class, 'model'))->isInitialized($this) ? $this->model : $this->entity) !== null) { + if (((new \ReflectionProperty(self::class, 'model'))->isInitialized($this) ? $this->model : $this->entity) === $model) { return; } diff --git a/tests/ViewTest.php b/tests/ViewTest.php index cd5c4c54e3..a28b0e3e3d 100644 --- a/tests/ViewTest.php +++ b/tests/ViewTest.php @@ -10,6 +10,7 @@ use Atk4\Ui\Callback; use Atk4\Ui\Console; use Atk4\Ui\Exception; +use Atk4\Ui\Form; use Atk4\Ui\JsCallback; use Atk4\Ui\JsSse; use Atk4\Ui\Loader; @@ -103,6 +104,22 @@ public function testSetModelTwiceException(): void $v->setModel($m2); } + public function testSetModelEntity(): void + { + $form = new Form(); + $form->setApp($this->createApp()); + $form->invokeInit(); + $entity = (new Model())->createEntity(); + $form->setModel($entity); + + self::assertSame($entity, $form->entity); + self::assertFalse((new \ReflectionProperty(Form::class, 'model'))->isInitialized($form)); + + $this->expectException(Exception::class); + $this->expectExceptionMessage('Use View::$entity property instead for entity access'); + $form->model; // @phpstan-ignore-line + } + public function testSetSourceZeroKeyException(): void { $v = new View();