Skip to content

Commit f3d83e4

Browse files
authored
Pass Persistence to their model closure factory only (#1185)
1 parent 8b12d73 commit f3d83e4

7 files changed

+34
-59
lines changed

docs/advanced.md

+10-36
Original file line numberDiff line numberDiff line change
@@ -471,11 +471,13 @@ Next we need to define reference. Inside Model_Invoice add:
471471
```
472472
$this->hasMany('InvoicePayment', ['model' => [Model_InvoicePayment::class]]);
473473
474-
$this->hasMany('Payment', ['model' => function (self $m) {
475-
$p = new Model_Payment($m->getPersistence());
474+
$this->hasMany('Payment', ['model' => static function (Persistence $persistence) {
475+
$p = new Model_Payment($persistence);
476476
$j = $p->join('invoice_payment.payment_id');
477477
$j->addField('amount_closed');
478478
$j->hasOne('invoice_id', ['model' => [Model_Invoice::class]]);
479+
480+
return $p;
479481
}, 'theirField' => 'invoice_id']);
480482
481483
$this->onHookShort(Model::HOOK_BEFORE_DELETE, function () {
@@ -724,7 +726,7 @@ $this->hasOne('client_id', ['model' => [$this->client_class]]);
724726
Alternatively you can replace model in the init() method of Model_Invoice:
725727

726728
```
727-
$this->getReference('client_id')->model = 'Model_Client';
729+
$this->getReference('client_id')->model = [Model_Client::class];
728730
```
729731

730732
You can also use array here if you wish to pass additional information into
@@ -737,53 +739,25 @@ $this->getReference('client_id')->model = ['Model_Client', 'no_audit' => true];
737739
Combined with our "Audit" handler above, this should allow you to relate
738740
with deleted clients.
739741

740-
The final use case is when some value inside the existing model should be
741-
passed into the related model. Let's say we have 'Model_Invoice' and we want to
742-
add 'payment_invoice_id' that points to 'Model_Payment'. However we want this
743-
field only to offer payments made by the same client. Inside Model_Invoice add:
744-
745-
```
746-
$this->hasOne('client_id', ['model' => [Model_Client::class]]);
747-
748-
$this->hasOne('payment_invoice_id', ['model' => function (self $m) {
749-
return $m->ref('client_id')->ref('Payment');
750-
}]);
751-
752-
/// how to use
753-
754-
$m = new Model_Invoice($db);
755-
$m->set('client_id', 123);
756-
757-
$m->set('payment_invoice_id', $m->ref('payment_invoice_id')->loadOne()->getId());
758-
```
759-
760-
In this case the payment_invoice_id will be set to ID of any payment by client
761-
123. There also may be some better uses:
762-
763-
```
764-
foreach ($cl->ref('Invoice') as $m) {
765-
$m->set('payment_invoice_id', $m->ref('payment_invoice_id')->loadOne()->getId());
766-
$m->save();
767-
}
768-
```
769-
770742
## Narrowing Down Existing References
771743

772744
Agile Data allow you to define multiple references between same entities, but
773745
sometimes that can be quite useful. Consider adding this inside your Model_Contact:
774746

775747
```
776748
$this->hasMany('Invoice', ['model' => [Model_Invoice::class]]);
777-
$this->hasMany('OverdueInvoice', ['model' => function (self $m) {
778-
return $m->ref('Invoice')->addCondition('due', '<', date('Y-m-d'))
749+
750+
$this->hasMany('OverdueInvoice', ['model' => static function (Persistence $persistence) {
751+
return (new Model_Invoice($persistence))
752+
->addCondition('due', '<', new \DateTime());
779753
}]);
780754
```
781755

782756
This way if you extend your class into 'Model_Client' and modify the 'Invoice'
783757
reference to use different model:
784758

785759
```
786-
$this->getReference('Invoice')->model = 'Model_Invoice_Sale';
760+
$this->getReference('Invoice')->model = [Model_Invoice_Sale::class];
787761
```
788762

789763
The 'OverdueInvoice' reference will be also properly adjusted.

docs/model.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@ you use Persistence's "afterAdd" hook. This will not affect ALL models but just
197197
which are associated with said persistence:
198198

199199
```
200-
$db->onHook(Persistence::HOOK_AFTER_ADD, function (Persistence $p, Model $m) use ($acl) {
201-
$fields = $m->getFields();
200+
$db->onHook(Persistence::HOOK_AFTER_ADD, function (Persistence $persistence, Model $model) use ($acl) {
201+
$fields = $model->getFields();
202202
203203
$acl->disableRestrictedFields($fields);
204204
});

docs/references.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ There are several ways how to link models with hasMany:
118118
```
119119
$m->hasMany('Orders', ['model' => [Model_Order::class]]); // using seed
120120
121-
$m->hasMany('Order', ['model' => static function (Model $m, Reference $r, array $defaults) { // using callback
121+
$m->hasMany('Order', ['model' => static function (Persistence $persistence, array $defaults) { // using callback
122122
return new Model_Order();
123123
}]);
124124
```
@@ -471,7 +471,7 @@ Sometimes you would want to have a different type of relation between models,
471471
so with `addReference` you can define whatever reference you want:
472472

473473
```
474-
$m->addReference('Archive', ['model' => function (Model $m) {
474+
$m->addReference('Archive', ['model' => static function (Persistence $persistence) use ($m) {
475475
return new $m(null, ['table' => $m->table . '_archive']);
476476
}]);
477477
```
@@ -489,7 +489,7 @@ custom logic.
489489
No condition will be applied by default so it's all up to you:
490490

491491
```
492-
$m->addReference('Archive', ['model' => function (Model $m) {
492+
$m->addReference('Archive', ['model' => static function (Persistence $persistence) use ($m) {
493493
$archive = new $m(null, ['table' => $m->table . '_archive']);
494494
495495
$m->addField('original_id', ['type' => 'integer']);

src/Reference.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Reference
4747
* Seed of their model. If it is a Model instance, self::createTheirModel() must
4848
* always clone it to return a new instance.
4949
*
50-
* @var Model|\Closure(object, static, array<string, mixed>): Model|array<mixed>
50+
* @var array<mixed>|\Closure(Persistence, array<string, mixed>): Model|Model
5151
*/
5252
protected $model;
5353

@@ -231,7 +231,7 @@ protected function initTableAlias(): void
231231
*
232232
* @return Persistence|false
233233
*/
234-
protected function getDefaultPersistence(Model $theirModel)
234+
protected function getDefaultPersistence()
235235
{
236236
$ourModel = $this->getOurModel();
237237

@@ -256,7 +256,8 @@ protected function createTheirModelBeforeInit(array $defaults): Model
256256

257257
// if model is Closure, then call the closure and it should return a model
258258
if ($this->model instanceof \Closure) {
259-
$m = ($this->model)($this->getOurModel(), $this, $defaults);
259+
$persistence = Persistence::assertInstanceOf($this->getDefaultPersistence());
260+
$m = ($this->model)($persistence, $defaults);
260261
} else {
261262
$m = $this->model;
262263
}
@@ -278,7 +279,7 @@ protected function createTheirModelBeforeInit(array $defaults): Model
278279
protected function createTheirModelSetPersistence(Model $theirModel): void
279280
{
280281
if (!$theirModel->issetPersistence()) {
281-
$persistence = $this->getDefaultPersistence($theirModel);
282+
$persistence = $this->getDefaultPersistence();
282283
if ($persistence !== false) {
283284
$theirModel->setPersistence($persistence);
284285
}

src/Reference/ContainsBase.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ protected function init(): void
7171
}
7272

7373
#[\Override]
74-
protected function getDefaultPersistence(Model $theirModel): Persistence
74+
protected function getDefaultPersistence(): Persistence
7575
{
7676
return new Persistence\Array_();
7777
}

tests/ReferenceSqlTest.php

+12-12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Atk4\Data\Exception;
88
use Atk4\Data\Model;
9+
use Atk4\Data\Persistence;
910
use Atk4\Data\Schema\TestCase;
1011
use Doctrine\DBAL\Platforms\AbstractPlatform;
1112
use Doctrine\DBAL\Platforms\SQLServerPlatform;
@@ -357,18 +358,17 @@ public function getValue(): int
357358
$integerWrappedTypeName = $integerWrappedType->getName(); // @phpstan-ignore-line
358359

359360
$this->executeFxWithTemporaryType($integerWrappedTypeName, $integerWrappedType, function () use ($integerWrappedType, $integerWrappedTypeName) {
360-
$file = new Model($this->db, ['table' => 'file']);
361-
$file->getField('id')->type = $integerWrappedTypeName;
362-
$file->addField('name');
363-
$file->hasOne('parentDirectory', [
364-
'model' => $file,
365-
'type' => $integerWrappedTypeName,
366-
'ourField' => 'parentDirectoryId',
367-
]);
368-
$file->hasMany('childFiles', [
369-
'model' => $file,
370-
'theirField' => 'parentDirectoryId',
371-
]);
361+
$createFileModelFx = static function (Persistence $persistence) use ($integerWrappedTypeName, &$createFileModelFx) {
362+
$m = new Model($persistence, ['table' => 'file']);
363+
$m->getField('id')->type = $integerWrappedTypeName;
364+
$m->addField('name');
365+
$m->hasOne('parentDirectory', ['model' => $createFileModelFx, 'ourField' => 'parentDirectoryId', 'type' => $integerWrappedTypeName]);
366+
$m->hasMany('childFiles', ['model' => $createFileModelFx, 'theirField' => 'parentDirectoryId']);
367+
368+
return $m;
369+
};
370+
371+
$file = $createFileModelFx($this->db);
372372

373373
$fileEntity = $file->loadBy('name', 'v');
374374
self::assertSame(3, $fileEntity->getId()->getValue());

tests/ReferenceTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public function testHasOneDuplicateNameException(): void
114114
public function testCustomReference(): void
115115
{
116116
$m = new Model($this->db, ['table' => 'user']);
117-
$m->addReference('archive', ['model' => static function (Model $m) {
117+
$m->addReference('archive', ['model' => static function () use ($m) {
118118
return new $m(null, ['table' => $m->table . '_archive']);
119119
}]);
120120

0 commit comments

Comments
 (0)