{"id":498,"date":"2013-01-17T01:51:39","date_gmt":"2013-01-17T00:51:39","guid":{"rendered":"http:\/\/codingexplained.com\/?p=498"},"modified":"2017-06-11T22:25:14","modified_gmt":"2017-06-11T20:25:14","slug":"zend-framework-2-service-manager","status":"publish","type":"post","link":"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager","title":{"rendered":"Zend Framework 2 Service Manager"},"content":{"rendered":"<p>The service manager in Zend Framework 2 is an implementation of the service locator design pattern. Hence, the terms service locator and service manager will be used interchangeably throughout this section. It is a central registry known as a service locator whose purpose is to retrieve services \u2014 or less formally \u2014 objects. The service manager knows how to lazily instantiate services when they are needed. This approach implements the inversion of control (IoC) technique such that object coupling is bound at runtime rather than compile time. It furthermore makes dependency injection simple.<\/p>\n<p>In Zend Framework 1, the <span class=\"code\">Zend_Registry<\/span> component was the closest thing to a service manager. It was, as the name suggests, simply a registry consisting of key-value pairs. The service manager in Zend Framework 2 is much more than that as will be seen in this section.<\/p>\n<p>The approaches discussed are usually defined in the modules&#8217; configuration files in practice. These configuration files are often large PHP arrays, where the service manager would be configured under the <span class=\"code\">service_manager<\/span> key. To keep the examples simple and intuitive, an imperative approach is taken instead.<\/p>\n<p>Please note that the keys used for the service manager should be unique across all modules. The service manager is commonly configured using a configuration within each module. These configuration files are merged by the module manager, hence why entries will be lost in the case of duplicates. The entries are stored in arrays within the <span class=\"code\">Zend\\ServiceManager\\ServiceManager<\/span> class, and thus two identical keys cannot exist within the same array. This is also why using an object oriented approach to configure the service manager will lead to the same conclusion. As a result, keys should at least be prepended by the module name, but using the entire namespace would be best practice. That being said, this is not the case for the examples to come; for the sake of simplicity, simpler keys are used.<\/p>\n<h3 id=\"invokables\">Invokables<\/h3>\n<p>An invokable is a string that contains a fully qualified class name. Fully qualified means that namespaces are included. When the service manager receives a request for an invokable, it instantiates the fully qualified class and returns the object. Below are examples of how an invokable can be added to the service manager as well as how to use it.<\/p>\n<pre><code class=\"php\">\/\/ Add invokable to service manager\r\n$serviceManager-&gt;setInvokableClass('user_mapper', 'User\\Mapper\\UserMapper');<\/code><\/pre>\n<p>In the above line of code, an invokable with the name <span class=\"code\">user_mapper<\/span> is added to the service manager instance. When this invokable is invoked, an instance of the <span class=\"code\">User\\Mapper\\UserMapper<\/span> class is returned. This is demonstrated below.<\/p>\n<pre><code class=\"php\">\/\/ Use invokable to retrieve an object\r\n$userMapper = $serviceManager-&gt;get('user_mapper');<\/code><\/pre>\n<p>The service manager&#8217;s <span class=\"code\">get<\/span> method is a generic method for obtaining a service, independent of the way the service is fetched. Thus, it is used regardless of whether the service is fetched by using an invokable or factory, for instance. What happens if the key matches an invokable is simply that the invokable&#8217;s class is instantiated. When the invokable was added to the service manager, it specified the <span class=\"code\">User\\Mapper\\User<\/span> class. This value is looked up and used to instantiate the class, like shown below.<\/p>\n<pre><code class=\"php\">\/\/ $className contains 'User\\Mapper\\UserMapper'\r\nreturn new $className();<\/code><\/pre>\n<h3 id=\"factories\">Factories<\/h3>\n<p>Another approach is to use so-called factories, which are used to perform any setup or dependency injection for the requested object.<\/p>\n<p>A factory can be either a PHP callable, an object or a fully qualified class name. If an object or a class name is provided, the class must implement <span class=\"code\">Zend\\ServiceManager\\FactoryInterface<\/span>, which defines a <span class=\"code\">createService<\/span> method. This method takes a <span class=\"code\">ServiceLocatorInterface<\/span> instance as its sole parameter, meaning that the service locator can be used to resolve dependencies needed to instantiate the object. The method is called by the service manager and should return the object that it instantiates. The same principles apply if a PHP callable is used instead.<\/p>\n<p>Expanding the previous example, imagine that the <span class=\"code\">UserMapper<\/span> class depends upon a database adapter. By using dependency injection, a database adapter can be injected into its constructor. To accomplish this, a factory can be used instead of an invokable. An anonymous function \u2014 or closure \u2014 is specified, which is responsible for instantiating the requested service along with its dependencies.<\/p>\n<pre><code class=\"php\">$serviceManager-&gt;setFactory('user_mapper', function($serviceManager) {\r\n\t$dbAdapter = $serviceManager-&gt;get('Zend\\Db\\Adapter\\Adapter');\r\n\treturn new \\User\\Mapper\\UserMapper($dbAdapter);\r\n});\r\n\r\n$userMapper = $serviceManager-&gt;get('user_mapper'); \/\/ Get user mapper<\/code><\/pre>\n<p>In this particular example, the service manager is used to obtain a database adapter so that it can be injected into the user mapper&#8217;s constructor. The user mapper is then returned and is ready for use.<\/p>\n<h3 id=\"abstract-factories\">Abstract Factories<\/h3>\n<p>An abstract factory is essentially a fallback in case a non-existing service is requested from the service manager. In such a scenario, the attached abstract factories will be queried to see if one of them can return the requested service.<\/p>\n<p>With abstract factories, there are two possible approaches; a string representing a fully qualified class name or an object. In both cases, the class must implement <span class=\"code\">Zend\\ServiceManager\\AbstractFactoryInterface<\/span>. This interface specifies two methods which will be explained below.<\/p>\n<pre><code class=\"php\">public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);<\/code><\/pre>\n<p>The method above does, as its name indicates, determine whether or not the abstract factory can create a service with the provided name. To determine this, the service that was requested is also provided. The method must return a boolean value.<\/p>\n<pre><code class=\"php\">public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);<\/code><\/pre>\n<p>The above method is responsible for creating a service with a given name and returning it.<\/p>\n<h3 id=\"initializers\">Initializers<\/h3>\n<p>Sometimes it is useful to be able to perform additional initialization tasks when an object is fetched from the service manager. Initializers specify a block of code to be executed when a service is retrieved from the service manager. The newly created instance is passed and it can thus be manipulated.<\/p>\n<p>An initializer can be either a PHP callable, object or string containing a fully qualified class name. If an object or string is used, then the class must implement <span class=\"code\">Zend\\ServiceManager\\InitializerInterface<\/span>.<\/p>\n<p>In a previous example, a mapper class was instantiated by using a factory method. It would quickly get tedious to write a factory for every mapper class. Instead, an anonymous function can be added as an initializer. The created object instance is passed to the function along with the service manager. This makes it possible to initialize a newly created object instance before it is returned from the call to the service manager&#8217;s <span class=\"code\">get<\/span> method.<\/p>\n<pre><code class=\"php\">$serviceManager-&gt;addInitializer(function($instance, $serviceManager) {\r\n\tif ($instance instanceof Zend\\Db\\Adapter\\AdapterAwareInterface) {\r\n$instance-&gt;setDbAdapter($serviceManager-&gt;get('Zend\\Db\\Adapter\\Adapter'));\r\n\t}\r\n});<\/code><\/pre>\n<p>In this example, it is assumed that mapper classes implement <span class=\"code\">AdapterAwareInterface<\/span> which specifies the <span class=\"code\">setDbAdapter<\/span> method. As a result, a database adapter can be set on the object if it implements this interface, and this is therefore done automatically for all objects of this type. This means that fetching the database adapter and assigning it to a mapper does not have to be done once for each mapper class. It is, however, important to note that the function above is only executed when a service is fetched from the service manager, and therefore the service manager should have knowledge on how to create an instance. In this case, a fully qualified class name would be sufficient; the initializer could then handle the rest of the initialization.<\/p>\n<p>Another thing to note is that every service that is retrieved from the service manager will trigger all of the initializers. Since the service manager is heavily used in Zend Framework 2, this impacts performance. These \u201cglobal\u201d initializers should therefore be kept at a minimum. It is true that initializers can also be added to controllers, for instance, which means that they will be executed when a controller is instantiated. Either way, it is important to consider how frequently an initialization will actually be carried out, or the \u201chit rate\u201d of the initialization. If the initialization should only happen for very few objects, it would probably not be worth it to suffer the performance impact. Should it, on the other hand, be done for the majority of the created objects, then it would indeed be a viable solution. In many cases, optimizations like these are not very important, so the main point is to avoid stuffing things into initializers for convenience.<\/p>\n<h3 id=\"aliases\">Aliases<\/h3>\n<p>An alias points from one service to another, so when a service with an aliased name is requested, a different name should be used instead. For instance, if a service A is an alias for a service B, then a request for service A would actually return service B. Aliases can be of invokables, factories or other aliases, and hence they can be recursive. This means that a service A can be an alias for service B, which in turn can be an alias for service C, and so on. In this scenario, requesting service A from the service manager would return service C.<\/p>\n<p>This gives a lot of flexibility, particularly because of Zend Framework 2&#8217;s modular structure. An application may be using <span class=\"code\">Zend\\Db\\Adapter\\Adapter<\/span> for database connectivity and hence a module can refer directly to this key in the service manager. This may, however, not be the case, in which case a lot of references would have to be updated. To make matters even worse, refactoring strings can prove to be a difficult task, even for modern IDEs. If an alias was used instead, one could do like shown in the below example.<\/p>\n<pre><code class=\"php\">$serviceManager-&gt;setAlias('user_db_adapter', 'Zend\\Db\\Adapter\\Adapter');\r\n$dbAdapter = $serviceManager-&gt;get('user_db_adapter');<\/code><\/pre>\n<p>An alias is created such that a request for <span class=\"code\">user_db_adapter<\/span> actually retrieves <span class=\"code\">Zend\\Db\\Adapter\\Adapter<\/span>, which could theoretically be another alias. The point to note here is that the actual database adapter has only been defined once in the module. A user module could thus refer to <span class=\"code\">user_db_adapter<\/span> whenever it needs to retrieve a database adapter. Should the database adapter be changed, the changes to be done in the modules are minimal. Module developers also do not have to make any assumptions of which database adapter people are using, because if an alias is used, this can easily be configured when the module is installed.<\/p>\n<h3 id=\"shared-services\">Shared Services<\/h3>\n<p>Services registered with a service manager can be either shared or not shared. In this context, the term shared refers to whether or not a new instance of a service is created on every request. Thus, if a service is shared, then an arbitrary number of requests for a given service will return the exact same object instance. Otherwise, a new instance will be created on every request. Services are shared by default.<\/p>\n<p>Using the previous mapper example, this behavior can be demonstrated with the following examples.<\/p>\n<pre><code class=\"php\">$mapper1 = $serviceManager-&gt;get('user_mapper');\r\n$mapper2 = $serviceManager-&gt;get('user_mapper');\r\n\r\n\/\/ The following line outputs: bool(true)\r\nvar_dump((spl_object_hash($mapper1) === spl_object_hash($mapper2)));<\/code><\/pre>\n<p>This example uses the default behavior and shows how the exact instance that was initially returned and stored in <span class=\"code\">$mapper1<\/span> is returned on the next request for the service. This means that <span class=\"code\">$mapper1<\/span> and <span class=\"code\">$mapper2<\/span> contain exactly the same content; a reference to the same <span class=\"code\">User\\Mapper\\UserMapper<\/span> object. This becomes clear when comparing the hash IDs stored in the two variables; the output shows that the comparison returns <span class=\"code\">true<\/span>, and thus the hashes are indeed identical.<\/p>\n<p>The next example shows how a new instance is returned if the shared option is set to <span class=\"code\">false<\/span>.<\/p>\n<pre><code class=\"php\">$serviceManager-&gt;setShared('user_mapper', false);\r\n$mapper3 = $serviceManager-&gt;get('user_mapper');\r\n\r\n\/\/ The following line outputs: bool(false)\r\nvar_dump((spl_object_hash($mapper2) === spl_object_hash($mapper3)));<\/code><\/pre>\n<p>This time, the service manager request returns a new instance because the service is no longer shared across requests. Therefore, a newly created and unique object of <span class=\"code\">User\\Mapper\\UserMapper<\/span> is stored in <span class=\"code\">$mapper3<\/span>. As with the previous example, this becomes evident when comparing the object hash IDs.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Service Manager in Zend Framework 2 is much more than a registry of key-value pairs. This article walks through the Service Manager&#8217;s many features and gives examples of how to use each one.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[38],"tags":[40,39,66],"series":[],"jetpack_publicize_connections":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Zend Framework 2 Service Manager<\/title>\n<meta name=\"description\" content=\"Learn how to use the Service Manager in Zend Framework 2. This article walks through its features and demonstrates them with code examples.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Zend Framework 2 Service Manager\" \/>\n<meta property=\"og:description\" content=\"Learn how to use the Service Manager in Zend Framework 2. This article walks through its features and demonstrates them with code examples.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager\" \/>\n<meta property=\"og:site_name\" content=\"Coding Explained\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/codingexplained\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/codingexplained\" \/>\n<meta property=\"article:published_time\" content=\"2013-01-17T00:51:39+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-06-11T20:25:14+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/codingexplained.com\/wp-content\/uploads\/2015\/11\/codingexplained-fb-promote.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"444\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Bo Andersen\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@codingexplained\" \/>\n<meta name=\"twitter:site\" content=\"@codingexplained\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Bo Andersen\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager\",\"url\":\"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager\",\"name\":\"Zend Framework 2 Service Manager\",\"isPartOf\":{\"@id\":\"https:\/\/codingexplained.com\/#website\"},\"datePublished\":\"2013-01-17T00:51:39+00:00\",\"dateModified\":\"2017-06-11T20:25:14+00:00\",\"author\":{\"@id\":\"https:\/\/codingexplained.com\/#\/schema\/person\/e19c92ec991f571605f047cefeaa950d\"},\"description\":\"Learn how to use the Service Manager in Zend Framework 2. This article walks through its features and demonstrates them with code examples.\",\"breadcrumb\":{\"@id\":\"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/codingexplained.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Zend Framework 2 Service Manager\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/codingexplained.com\/#website\",\"url\":\"https:\/\/codingexplained.com\/\",\"name\":\"Coding Explained\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/codingexplained.com\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/codingexplained.com\/#\/schema\/person\/e19c92ec991f571605f047cefeaa950d\",\"name\":\"Bo Andersen\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/codingexplained.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/28f5826f9d5d544b0c5e1ec321dfdfb8?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/28f5826f9d5d544b0c5e1ec321dfdfb8?s=96&d=mm&r=g\",\"caption\":\"Bo Andersen\"},\"description\":\"I am a back-end web developer with a passion for open source technologies. I have been a PHP developer for many years, and also have experience with Java and Spring Framework. I currently work full time as a lead developer. Apart from that, I also spend time on making online courses, so be sure to check those out!\",\"sameAs\":[\"https:\/\/codingexplained.com\",\"https:\/\/www.facebook.com\/codingexplained\",\"https:\/\/www.linkedin.com\/in\/ba0708\",\"https:\/\/twitter.com\/codingexplained\",\"https:\/\/www.youtube.com\/c\/codingexplained\"],\"url\":\"https:\/\/codingexplained.com\/author\/andy\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Zend Framework 2 Service Manager","description":"Learn how to use the Service Manager in Zend Framework 2. This article walks through its features and demonstrates them with code examples.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager","og_locale":"en_US","og_type":"article","og_title":"Zend Framework 2 Service Manager","og_description":"Learn how to use the Service Manager in Zend Framework 2. This article walks through its features and demonstrates them with code examples.","og_url":"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager","og_site_name":"Coding Explained","article_publisher":"https:\/\/www.facebook.com\/codingexplained","article_author":"https:\/\/www.facebook.com\/codingexplained","article_published_time":"2013-01-17T00:51:39+00:00","article_modified_time":"2017-06-11T20:25:14+00:00","og_image":[{"width":1200,"height":444,"url":"https:\/\/codingexplained.com\/wp-content\/uploads\/2015\/11\/codingexplained-fb-promote.png","type":"image\/png"}],"author":"Bo Andersen","twitter_card":"summary_large_image","twitter_creator":"@codingexplained","twitter_site":"@codingexplained","twitter_misc":{"Written by":"Bo Andersen","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager","url":"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager","name":"Zend Framework 2 Service Manager","isPartOf":{"@id":"https:\/\/codingexplained.com\/#website"},"datePublished":"2013-01-17T00:51:39+00:00","dateModified":"2017-06-11T20:25:14+00:00","author":{"@id":"https:\/\/codingexplained.com\/#\/schema\/person\/e19c92ec991f571605f047cefeaa950d"},"description":"Learn how to use the Service Manager in Zend Framework 2. This article walks through its features and demonstrates them with code examples.","breadcrumb":{"@id":"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/codingexplained.com\/coding\/php\/zend-framework\/zend-framework-2-service-manager#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/codingexplained.com\/"},{"@type":"ListItem","position":2,"name":"Zend Framework 2 Service Manager"}]},{"@type":"WebSite","@id":"https:\/\/codingexplained.com\/#website","url":"https:\/\/codingexplained.com\/","name":"Coding Explained","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/codingexplained.com\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/codingexplained.com\/#\/schema\/person\/e19c92ec991f571605f047cefeaa950d","name":"Bo Andersen","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/codingexplained.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/28f5826f9d5d544b0c5e1ec321dfdfb8?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/28f5826f9d5d544b0c5e1ec321dfdfb8?s=96&d=mm&r=g","caption":"Bo Andersen"},"description":"I am a back-end web developer with a passion for open source technologies. I have been a PHP developer for many years, and also have experience with Java and Spring Framework. I currently work full time as a lead developer. Apart from that, I also spend time on making online courses, so be sure to check those out!","sameAs":["https:\/\/codingexplained.com","https:\/\/www.facebook.com\/codingexplained","https:\/\/www.linkedin.com\/in\/ba0708","https:\/\/twitter.com\/codingexplained","https:\/\/www.youtube.com\/c\/codingexplained"],"url":"https:\/\/codingexplained.com\/author\/andy"}]}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p3mJkW-82","_links":{"self":[{"href":"https:\/\/codingexplained.com\/wp-json\/wp\/v2\/posts\/498"}],"collection":[{"href":"https:\/\/codingexplained.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codingexplained.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codingexplained.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codingexplained.com\/wp-json\/wp\/v2\/comments?post=498"}],"version-history":[{"count":10,"href":"https:\/\/codingexplained.com\/wp-json\/wp\/v2\/posts\/498\/revisions"}],"predecessor-version":[{"id":3051,"href":"https:\/\/codingexplained.com\/wp-json\/wp\/v2\/posts\/498\/revisions\/3051"}],"wp:attachment":[{"href":"https:\/\/codingexplained.com\/wp-json\/wp\/v2\/media?parent=498"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codingexplained.com\/wp-json\/wp\/v2\/categories?post=498"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codingexplained.com\/wp-json\/wp\/v2\/tags?post=498"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/codingexplained.com\/wp-json\/wp\/v2\/series?post=498"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}