{"id":24016285,"url":"https://github.com/decodelabs/archetype","last_synced_at":"2025-10-29T05:02:21.320Z","repository":{"id":56964543,"uuid":"429099249","full_name":"decodelabs/archetype","owner":"decodelabs","description":"Simple class name resolution for PHP","archived":false,"fork":false,"pushed_at":"2025-04-14T11:30:12.000Z","size":151,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2025-04-15T14:06:42.529Z","etag":null,"topics":["class-loader","php","resolver"],"latest_commit_sha":null,"homepage":"","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/decodelabs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-11-17T15:25:57.000Z","updated_at":"2025-04-14T11:30:16.000Z","dependencies_parsed_at":"2023-11-27T11:48:00.229Z","dependency_job_id":"44317c21-483a-4d65-8568-f7e5576de3dc","html_url":"https://github.com/decodelabs/archetype","commit_stats":{"total_commits":71,"total_committers":1,"mean_commits":71.0,"dds":0.0,"last_synced_commit":"aac510e53d44f6dcbfce6ccb4d020cccb46b2ded"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decodelabs%2Farchetype","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decodelabs%2Farchetype/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decodelabs%2Farchetype/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decodelabs%2Farchetype/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/decodelabs","download_url":"https://codeload.github.com/decodelabs/archetype/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249085436,"owners_count":21210267,"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":["class-loader","php","resolver"],"created_at":"2025-01-08T08:48:49.121Z","updated_at":"2025-10-29T05:02:21.302Z","avatar_url":"https://github.com/decodelabs.png","language":"PHP","readme":"# Archetype\n\n[![PHP from Packagist](https://img.shields.io/packagist/php-v/decodelabs/archetype?style=flat)](https://packagist.org/packages/decodelabs/archetype)\n[![Latest Version](https://img.shields.io/packagist/v/decodelabs/archetype.svg?style=flat)](https://packagist.org/packages/decodelabs/archetype)\n[![Total Downloads](https://img.shields.io/packagist/dt/decodelabs/archetype.svg?style=flat)](https://packagist.org/packages/decodelabs/archetype)\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/decodelabs/archetype/integrate.yml?branch=develop)](https://github.com/decodelabs/archetype/actions/workflows/integrate.yml)\n[![PHPStan](https://img.shields.io/badge/PHPStan-enabled-44CC11.svg?longCache=true\u0026style=flat)](https://github.com/phpstan/phpstan)\n[![License](https://img.shields.io/packagist/l/decodelabs/archetype?style=flat)](https://packagist.org/packages/decodelabs/archetype)\n\n### Simple class name resolution for PHP\n\nArchetype provides a generic frontend to resolving implementation classes for a named interface with an extensible plugin architechture.\n\n---\n\n## Installation\n\nThis package requires PHP 8.4 or higher.\n\nInstall via Composer:\n\n```bash\ncomposer require decodelabs/archetype\n```\n\n## Usage\n\nUse `Archetype` when designing plugin oriented libraries that need to load arbitrary extension classes based on a naming convention.\n\nBy mapping names to classes in an extensible and customisable resolver structure, `Archetype` allows fast and reliable means to create loosely coupled plugin ecosystems.\n\n```php\nuse DecodeLabs\\Archetype;\nuse MyInterface;\n\n$archetype = new Archetype();\n$class = $archetype-\u003eresolve(MyInterface::class, 'MyClass');\n```\n\n\nIt is especially useful in `Factory` patterns where you need to load arbitrary classes based on a name.\n\nExample:\n\n```php\n\n// Main library\nnamespace My\\Library\n{\n\n    use DecodeLabs\\Archetype;\n\n    interface Thing {}\n\n    class Factory {\n\n        public function __construct(\n            private Archetype $archetype\n        ) {\n            $this-\u003earchetype = $archetype;\n        }\n\n        public function loadThing(\n            string $name\n        ): Thing {\n            // Resolve name to class for Thing interface\n            $class = $this-\u003earchetype-\u003eresolve(Thing::class, $name);\n            return new $class();\n        }\n    }\n}\n\n\n// Thing implementations\nnamespace My\\Library\\Thing\n{\n\n    use My\\Library\\Thing;\n\n    class Box implements Thing {}\n    class Potato implements Thing {}\n    class Dog implements Thing {}\n}\n\n\n\n// Calling code\nnamespace My\\App\n{\n\n    use My\\Library\\Factory;\n\n    $factory = new Factory(new Archetype());\n\n    $box = $factory-\u003eloadThing('Box');\n    $potato = $factory-\u003eloadThing('Potato');\n    $dog = $factory-\u003eloadThing('Dog');\n}\n```\n\n## Resolvers\n\nArchetype uses a hierarchy of `Resolvers` to turn a name into a class. By default, the `Handler` will fall back on a generic resolver that simply locates the named class within the namespace of the associated interface.\n\nIn the above example, the implementations of the `My\\Library\\Thing` can be found at `My\\Library\\Thing\\\\*`.\n\n\n### Custom resolvers\n\nThe `Resolver\\Archetype` implementation however will also automatically look for custom `Resolver` classes in the same location as the target interface, named `\\\u003cInterface\\\u003eArchetype`.\n\nThe following example will replace the default functionality and cause Archetype to look in a different location for the `Thing` implementations:\n\n```php\nnamespace My\\Library {\n\n    use DecodeLabs\\Archetype\\Resolver;\n\n    class ThingArchetype implements Resolver\n    {\n\n        public function getInterface(): string\n        {\n            return Thing::class;\n        }\n\n        public function getPriority(): int\n        {\n            return 10;\n        }\n\n        public function resolve(string $name): ?string\n        {\n            return 'Some\\\\Other\\\\Namespace\\\\'.$name;\n        }\n    }\n}\n```\n\n### Multiple resolvers\n\nMultiple `Resolver` instances can be stacked against a single interface, called in series based on the priority they request, the first one to return a non-null class name wins.\n\nAlternative `Resolvers` can be loaded with:\n\n```php\nuse My\\Library\\Resolver\\Alternative as AlternativeResolver;\n\n$archetype = new Archetype();\n$archetype-\u003eregister(new AlternativeResolver());\n```\n\n### Class scanning\n\nSome resolvers (including the default one) can scan and list all classes resolvable under a namespace.\n\n```php\nforeach($archetype-\u003escanClasses(Thing::class) as $path =\u003e $class) {\n    echo 'Found class: '.$class.' at '.$path.PHP_EOL;\n}\n```\n\n\n### File lookup\n\n`Resolvers` that also implement the `Finder` interface can define the means to lookup a file path based on the provided name, against the space defined by the target interface.\n\nThis can be useful when the _space_ that is defined by the root interface may contain assets aside from PHP code.\n\nIt is down to the implementation to decide how to map names to file paths (there are no pre-built default `Finder` classes).\n\nExample:\n\n```php\nnamespace My\\Library {\n\n    use DecodeLabs\\Archetype\\Finder;\n\n    class ThingArchetype implements Finder\n    {\n\n        public function getInterface(): string\n        {\n            return Thing::class;\n        }\n\n        public function getPriority(): int\n        {\n            return 10;\n        }\n\n        public function resolve(\n            string $name\n        ): ?string {\n            return 'Some\\\\Other\\\\Namespace\\\\'.$name;\n        }\n\n        public function findFile(\n            string $name\n        ): ?string {\n            return './some/other/namespace/'.$name.'.jpg';\n        }\n    }\n}\n\n\nnamespace My\\App {\n\n    use My\\Library\\Thing;\n\n    $boxImagePath = $archetype-\u003efindFile(Thing::class, 'box');\n}\n```\n\n\n## Licensing\nArchetype is licensed under the MIT License. See [LICENSE](./LICENSE) for the full license text.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdecodelabs%2Farchetype","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdecodelabs%2Farchetype","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdecodelabs%2Farchetype/lists"}