{"id":19857967,"url":"https://github.com/boldare/xsolve-model-factory","last_synced_at":"2025-06-21T10:05:36.921Z","repository":{"id":46707051,"uuid":"111918167","full_name":"boldare/xsolve-model-factory","owner":"boldare","description":"This library provides a versatile skeleton for organizing model factories.","archived":false,"fork":false,"pushed_at":"2021-09-29T11:05:06.000Z","size":21,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-21T10:04:21.787Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boldare.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-24T12:52:04.000Z","updated_at":"2021-09-29T11:03:56.000Z","dependencies_parsed_at":"2022-08-27T08:41:39.781Z","dependency_job_id":null,"html_url":"https://github.com/boldare/xsolve-model-factory","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/boldare/xsolve-model-factory","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boldare%2Fxsolve-model-factory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boldare%2Fxsolve-model-factory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boldare%2Fxsolve-model-factory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boldare%2Fxsolve-model-factory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boldare","download_url":"https://codeload.github.com/boldare/xsolve-model-factory/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boldare%2Fxsolve-model-factory/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261103180,"owners_count":23109928,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T14:20:33.304Z","updated_at":"2025-06-21T10:05:31.898Z","avatar_url":"https://github.com/boldare.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/xsolve-pl/xsolve-model-factory.svg?branch=master)](https://travis-ci.org/xsolve-pl/xsolve-model-factory)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/xsolve-pl/xsolve-model-factory/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/xsolve-pl/xsolve-model-factory/?branch=master)\n[![Latest Stable Version](https://poser.pugx.org/xsolve-pl/model-factory/v/stable)](https://packagist.org/packages/xsolve-pl/model-factory)\n[![Total Downloads](https://poser.pugx.org/xsolve-pl/model-factory/downloads)](https://packagist.org/packages/xsolve-pl/model-factory)\n[![Monthly Downloads](https://poser.pugx.org/xsolve-pl/model-factory/d/monthly)](https://packagist.org/packages/xsolve-pl/model-factory)\n[![License](https://poser.pugx.org/xsolve-pl/model-factory/license)](https://packagist.org/packages/xsolve-pl/model-factory)\n\nTable of contents\n=================\n\n  * [Introduction](#introduction)\n  * [License](#license)\n  * [Getting started](#getting-started)\n  * [Usage examples](#usage-examples)\n    * [Implementing model factory](#implementing-model-factory)\n    * [Using external dependencies in model](#using-external-dependencies-in-model)\n    * [Grouping model factories into collections](#grouping-model-factories-into-collections)\n    * [Creating nested models](#creating-nested-models)\n\nIntroduction\n============\n\nThis library provides a versatile skeleton for organizing model factories.\n\nIt can be used to provide objects that will be later on passed to some\nserializer and returned via API, or some adapters or facades for your objects\nbefore they are handed over to some other libraries or bundles.\n\nIt aims to empower models so that they can easily get access to some services or\ncreate nested models lazily without requiring much work upfront.\n\nIf you want to use this library in a Symfony application you may be interested in\nusing the dedicated bundle available at\n[xsolve-pl/model-factory-bundle](https://packagist.org/packages/xsolve-pl/model-factory-bundle).\n\nLicense\n=======\n\nThis library is under the MIT license. See the complete license in `LICENSE` file.\n\nGetting started\n===============\n\nInclude this library in your project using Composer as follows\n(assuming it is installed globally):\n\n```bash\n$ composer require xsolve-pl/model-factory\n```\n\nFor more information on Composer see its\n[Introduction](https://getcomposer.org/doc/00-intro.md).\n\n\n\nUsage examples\n==============\n\nImplementing model factory\n--------------------------\n\nThis library defines a simple interface for model factory that provides\ninformation about whether it supports given object (i.e. is able to produce\nmodel object appropriate for given object) and instantiate such model object.\nIt also include convenient methods allowing to operate on multiple objects at\nonce. See `Xsolve\\ModelFactory\\ModelFactory\\ModelFactoryInterface` for\nmore details.\n\nOne you are free to implement this interface with your own model factory\nclasses, a basic abstract class for model factory is included as well in\n`Xsolve\\ModelFactory\\ModelFactory\\ModelFactory`. It includes all the\nnecessary logic and leaves out only a public `supportsObject` method and a\nprotected `instantiateModel` method to be implemented. Using it as a base\nclass creating a new model factory class becomes very easy:\n\n```php\n\u003c?php\n\nnamespace Example;\n\nuse Xsolve\\ModelFactory\\ModelFactory\\ModelFactory;\n\nclass FooModelFactory extends ModelFactory\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function supportsObject($object)\n    {\n        return ($object instanceof Foo);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function instantiateModel($object)\n    {\n        /* @var Foo $object */\n        return new FooModel($object);\n    }\n}\n```\n\nUsing external dependencies in model\n------------------------------------\n\nThere are cases where some external dependency is required in model object\nto return some value. Simple example would be having an model object\nrepresenting a package for which volumetric weight needs to be calculated\n(which results from multiplying its volume by some coefficient specific for\neach shipment company). A helper class calculating such value would usually\nbe defined as a service in DI container, with coefficient provided via\nsome config files or fetched from some data storage.\n\nWith this library it is extremely easy to gain access to such services in model\nobject by utilizing\n`Xsolve\\ModelFactory\\ModelFactory\\ModelFactoryAwareModelInterface`. If\n`Xsolve\\ModelFactory\\ModelFactory\\ModelFactory` was used as a base class\nfor your model factory class, then every model implementing aforementioned\ninterface will be injected with model factory that was used to produce it.\nSince model factories can be defined as services themselves, they can be\ninjected with any service from DI container and can expose public proxy methods\nfor model objects to access them.\n\nFollowing example presents sample usage of this interface. First we define\nmodel factory class:\n\n```php\n\u003c?php\n\nnamespace Example;\n\nuse Xsolve\\ModelFactory\\ModelFactory\\ModelFactory;\n\nclass BazModelFactory extends ModelFactory\n{\n    /**\n     * @var VolumetricWeightCalculator\n     */\n    protected $volumetricWeightCalculator;\n\n    /**\n     * @param VolumetricWeightCalculator $volumetricWeightCalculator\n     */\n    public function __construct(VolumetricWeightCalculator $volumetricWeightCalculator)\n    {\n        $this-\u003evolumetricWeightCalculator = $volumetricWeightCalculator;\n    }\n\n    /**\n     * @return VolumetricWeightCalculator\n     */\n    public function getVolumetricWeightCalculator()\n    {\n        return $this-\u003evolumetricWeightCalculator;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function supportsObject($object)\n    {\n        return ($object instanceof Baz);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function instantiateModel($object)\n    {\n        /* @var Baz $object */\n        return new BazModel($object);\n    }\n}\n```\n\nOur model class would look as follows (note that\n`Xsolve\\ModelFactory\\ModelFactory\\ModelFactoryAwareModelTrait` is\nused here to provide convenient `setModelFactory` and `getModelFactory` methods):\n\n```php\n\u003c?php\n\nnamespace Example;\n\nuse Xsolve\\ModelFactory\\ModelFactory\\ModelFactoryAwareModelInterface;\nuse Xsolve\\ModelFactory\\ModelFactory\\ModelFactoryAwareModelTrait;\n\nclass BazModel implements ModelFactoryAwareModelInterface\n{\n    use ModelFactoryAwareModelTrait;\n\n    /**\n     * @var Baz\n     */\n    protected $baz;\n\n    /**\n     * @param Baz $baz\n     */\n    public function __construct(Baz $baz)\n    {\n        $this-\u003ebaz = $baz;\n    }\n\n    /**\n     * @return float\n     */\n    public function getVolume()\n    {\n        return ($this-\u003ebaz-\u003egetLength() * $this-\u003ebaz-\u003egetWidth() * $this-\u003ebaz-\u003egetHeight());\n    }\n\n    /**\n     * @return float\n     */\n    public function getVolumetricWeight()\n    {\n        return $this\n            -\u003egetModelFactory()\n            -\u003egetVolumetricWeightCalculator()\n            -\u003ecalculate($this-\u003egetVolume());\n    }\n}\n```\n\nGrouping model factories into collections\n-----------------------------------------\n\nTo make it easy to produce models for multiple objects it is possible to\ngroup model factories into collections. If your application provides multiple\nAPI (or multiple API versions that are so different that they utilize\ncompletely different models) you are able to group factories in separate\ncollections and avoid the risk of producing incorrect models.\n\nBasic implementation of model factory collection is provided in\n`Xsolve\\ModelFactory\\ModelFactoryCollection\\ModelFactoryCollection`\nclass. It allows to register multiple model factories via its\n'addModelFactory` method and provides same interface as a single\nmodel factory, so that it is completely interchangable. Its methods attempt\nto find appropriate model factory for each object provided.\n\n```php\n\u003c?php\n\nnamespace Example;\n\nuse Xsolve\\ModelFactory\\ModelFactoryCollection\\ModelFactoryCollection;\n\n$fooModelFactory = new FooModelFactory();\n$bazModelFactory = new BazModelFactory();\n\n$modelFactoryCollection = new ModelFactoryCollection();\n$modelFactoryCollection\n    -\u003eaddModelFactory($fooModelFactory)\n    -\u003eaddModelFactory($bazModelFactory);\n\n$foo1 = $storage-\u003egetFoo(1);\n$baz1 = $storage-\u003egetBaz(1);\n\n$foo1Model = $modelFactoryCollection-\u003ecreateModel($foo1);\n$baz1Model = $modelFactoryCollection-\u003ecreateModel($baz1);\n\n```\n\nThis snippet defines one model factory collections `$modelFactoryCollection` and two model\nfactories `$fooModelFactory` and `$bazModelFactory` which are added to the collection.\n\nAfterwards it is possible to call `createModel` method (as well as other methods\ncharacteristic for model factories) on the collection and model will be created as long as\nthere is one and only one model factory supporting given object.\n\nCreating nested models\n----------------------\n\nIn some cases the models you would like to produce can contain other models\n(e.g. produced for objects associated with the root object). If this nesting\nis deep (as it may be for some APIs optimized for SPA applications that aim\nto reduce number of requests required to fetch data) it becomes tedious to\nbuild all models upfront and connect them in a proper way. An easier solution\nis to empower models to be able to produce nested models on their own via the\nsame model factory collection that was used to instantiate themselves.\n\nTo achieve this your model may implement\n`Xsolve\\ModelFactory\\ModelFactoryCollection\\ModelFactoryCollectionAwareModelInterface`\nwhich will result in model factory collection that was used to create the model\nto be injected to it. The basic implementation of this interface is provided in\n`Xsolve\\ModelFactory\\ModelFactoryCollection\\ModelFactoryCollectionAwareModelTrait`.\n\nLet's assume that previously presented `Example\\Foo` class object contains a\nproperty containing an array of `Example\\Baz` class objects and we want this\nassociation to be carried to model objects as well. If both `Example\\FooModelFactory`\nand `Example\\BazModelFactory` are a part of the same model factory collection\nand instances of `Example\\FooModel` class are instantiated via collection's\n`createModel` or `createModels` methods of this collection, implementation of\n`Example\\FooModel` class could look as follows:\n\n```php\n\u003c?php\n\nnamespace Example;\n\nuse Xsolve\\ModelFactory\\ModelFactoryCollection\\ModelFactoryCollectionAwareModelInterface;\nuse Xsolve\\ModelFactory\\ModelFactoryCollection\\ModelFactoryCollectionAwareModelTrait;\n\nclass FooModel implements ModelFactoryCollectionAwareModelInterface\n{\n    use ModelFactoryCollectionAwareModelTrait;\n\n    /**\n     * @var Foo\n     */\n    protected $foo;\n\n    /**\n     * @param Foo $foo\n     */\n    public function __construct(Foo $foo)\n    {\n        $this-\u003efoo = $foo;\n    }\n\n    /**\n     * @return BazModel[]\n     */\n    public function getBazs()\n    {\n        return $this\n            -\u003egetModelFactoryCollection()\n            -\u003ecreateModels($this-\u003efoo-\u003egetBazs());\n    }\n}\n```\n\nOf course if `Example\\BazModel` implements the same interface it will also be\ninjected with the same model factory collection and will be able to produce\nmodels for nested objects - it's as easy as that!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboldare%2Fxsolve-model-factory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboldare%2Fxsolve-model-factory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboldare%2Fxsolve-model-factory/lists"}