$customer = ['Id' => 21, 'Name' => 'Janis Zarinsh']; $order = ['Id' => 32, 'Amount' => 43.32, 'Currency' => 'EUR']; $data = []; $data['Customer'] = $customer; $data['SaleOrder'] = $order;
Any "leaf" of a tree or part of a tree (subtree) is addressed "by" - listing all the keys on the way to the goal: $orderId = $data['SaleOrder']['Id'];
In PHP using magic methods you can do the same thing like this: $customer = new DataObject(['Id' => 21, 'Name' => 'Janis Zarinsh']); $order = new DataObject(['Id' => 32, 'Amount' => 43.32]); $order->setCurrency('EUR'); $data = new DataObject(); $data->setCustomer($customer); $data->setSaleOrder($order);
Addressing in a more familiar form (as the path to the file in * nix): $orderId = $data->getData('/SaleOrder/Id');
What do we have as a result? Container for transferring any data. A description of PHP by a developer of objects similar to POJOs in Java is reduced to annotating their accessors (get / set methods) so that you can use auto-completion in the IDE. You can do the same thing through the @property annotation, it will be even slightly shorter (although it will require another implementation of DataObject, via get, set), but it’s more convenient for me like this: /** * @method array getBaseCalcData() * @method void setBaseCalcData(array $data) * @method array getDependentCalcData() * @method void setDependentCalcData(array $data) */ class GetForDependentCalc extends DataObject {}
As the author of this object, I determined the properties that I use for my own purposes. A universal container will transfer the data I use from one data handler to another (for example, from one of my services to another of my services) and absolutely will not mind if other data will be added to it (for example, by any extension written completely). another developer). Moreover, you can "teach" a universal container to automatically convert the data stored in it into a format, for example, JSON, and transfer this data from the server side to the browser. Together with my data, the container also converts the data prepared by third-party extension of my code on the server side and used by third-party extension of my code on the client side. In some way, a universal data container contradicts the object-oriented paradigm, separating in the application pure data objects and objects handlers. But this is, rather, not a contradiction, but a boundary case of the use of OOP — like a POJO. A universal data container can coexist with OOP as well as RDBMS - after all, after all, RDBMS is also a kind of “universal data container”. Theoretically, any database can be placed in an associative array (if we are talking about data, and not about handlers, a trigger / procedure / function). function tooManyArgs($arg1, $arg2, $arg3) {}
If you limit the number of input arguments to the processor function to one single argument (as well as the result of the function’s operation): function oneArgOnly($data) {}
then you can get very interesting consequences in the form of chains of processor functions, where the output of some functions are input data for others. An example of the practical application of this approach is the promise in JavaScript: httpGet(...) .then(...) .then(...) .then(...)
In PHP, a handler pipeline could look something like this: function proc5(DataObject $arg) { $result = new DataObject(); $customer = $arg->getData('/Customer'); $order = $arg->getData('/SaleOrder'); // ... $result->setData('/Transaction', $trans); return $result; } function proc6(DataObject $arg) { $result = new DataObject(); $transaction = $arg->getData('/Transaction'); // ... $result->setData('/Balance', $balance); return $result; } $res5 = proc5($data); $res6 = proc6($res1); $amount = $res6->getData('/Balance/Amount');
It is possible from a set of similar processor functions at a descriptive level to build a data processing flow: <workflow> <step id="5"> <handler id="proc5"> <input> <map as="/Customer"> <handler>proc3</handler> <result/> </map> <map as="/SaleOrder"> <handler>proc4</handler> <result/> </map> </input> </handler> </step> <step id="6"> <handler id="proc6"> <input> <map as="/Transaction"> <handler>proc5</handler> <result/> </map> </input> </handler> </step> </workflow>
and change it depending on the data being processed: <workflow> <step id="7"> <case> <condition if="qt"> <left output="proc5">/Balance/Amount</left> <right>0</right> </condition> <then> <handler id="proc7">...</handler> </then> <else> <handler id="proc8">...</handler> </else> </case> </step> </workflow>
This technique will be, as they say, "a hundred years at lunch," but it has its niche .Source: https://habr.com/ru/post/273261/
All Articles