{"id":18750644,"url":"https://github.com/webiny/servicemanager","last_synced_at":"2025-11-26T20:30:17.952Z","repository":{"id":20228733,"uuid":"23500596","full_name":"webiny/ServiceManager","owner":"webiny","description":"[READ-ONLY] PHP component that enables you to define services and re-use them in any part of your code. With this component you can solve any dependency injection problems you might have. (master at Webiny/Framework)","archived":false,"fork":false,"pushed_at":"2017-11-26T21:25:24.000Z","size":29,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-12-28T22:53:14.885Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://www.webiny.com/","language":"PHP","has_issues":false,"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/webiny.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}},"created_at":"2014-08-30T20:57:58.000Z","updated_at":"2022-10-27T04:41:02.000Z","dependencies_parsed_at":"2022-08-21T17:21:19.343Z","dependency_job_id":null,"html_url":"https://github.com/webiny/ServiceManager","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2FServiceManager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2FServiceManager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2FServiceManager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2FServiceManager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/webiny","download_url":"https://codeload.github.com/webiny/ServiceManager/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239635836,"owners_count":19672239,"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-07T17:12:41.249Z","updated_at":"2025-11-26T20:30:17.893Z","avatar_url":"https://github.com/webiny.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"Service Manager\n===============\n\nInstall the component\n---------------------\nThe best way to install the component is using Composer.\n\n```bash\ncomposer require webiny/service-manager\n```\nFor additional versions of the package, visit the [Packagist page](https://packagist.org/packages/webiny/service-manager).\n\n## Usage\n\nAvailable service configuration parameters are:\n\n* `Class`\n* `Arguments` (`Object` \u0026 `ObjectArguments`)\n* `Abstract`\n* `Calls`\n* `Scope`\n\nExtra parameters, for factory services, are:\n\n* `Factory` - class or service\n* `Static` (Optional) - defaults to TRUE, means that `Method` will be called statically on `Factory` object\n* `Method` - a method to call on `Factory` object\n* `MethodArguments` (Optional) - method arguments for `Method`\n\nThere are 2 possible types of scope:\n\n* `container` (Default) - only 1 instance of service is created, and is re-used on each subsequent request of service\n* `prototype` - a new instance of service is created each time a service is requested\n\n## Service definition\n\nTo register a service you need to create a service config object (using `ConfigObject` class) and pass it to `ServiceManager`\n\nYou can either create your configuration files in YAML or use plain PHP and build arrays straight from your code.\nIf using PHP - call `new ConfigObject($configArray)` to build a proper config object.\nIf using YAML - call `$config = Config::getInstance()-\u003eyaml($pathToYourConfigFile);`\n\nBasic service definition takes only `Class` parameter:\n\n```php\n$config = [\n    'Class' =\u003e '\\My\\Service\\Class'\n];\n\nServiceManager::getInstance()-\u003eregisterService('MyService', new ConfigObject($config));\n\n// Now get your service\n$myService = ServiceManager::getInstance()-\u003egetService('MyService');\n\n```\n\nYou can group your services in logic groups, by creating an array of service definitions and then registering them as a group:\n\n```php\n$config = [\n    'MyLogger' =\u003e [\n        'Class' =\u003e '\\My\\Service\\Class'\n    ],\n    'MyMailer' =\u003e [\n        'Class' =\u003e '\\My\\Mailer\\Class'\n    ]\n];\n\nServiceManager::getInstance()-\u003eregisterServices('MyServiceGroup', new ConfigObject($config));\n\n// Now get your specific service\n$myMailer = ServiceManager::getInstance()-\u003egetService('MyServiceGroup.MyMailer');\n\n```\n\n\n## Constructor arguments\n\nYou can provide constructor arguments to your service class, by using `Arguments` parameter. Argument can be any value, including class name (it will be instantiated and passed to constructor as a PHP object) and a reference to another service (enter service reference using `@` character):\n\n```php\n$config = [\n    'Class' =\u003e '\\My\\Service\\Class'\n    'Arguments' =\u003e ['FirstArgument', [1,2,3], '\\This\\Class\\Will\\Be\\Instantiated', '@someOtherService']\n];\n```\n\nIn case you need to provide constructor parameters to your argument class or service, you will need to use an extended arguments syntax (here is a config example written in YAML):\n\n```yaml\nClass: \\My\\Service\\Class\nArguments:\n    name: FirstArgument\n    ids: [1,2,3]\n    some_instance:\n        Object: \\This\\Class\\Will\\Be\\Instantiated\n        ObjectArguments: [Name, Y-m-d]\n    some_service:\n        Object: @some.other.service\n        ObjectArguments: [Name]\n```\n\n## Creating service from a YAML config file\n\nTo create a `ConfigObject` out of your YAML file and register a new service, simply call:\n\n```php\n$config = Config::getInstance()-\u003eyaml($pathToYourConfigFile);\nServiceManager::getInstance()-\u003eregisterService('MyNewService', $config);\n```\n\n## Service object method calls\n\nIn case you need to call some methods on your service instance, you can specify them using `Calls` parameter:\n\n```yaml\nClass: \\My\\Service\\Class\nArguments: [FirstArgument, [1,2,3], \\This\\Class\\Will\\Be\\Instantiated, @some.other.service]\nCalls:\n    - [yourMethod]\n    - [yourMethodWithArguments, [Arg1, 123]]\n    - [yourMethodWithClassArgument, [\\Some\\Class\\That\\Will\\Be\\Instantiated]]\n    - [yourMethodWithServiceArgument, [@some_service]]\n```\n\n## Abstract services and parameters\nService manager also supports abstract services. When you have 2 or more services sharing similar functionality, you can extract common stuff into an abstract service. In the following example we also use `Parameters`. Parameters are like variables, define them once, and reuse whenever you need them.\n\nParameters config file:\n\n```yaml\n# Definition of parameters\nlogger.class: \\Webiny\\Component\\Logger\\Logger\nlogger.driver.class: \\Webiny\\Component\\Logger\\Drivers\\Webiny\nlogger.handler.udp.class: \\Webiny\\Component\\Logger\\Drivers\\Webiny\\Handlers\\UDPHandler\n```\n\n\u003e NOTE: At the moment, parameters can not be used in ObjectArguments. \n\nServices config file (this can also be defined in plain PHP array):\n\n```yaml\nUdpHandler:\n    Class: %logger.handler.udp.class%\nTrayLoggerAbstract:\n    Abstract: true\n    Class: %logger.class%\n    Calls:\n      - [addHandler, [@UdpHandler]]\nWebinySystem:\n    Parent: @TrayLoggerAbstract\n    Arguments: [System, %logger.driver.class%]\nWebinyEcommerce:\n    Parent: @TrayLoggerAbstract\n    Arguments: [Ecommerce, %logger.driver.class%]\n```\nNow we need to register parameters and services with `ServiceManager`:\n\n```php\n// Registering multiple parameters at once\n$parameters = Config::getInstance()-\u003eyaml($pathToYourParametersConfigFile);\nServiceManager::getInstance()-\u003eregisterParameters($parameters);\n\n// Registering one parameter\nServiceManager::getInstance()-\u003eregisterParameter('someClassName', '\\Webiny\\Some\\Class\\Name');\n\n// Registering your services\n$servicesConfig = Config::getInstance()-\u003eyaml($pathToYourServicesConfigFile);\nServiceManager::getInstance()-\u003eregisterServices('Logger', new ConfigObject($servicesConfig));\n```\n\nIn this example we defined and abstract service `TrayLoggerAbstract` and 2 real loggers that extend the abstract service, `WebinySystem` and `WebinyEcommerce`. These 2 loggers share same class and method calls, but have different constructor arguments.\n\nYou can also specify arguments in abstract class and later override them in the real class. Also, you can add more method calls from child service:\n\n```yaml\n# Services\nUdpHandler:\n    Class: %logger.handler.udp.class%\nTrayLoggerAbstract:\n    Abstract: true\n    Class: %logger.class%\n    Arguments: [Default, %logger.driver.class%]\n    Calls:\n      - [addHandler, [@UdpHandler]]\nWebinySystem:\n    Parent: @TrayLoggerAbstract\n    Calls:\n    - [setSomething, [someParameter]]\nWebinyEcommerce:\n    Parent: @TrayLoggerAbstract\n    Arguments: [Ecommerce, %logger.driver.class%]\n```\n\nIn this last example, `WebinySystem` service will be constructed using the arguments from parent service and will also add an extra method call. `WebinyEcommerce` will provide it's own arguments to the parent constructor and will inherit the parent's `Calls`.\n\nIf you need to replace a method in `Calls` parameter, specify the third argument in call definition with the index of method to replace. In the following example, child method `setSomething` will replace the parent method at index 0, which is `addHandler`:\n\n```yaml\nUdpHandler:\n    Class: %logger.handler.udp.class%\nTrayLoggerAbstract:\n    Abstract: true\n    Class: %logger.class%\n    Arguments: [Default, %logger.driver.class%]\n    Calls:\n      - [addHandler, [@UdpHandler]]\nWebinySystem:\n    Parent: @TrayLoggerAbstract\n    Calls:\n    - [setSomething, [someParameter], 0]\n```\n\nIf you want to replace all of the parent `Calls`, put an exclamation mark in front of the `Calls` key, and make it look like this - `!Calls`:\n\n```yaml\nUdpHandler:\n    Class: %logger.handler.udp.class%\nTrayLoggerAbstract:\n    Abstract: true\n    Class: %logger.class%\n    Arguments: [Default, %logger.driver.class%]\n    Calls:\n      - [addHandler, [@UdpHandler]]\nWebinySystem:\n    Parent: @TrayLoggerAbstract\n    !Calls:\n    - [setSomething, [someParameter]]\n```\n\nIn this case, child service `Calls` will completely replace parent `Calls`.\n\n## Accessing services from PHP\n\nTo use `ServiceManager` in your code, the easiest way is to simply use `ServiceManagerTrait`. This will give you access to `$this-\u003eservice()`.\n\n```php\nclass YourClass{\n    use ServiceManagerTrait;\n    \n    public function yourMethod(){\n        $service = $this-\u003eservice('YourServiceName');\n    }\n}\n```\n\nIf you do need to access ServiceManager class directly, use it like this:\n\n```php\nServiceManager::getInstance()-\u003egetService('YourServiceName')\n```\n\n## Accessing services by tags\nYou can group services by using tags and load all of related services using single call. To achieve that, you need to add `tags` key to your service configuration:\n\n\n```yaml\nWebinySystem:\n    Parent: @TrayLoggerAbstract\n    !Calls:\n    - [setSomething, [someParameter]]\n    Tags: [logger]\nWebinyCustom:\n    Parent: @TrayLoggerAbstract\n    Tags: [logger, custom_logger]\n```\n\nNow execute the following piece of code. The result will be an array containing two services: `WebinySystem` and `WebinyCustom`:\n\n```php\nclass YourClass{\n    use ServiceManagerTrait;\n    \n    public function yourMethod(){\n        $services = $this-\u003eservicesByTag('logger');\n    }\n}\n```\n\nYou can also tell `ServiceManager` to filter the services using a given interface or a class name. It fill first fetch all services containing the requested tag and then filter them using the given class or interface name, before returning the final result set to you. This way you are sure you only get what you need and don't have to make checks yourself, resulting in a cleaner code:\n\n```php\nclass YourClass{\n    use ServiceManagerTrait;\n    \n    public function yourMethod(){\n        $services = $this-\u003eservicesByTag('cms_plugin', '\\Your\\Expected\\Class\\Or\\Interface');\n    }\n}\n```\n\nResources\n---------\n\nTo run unit tests, you need to use the following command:\n\n    $ cd path/to/Webiny/Component/ServiceManager/\n    $ composer.phar install\n    $ phpunit","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebiny%2Fservicemanager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebiny%2Fservicemanager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebiny%2Fservicemanager/lists"}