- Notifications
You must be signed in to change notification settings - Fork 48
Add Model\UnionModel model #677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
georgehristov wants to merge 211 commits into develop Choose a base branch from feature/introduce-aggregate-union-models
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline, and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
211 commits Select commit Hold shift + click to select a range
7083cf5 [update] migrate aggregate and union models to data package
georgehristov 9f95593 [update] combine union test in single class
georgehristov 691d9bd [fix] create db tables with all columns
georgehristov ee88bb5 [update] migrate and update docs
georgehristov e436599 [update] php docs
georgehristov c728ce1 [update] variable names
georgehristov e3432cf [update] use generic Model::export method
georgehristov 9dcd45d [fix] typos
georgehristov e2364cb [update] improve naming consistency
georgehristov 19c6689 [update] provide integration trait for generic support of aggregates …
georgehristov 0b21ab3 Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov ebc06d9 Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov a03dbc5 [update] add return types
georgehristov 1033a0b Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov 66483ed [fix] add method return types in Aggregate and Union
georgehristov 4b4affa [fix] clone test models on use
georgehristov c43694b [fix] skip non-aggregate fields on union select sub-query
georgehristov 1325b54 [fix] add test export sorting order
georgehristov 650e449 [fix] teardown class properties
georgehristov bb349c1 [fix] mark test incomplete
georgehristov ee3be79 [update] rename properties
georgehristov 1274012 [update] add annotations for $persistence and expr
georgehristov 6e5f66a [update] use clone of base model
georgehristov 9059644 [update] method signature and phpdoc
georgehristov 8c8bb41 [update] aggregate order
georgehristov 4922475 [refactor] Union::getSubAction
georgehristov 7af4243 [update] code comments
georgehristov 6a08906 [update] Union::addCondition
georgehristov 9936315 [update] fix complex conditions handling using field alias
georgehristov 5289b65 Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov a8839b1 [fix] revert field alias usage
georgehristov 2595921 Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov b75a23d [update] to latest develop
georgehristov 30ece17 [fix] test
georgehristov 8c0080e [fix] static analysis errors
georgehristov 33c0674 [fix] docs
georgehristov 707c070 [update] reorder methods and adjust visibility
georgehristov 690e1ca [feature] introduce Model\Aggregate
georgehristov 2ee790b [update] avoid modifying existing model Client
georgehristov 4a9f37c [update] move setup of properties to constructor
georgehristov d566c62 [update] add docs
georgehristov de06f03 [update] use strong argument typing
georgehristov ae45471 [update] rename properties to intuitive names
georgehristov 3dd1ab0 [update] phpdoc types
georgehristov 5cb2bf8 [update] allow to unset Model::$id_field
georgehristov 68d32d3 [update] use array_merge
georgehristov 8c69320 [update] arguments and return types
georgehristov 47fc81d [update] tests
georgehristov adb57dc [update] docs
georgehristov b6b0852 [update] add return type for Invoice
georgehristov a974658 [fix] phpstan issues
georgehristov a176a33 [update] optimize demo
georgehristov 665eb86 [update] LIMIT functionality
georgehristov 4e2221d Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek ae0a56a fix renamed TestCase class
mvorisek 722cbdf fix renamed atk4_money type
mvorisek 1f25740 add missing void return type for test cases
mvorisek 5c40110 fix renamespaced Dsql names
mvorisek d047cd5 fix stan
mvorisek cfae1b1 Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek ad9c90a fix typo in comment
mvorisek 41637d0 fix SQL render assertions
mvorisek a21ef63 fix renamed API
mvorisek 25dc215 fix comparison/bind for atk4_money typed values for Sqlite
mvorisek 4b956bc Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek f62907b Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek 0f9bbe8 fix tests by not enforcing use_table_prefixes
mvorisek e7639e8 workaround mysql server 8.0.27 bug in test
mvorisek 787c5d9 fix doc cs
mvorisek 138d064 Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 1fa050b adjust to the latest atk4/data (by phpstan)
mvorisek 5593643 fix assertions
mvorisek 55df20d client_id in transaction model
mvorisek 92654fc skip tests with wrong fields pushdown
mvorisek f403b82 fix grouping for PostgreSQL
mvorisek 98cec38 fix report test
mvorisek 564944c fix/use non-aliased field name for update/delete where
mvorisek 7353322 fix id typecasting in SQL persistence
mvorisek e0af1c5 dedup/impl insert/update/delete methods in main Persistence
mvorisek af5333b impl raw write methods
mvorisek 9dd61ba add support for model nesting for SQL
mvorisek ddc2db3 fix join/hasMany
mvorisek bcd74c5 impl write queries using nested Models
mvorisek a4438ea use "_tm" as default alias for model-in-model table
mvorisek 79b2743 drop unneeded composer requirements
mvorisek 96f6009 Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek d5337a0 fix/skip one test /w constant column for MSSQL
mvorisek 8374849 Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek c7ba8ff Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 9e95d1c do not accept badly formatted seeds
mvorisek 934041f fix unordered export assertions
mvorisek 59cd671 Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek eed9609 fix unordered export assertions
mvorisek d654352 subaction must not add table alias
mvorisek 6bf9c9a subaction must not wrap in parenthesis
mvorisek 8f27132 prepare for Union::groupBy always wraps
mvorisek fbc54ae drop deprecated hook alias
mvorisek 8e563e5 fix expr seeding
mvorisek a883a75 allow to group by non-selecting expr, but then do not add that field
mvorisek 58b83ee fix grouping for PostgreSQL
mvorisek 3fb83e6 Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 0540bf9 Merge branch 'model_in_model' into feature/introduce-aggregate-model
mvorisek 6b18dc7 Merge branch 'model_in_model' into feature/introduce-aggregate-union-…
mvorisek 02c64e3 Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek fb296e1 use "_tu" as default alias for Union model
mvorisek 035f36b createInvoiceAggregate must not add default "client" field
mvorisek 65ada49 impl Aggregate using model-in-model
mvorisek abfaabe do not skip WITH test for MariaDB
mvorisek 12c2c2a add model-in-model tests incl. hooks
mvorisek aab0bf9 test with "_id" ID column name
mvorisek 1a96086 fix different ID column across nested models
mvorisek d48a037 assert nested transactions
mvorisek e572ff6 Merge branch 'model_in_model' into feature/introduce-aggregate-model
mvorisek 5fe3df9 Merge branch 'model_in_model' into feature/introduce-aggregate-union-…
mvorisek 23a33c4 Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 3f51e91 Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek 0cea47b Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek e29bdee Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek a96f9d8 fixed mysql server 8.0.28 released
mvorisek 755bf26 Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek 0e315a2 Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 8be423b Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 081f694 Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek f451c5c drop withAggregateField method
mvorisek e9edb8b drop AggregatesTrait trait
mvorisek fcbb43c Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek 254bb67 rename Aggregate to AggregateModel
mvorisek d82ff1f Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 6492e17 Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 37fffd7 fix merge
mvorisek 91db9f8 rename Union to UnionModel
mvorisek 2a4f6df DEBUG add infinite recursion detection
mvorisek 4d827b8 drop wrong union grouping pushdown
mvorisek cdbd07a fix doc
mvorisek da5856f rename groupBy to setGroupBy as it mutates the model
mvorisek c24d974 Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 25c92cb Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek 335f261 Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 3db6a8a adjust to latest develop
mvorisek 3a020b6 Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 485d1ef adjust to latest develop
mvorisek 9349c88 Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek fc69c68 Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek e2cd2e2 adjust to latest develop
mvorisek 8ae2036 simplify
mvorisek 9c9fa6f fix cloned field - we should either disallow refs or wrap twice
mvorisek 2da2f6a compact assertSameExportUnordered assertions
mvorisek 07d1838 fix array merge
mvorisek 5d8ee39 fix count query
mvorisek 431da2e no false for initQueryFields
mvorisek 1a821a8 fix cloned field - we should either disallow refs or wrap twice
mvorisek 8e8bfd5 fix ii - do not clone field
mvorisek ffd69fd Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek e36543d Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 3716814 fix merge - no false for initQueryFields
mvorisek a46433d fix unaggregated fields for pgsql
mvorisek 27a9ced Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 265958f fix unaggregated fields for pgsql
mvorisek 95af333 compact test code
mvorisek d4063b3 Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek f8a2653 compact test code
mvorisek b4aa593 skip unsupported sql tests
mvorisek 222724a compact test code
mvorisek d57af82 rm ReportTest - same as ModelAggregateTest::testGroupLimit2
mvorisek 5520638 rename hook const
mvorisek c6c8921 fix cs
mvorisek c966abe rename hook const
mvorisek c424234 Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 6dd0eb2 Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 26d4b26 rm link to archived reports repo from README
mvorisek 002665a rm debug recursion detection
mvorisek 63c53cb rm pushdown note, it was wrong
mvorisek af7bba4 comments cleanup
mvorisek 1bb383b Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 3c12605 Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek b65a109 Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek b1d090f Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 4eeaaf8 Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 98b1f70 Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 77b11d8 WIP convert rst to md
mvorisek f3b910a fix cs
mvorisek f9ee26f fix merge
mvorisek 639bdb4 fix merge II
mvorisek bd15f65 WIP comment out failing test
mvorisek 8884678 fix cs
mvorisek d4c6fa6 convert rst to md
mvorisek e8ff052 Merge branch 'develop'
mvorisek 48117ac fix stan
mvorisek 01d93b6 Merge branch 'develop'
mvorisek a53543a fix test /w reference and has many
mvorisek d2f626d uncomment remaining test
mvorisek c8646b8 improve coverage
mvorisek c84cfc6 prevent child models mutation
mvorisek 8c7921e Merge branch 'develop'
mvorisek 06f309c Merge branch 'develop'
mvorisek 6a5f2b8 Merge branch 'develop'
mvorisek a82a108 do no wrap inner from in extra select
mvorisek b4fbe57 rm UnionModel::createSubAction() method
mvorisek 1c8abad improve subQuery case
mvorisek 0cc8f36 Merge branch 'develop'
mvorisek 9c0385f Merge branch 'develop'
mvorisek 3eb55af Merge branch 'develop'
mvorisek d17f009 adjust for latest atk4/data
mvorisek 62affa7 fix cs
mvorisek 33fb29d fix typo
mvorisek 0b85726 fix variable names in docs
DarkSide666 26cfd6f Merge branch 'develop'
mvorisek f35f810 fix cs
mvorisek 526adae Merge branch 'develop'
mvorisek 5676f2f improve phpstan ignores
mvorisek 278d530 Merge branch 'develop'
mvorisek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| | @@ -22,6 +22,7 @@ static | |
| references | ||
| expressions | ||
| joins | ||
| unions | ||
| aggregates | ||
| hooks | ||
| deriving | ||
| | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| :::{php:namespace} Atk4\Data | ||
| ::: | ||
| | ||
| (Unions)= | ||
| | ||
| # Model Unions | ||
| | ||
| :::{php:class} Model\UnionModel | ||
| ::: | ||
| | ||
| In some cases data from multiple models need to be combined. In this case the UnionModel model comes very handy. | ||
| In the case used below Client model schema may have multiple invoices and multiple payments. Payment is not related to the invoice.: | ||
| | ||
| ``` | ||
| class Client extends \Atk4\Data\Model { | ||
| public $table = 'client'; | ||
| | ||
| protected function init(): void | ||
| { | ||
| parent::init(); | ||
| | ||
| $this->addField('name'); | ||
| | ||
| $this->hasMany('Payment'); | ||
| $this->hasMany('Invoice'); | ||
| } | ||
| } | ||
| ``` | ||
| | ||
| (see tests/ModelUnionTest.php, tests/Model/Client.php, tests/Model/Payment.php and tests/Model/Invoice.php files). | ||
| | ||
| ## Union Model Definition | ||
| | ||
| Normally a model is associated with a single table. Union model can have multiple nested models defined and it fetches | ||
| results from that. As a result, Union model will have no "id" field. Below is an example of inline definition of Union model. | ||
| The Union model can be separated in a designated class and nested model added within the init() method body of the new class: | ||
| | ||
| ``` | ||
| $unionPaymentInvoice = new \Atk4\Data\Model\UnionModel(); | ||
| | ||
| $nestedInvoice = $unionPaymentInvoice->addNestedModel(new Invoice()); | ||
| $nestedPayment = $unionPaymentInvoice->addNestedModel(new Payment()); | ||
| ``` | ||
| | ||
| Next, assuming that both models have common fields "name" and "amount", `$unionPaymentInvoice` fields can be set: | ||
| | ||
| ``` | ||
| $unionPaymentInvoice->addField('name'); | ||
| $unionPaymentInvoice->addField('amount', ['type' => 'atk4_money']); | ||
| ``` | ||
| | ||
| Then data can be queried: | ||
| | ||
| ``` | ||
| $unionPaymentInvoice->export(); | ||
| ``` | ||
| | ||
| ## Define Fields | ||
| | ||
| Below is an example of 3 different ways to define fields for the UnionModel model: | ||
| | ||
| ``` | ||
| // will link the "name" field with all the nested models | ||
| $unionPaymentInvoice->addField('client_id'); | ||
| | ||
| // Expression will not affect nested models in any way | ||
| $unionPaymentInvoice->addExpression('name_capital', ['expr' => 'upper([name])']); | ||
| | ||
| // UnionModel model can be joined with extra tables and define some fields from those joins | ||
| $unionPaymentInvoice | ||
| ->join('client', 'client_id') | ||
| ->addField('client_name', 'name'); | ||
| ``` | ||
| | ||
| {ref}`Expressions` and {ref}`Joins` are working just as they would on any other model. | ||
| | ||
| ## Field Mapping | ||
| | ||
| Sometimes the field that is defined in the UnionModel model may be named differently inside nested models. | ||
| E.g. Invoice has field "description" and payment has field "note". | ||
| When defining a nested model a field map array needs to be specified: | ||
| | ||
| ``` | ||
| $nestedInvoice = $unionPaymentInvoice->addNestedModel(new Invoice()); | ||
| $nestedPayment = $unionPaymentInvoice->addNestedModel(new Payment(), ['description' => '[note]']); | ||
| $unionPaymentInvoice->addField('description'); | ||
| ``` | ||
| | ||
| The key of the field map array must match the UnionModel field. The value is an expression. (See {php:meth}`Model::addExpression`). | ||
| This format can also be used to reverse sign on amounts. When we are creating "Transactions", then invoices would be | ||
| subtracted from the amount, while payments will be added: | ||
| | ||
| ``` | ||
| $nestedInvoice = $mUnion->addNestedModel(new Invoice(), ['amount' => '-[amount]']); | ||
| $nestedPayment = $mUnion->addNestedModel(new Payment(), ['description' => '[note]']); | ||
| $unionPaymentInvoice->addField('description'); | ||
| ``` | ||
| | ||
| Should more flexibility be needed, more expressions (or fields) can be added directly to nested models: | ||
| | ||
| ``` | ||
| $nestedInvoice = $unionPaymentInvoice->addNestedModel(new Invoice(), ['amount' => '-[amount]']); | ||
| $nestedPayment = $unionPaymentInvoice->addNestedModel(new Payment(), ['description' => '[note]']); | ||
| | ||
| $nestedInvoice->addExpression('type', ['expr' => '\'invoice\'']); | ||
| $nestedPayment->addExpression('type', ['expr' => '\'payment\'']); | ||
| $unionPaymentInvoice->addField('type'); | ||
| ``` | ||
| | ||
| A new field "type" has been added that will be defined as a static constant. | ||
| | ||
| ## Referencing an UnionModel Model | ||
| | ||
| Like any other model, UnionModel model can be assigned through a reference. In the case here one Client can have multiple transactions. | ||
| Initially a related union can be defined: | ||
| | ||
| ``` | ||
| $client->hasMany('Transaction', new Transaction()); | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| <?php | ||
| | ||
| declare(strict_types=1); | ||
| | ||
| namespace Atk4\Data\Model; | ||
| | ||
| use Atk4\Core\TrackableTrait; | ||
| use Atk4\Data\Exception; | ||
| use Atk4\Data\Model; | ||
| use Atk4\Data\Persistence; | ||
| | ||
| /** | ||
| * Map self::action() to self::getOwner()->actionInnerTable(). | ||
| * | ||
| * Called from https://github.com/atk4/data/blob/5.0.0/src/Persistence/Sql.php#L188. | ||
| * | ||
| * @method Model getOwner() | ||
| * | ||
| * @internal | ||
| */ | ||
| class UnionInternalTable | ||
| { | ||
| use TrackableTrait; | ||
| | ||
| /** | ||
| * @param array<mixed> $args | ||
| * | ||
| * @return Persistence\Sql\Query | ||
| */ | ||
| public function action(string $mode, array $args = []) | ||
| { | ||
| if ($mode !== 'select' || $args !== []) { | ||
| throw new Exception('Only "select" action with empty arguments is expected'); | ||
| } | ||
| | ||
| $model = $this->getOwner(); | ||
| | ||
| $tableOrig = $model->table; | ||
| $model->table = '_tu'; | ||
| try { | ||
| return $model->actionSelectInnerTable(); // @phpstan-ignore method.notFound | ||
| } finally { | ||
| $model->table = $tableOrig; | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is "static constant" here? Minimal example would be good.