{"tag":"dependency injection","articles":{"projects\/micrus-v4":{"key":"projects\/micrus-v4","type":"article","published":true,"meta":{"createdAt":"2018-01-28T12:45:41+01:00","publishedAt":"2018-01-28T12:40:00+01:00","group":"micrus","links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/micrus.avris.it","displayUrl":null},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/Micrus","displayUrl":null}],"category":"projects","subcategory":null,"slug":"micrus-v4"},"content":{"en":{"slug":"micrus-v4","title":"Micrus v4 \u2022 Beauty of simplicity","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/micrus-demo_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022279.53757225434\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEgklEQVRIicWWy44bRRSGv1NdfbE9Y0+scTJBIQosgGwQICEWvAAb3oGX4hV4CRYsWCAuEkgIERCCEEKSGWcSz3hst12Xw6K6fZkJGyTgqOVqd50+9Z\/z\/12nRJMBoKocHx9js4yyqphOz+l293BuRZZllGXJ+fkZZdkhhgAC+\/0+ZVGwbSKCqq5HgOn9x2CUjsk5mzyEm7fpdDo45zg4OFj7ydc\/nTR365\/d4AiKrmc2znrFtzVtp7bChRAQbSKIIMZceikN9tNvHzVZtRGkvV4IcAeG6g423XFSaJJ50Zyy\/Z4imkZrshZMm5SuqyVyeaUX1UV3cekmEb2CtPVpqJRNXkgarTXbgJoZEaTxfve1Ef1uzlc\/j\/ngnVt8\/sMTnjxfbBaj1ckmKxE47HfwMRKjEiMU1hBUmdeeehV2C9mMqmC7uUkwRLbKmji7ddjj\/bvXAXjtpT5lnvHhe7f55LNfWPmwlfbm3cIaepUlaMQKRAMYwaAYIwy6lk4uzGq\/RaYkyhTszf0ilasJGJvggvDmnSHf3Dum3yt45eaAr348ZtArePuVIb8+Pmv8dxWcW6HKM0JstCFCjBEQoiohRHLJsC2l2nLWAHLBUUdDP1dqDw\/PA93c8PqhZfL0Kb52nM5gfjbB157xDLpVzlEvBfAq3Bs7vn9c40NEEbql4VrHMqgyEBhUBh8Ua2C+ijyfJ9qu7+csHIwvPMNuxqtDi3z08RdqAMQkLWkqcSZw93rJG7eukZtIgWe\/EDCG356teKlyfPfI8eWfnplLWhGgU2YMewXj6RIUjEDtGnpjREXxARZL3yqW3BgQMIDNTSvEVF4UFivP09pztnB8+fuMw\/2CvdJiM4OqMl04AKbLgI9KbpQoSbz1MvKwdolKTV9giMrKe0IjchCMQGYSzT5GUJLu3nq5h\/Pw5HzJn88WTOYOVYiAc46lD5yeC3lmyDJDlVvKPCMzwnLlGE8umNcritxSFJZeVXLQK7GZTV+ZQoxKCIaoEGLER8UAEUWi4pvqirHYUancO3c4Hxn2CoZ7JSjUPuBaZ92IPjOCaspouXL0OgXdKifGiI9wUS+Zzmuu7XW4PdonzwwhJBAtIEEQ02zDknqBUXDBI4t6+fc94H8wK+tdMfFts+w\/BaCqW1uHYtPAmpPT06c8ePCAo6MbIIaqLBmNRuvu3Qb5J\/fbz9ZgoqaTA01rXNSrLYVAWeT\/SiX+zmKMOB9ou6Hd9ONkIQTOziY450GVvCgYDodXAi0Wc+7f\/x3JLEVnnzu3jjCXDgchBMbjE55Pa4y1HFwbcuOgt3NO2vTA9N+mRtrSlh4aY9a9zTnHyckJVVUxGAzWi4kYBoMBe3t7O89baxfM84JBT4nVAf1etaZsG9Q2jetT0lZrJUZFYyTGyGqZTosXFxdMJpPNipIxz\/qcectv4xlLH7ey3nKr9lnmA0SETm6uzF9K46qoE7i0e9osw+YZIQSMMcxms3U1DJFunJI5IUZlcnpBCJHR6JA83+jQhprKXWCC4Y9TJSjcGfVecPRLBP0FlaGMv+a4vYsAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/micrus-demo_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022279.53757225434\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA framework doesn\u2019t have to be overly complex! Micrus provides you with a quick, easy and comfortable way of creating neatly structured, modular MVC websites, which can be easily extended and configured.\u003C\/p\u003E\n\u003Cp\u003EOur goal is to keep the framework as simple as possible, while offering all the most important features.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/micrus-demo_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022559.07514450867\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEgklEQVRIicWWy44bRRSGv1NdfbE9Y0+scTJBIQosgGwQICEWvAAb3oGX4hV4CRYsWCAuEkgIERCCEEKSGWcSz3hst12Xw6K6fZkJGyTgqOVqd50+9Z\/z\/12nRJMBoKocHx9js4yyqphOz+l293BuRZZllGXJ+fkZZdkhhgAC+\/0+ZVGwbSKCqq5HgOn9x2CUjsk5mzyEm7fpdDo45zg4OFj7ydc\/nTR365\/d4AiKrmc2znrFtzVtp7bChRAQbSKIIMZceikN9tNvHzVZtRGkvV4IcAeG6g423XFSaJJ50Zyy\/Z4imkZrshZMm5SuqyVyeaUX1UV3cekmEb2CtPVpqJRNXkgarTXbgJoZEaTxfve1Ef1uzlc\/j\/ngnVt8\/sMTnjxfbBaj1ckmKxE47HfwMRKjEiMU1hBUmdeeehV2C9mMqmC7uUkwRLbKmji7ddjj\/bvXAXjtpT5lnvHhe7f55LNfWPmwlfbm3cIaepUlaMQKRAMYwaAYIwy6lk4uzGq\/RaYkyhTszf0ilasJGJvggvDmnSHf3Dum3yt45eaAr348ZtArePuVIb8+Pmv8dxWcW6HKM0JstCFCjBEQoiohRHLJsC2l2nLWAHLBUUdDP1dqDw\/PA93c8PqhZfL0Kb52nM5gfjbB157xDLpVzlEvBfAq3Bs7vn9c40NEEbql4VrHMqgyEBhUBh8Ua2C+ijyfJ9qu7+csHIwvPMNuxqtDi3z08RdqAMQkLWkqcSZw93rJG7eukZtIgWe\/EDCG356teKlyfPfI8eWfnplLWhGgU2YMewXj6RIUjEDtGnpjREXxARZL3yqW3BgQMIDNTSvEVF4UFivP09pztnB8+fuMw\/2CvdJiM4OqMl04AKbLgI9KbpQoSbz1MvKwdolKTV9giMrKe0IjchCMQGYSzT5GUJLu3nq5h\/Pw5HzJn88WTOYOVYiAc46lD5yeC3lmyDJDlVvKPCMzwnLlGE8umNcritxSFJZeVXLQK7GZTV+ZQoxKCIaoEGLER8UAEUWi4pvqirHYUancO3c4Hxn2CoZ7JSjUPuBaZ92IPjOCaspouXL0OgXdKifGiI9wUS+Zzmuu7XW4PdonzwwhJBAtIEEQ02zDknqBUXDBI4t6+fc94H8wK+tdMfFts+w\/BaCqW1uHYtPAmpPT06c8ePCAo6MbIIaqLBmNRuvu3Qb5J\/fbz9ZgoqaTA01rXNSrLYVAWeT\/SiX+zmKMOB9ou6Hd9ONkIQTOziY450GVvCgYDodXAi0Wc+7f\/x3JLEVnnzu3jjCXDgchBMbjE55Pa4y1HFwbcuOgt3NO2vTA9N+mRtrSlh4aY9a9zTnHyckJVVUxGAzWi4kYBoMBe3t7O89baxfM84JBT4nVAf1etaZsG9Q2jetT0lZrJUZFYyTGyGqZTosXFxdMJpPNipIxz\/qcectv4xlLH7ey3nKr9lnmA0SETm6uzF9K46qoE7i0e9osw+YZIQSMMcxms3U1DJFunJI5IUZlcnpBCJHR6JA83+jQhprKXWCC4Y9TJSjcGfVecPRLBP0FlaGMv+a4vYsAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/micrus-demo_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022559.07514450867\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA framework doesn\u2019t have to be overly complex! Micrus provides you with a quick, easy and comfortable way of creating neatly structured, modular MVC websites, which can be easily extended and configured.\u003C\/p\u003E\n\u003Cp\u003EOur goal is to keep the framework as simple as possible, while offering all the most important features.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["container","dependency injection","doctrine","event dispatcher","framework","full-stack","micrus","mvc","php","routing","twig"],"hasMore":false,"image":"https:\/\/avris.it\/image\/micrus-demo_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/micrus-demo_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/micrus-demo_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022139.76878612717\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA framework doesn\u2019t have to be overly complex! Micrus provides you with a quick, easy and comfortable way of creating neatly structured, modular MVC websites, which can be easily extended and configured.\u003C\/p\u003E\n\u003Cp\u003EOur goal is to keep the framework as simple as possible, while offering all the most important features.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/micrus-demo_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/micrus-demo_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022139.76878612717\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA framework doesn\u2019t have to be overly complex! Micrus provides you with a quick, easy and comfortable way of creating neatly structured, modular MVC websites, which can be easily extended and configured.\u003C\/p\u003E\n\u003Cp\u003EOur goal is to keep the framework as simple as possible, while offering all the most important features.\u003C\/p\u003E","words":51,"readTime":null,"lang":"en"}}},"projects\/avris-container":{"key":"projects\/avris-container","type":"article","published":true,"meta":{"createdAt":"2018-01-09T20:22:03+01:00","publishedAt":"2018-01-09T20:21:00+01:00","group":null,"links":[{"icon":"brands gitlab","colour":"primary","url":"https:\/\/gitlab.com\/Avris\/Container","displayUrl":null}],"category":"projects","subcategory":null,"slug":"avris-container"},"content":{"en":{"slug":"avris-container","title":"Avris Container","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-container_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHlklEQVRIiX2XyY8kRxXGf2+JyKyqruplZnq8zoA3MAYsNmFkIYwlLwgBAsRikBAc4ADiwJ\/AnRsHBOIMJ8TFgAQCgS3ZEptYjbEweLwNlsczvVR3V1dmxOOQNW0EiFBGZkoZyxffFy\/el3LuNXdElIoQRK0QFXOnlkIQqAiuhqmS3Fkuj6m1QgREIICIIAxFRBARILhaImJV68mTqIiAimDumAhNM8IjhIig1IIECFBKQRgGVtUBqCjUSlKlX02AyKodJ+1FAARVeXVyufouRC2IGhGv9jOEpIbWgl\/tIChBJQI0BNFhMkJQdUDoS8UQFCFEMdUVG8NCkOHb6lrdDHdjuewQgYhhgSKKrvqaKm5GUsVDFGpZETwwQgQSgqrhppgIJoqbIlGptVJrGQZwH1ZfK6p2IpWKELUSBOsbG+xcvgJUCEEcohZUBQLMlGRG8quABFCBumJLQERXMhiKYmZkS4ybBqLn8OiIxp0mOdkTtVZK6elLAWHYL7UCcO3ZbY7350AdSItANa9AKaaDxNkUF01EdEgYSEVPNqmgZgO1llBRVAwVZ9JM2Bytc2W+i4YSJWg8oZ4hCiFC33cDQwLnz53jn888i0ggAaaCEEBCJFaSKckU15Tpg1XE2NVYAdWBHTVMjexOtoRiiCSanHjtmTUODuccdx1nr9lmeXTIfG8fEyG7UqNy9\/3v4eknnmSWG4IYIgtQHURRBRFIpmQ3PDQhaSUXQg0wUVQNFcXNcTWyZ1yEZE6SRNKGra11PvLZj7G1ucHPv\/cjnrvwHNaskXyIpun6Gnff+x7+\/IvH2GhHQCEiBjAqqICZYDqw5i44uUF6p9ZY6QugiBpqjojh5qgm3GxVE\/e879089KVP8NSv\/8LDX\/8uicJt115H1Mr+wRzPxqe\/+hV+\/f0fcsNsxrJ01OiJKIN0uoquNOyhnBRTcGkn1K4gtQ7nUABiiDhqiWSOqpHMaVNm7M7nvvhRHvjwPcyv7PPDbz5M1hGb45abb7mOg91L7B4uuPfLnyKpUC88z+uv3WZ+dMiiX1JqT6kdaCW5YSa4K8mFlAyX8QxZ9lAqAcMeQRFJqBjiiaxOmxLjlHjoM\/fxwIfvAeAPj\/6JRMN0bcrauGH\/8hHn3\/5m7v\/A3Xjb8PjXvs326XU0Onb3gr5PlBgAhVRUg5QddyElxbPgMppC7qGAhEIogoI4aMLUSebklLjzztfywY+\/9yQl7L0059TZM1x\/fpvzd9zIjW+9icnpGRHBcz9+hMkoU+oabdOTmwpSqdHR90uidqiBamBu5MbxJDjTdegLETKAiSG6DMc1oTiyOgA\/84X3nZzMAA9+\/j7+s0QELzzyG5YvX+LMa05xvJvpDnaYaYdYRSyotaP2xwg9aoK5knLGmwbX6ZRUGPIMioeSMLI4OYysRkZ5653nuP76rf8C8O+llsLTP\/kV+089TTtR2vUxZ26\/gX53wt5FQWWJ0IFkoiRE6hBhybGcsWaETzemlAKsGDIED6cVo0VpMZoq3PXOW\/4vmPnLuzzxg8dYvvIyowZQ6I4OOXylw2XJeL2hdmU4ewxUErKSS92x3KLNCL9ma0TfB7VADUVDUYwUQsJoQ2mKcNtNp\/8nkKO9Q\/766J944bdPkqVj1NYhdVSIDuqxQaPkkRJJMYmVTAk1xVJGc4OkBvIIf+N2w+GiY3lcWPaVUiqlViQEiYoVwUQ4vTk+AXEwP+LCUy\/wzO\/\/zgt\/\/gdNdIy9EKngVLJWQgMsYDnkSklB8sBNMBM0JSS3kAxyhtyAt\/gHNl\/kYFGZzzv2DirzPtg\/hsMlLDpY9kLp4Vvf+A5HB0fsXNrj4PIeuRQShUSl1crIeiYpmLWV5bjCNEghtDbYDCkd6oFlw2rQdYYxpTs2tE3sXhnT0SL33HE6Zm1isRisklsmxKk4IYmCUzXTVwhR1BObm6fY29nFzWhSovGES2VrfQLHB0wznJkE124Wtk8bk4nw7MUd5kdHlNyxcd31\/OKnv+SZi8fM2sr29pTjLnj8iQNkbWMrNGVEDUsJb1pEDc8NnjKWGlSN3LSYJ971trdw8dIut95wltJVmmZE45mttTGH+wdMsjNrE9Ns7D1\/gTVZsDmBpD3JejYmPbfdOWbn4pyXL+4xHYFLz5m77uPwjz\/Db\/\/QJ2nWZvQV2skUTw2qjpiTPCFiCEPekRB8NuGmc7A1m7C7e0DfdUzHI3p3sAn7xx21KseLYFG3kFbJyWhTpVpl0VQ622DrdbAz\/ztpJDTe0185ZO0ND+AFY354BJZY7u8jcgDo4IViMOCDFwIplUsvVqRW6mIBtZDNkBJIBFYLicEbj1NmmpypO+tNYpwE18I4w3zR8Y43zXj+ilIv98xGMN15kVsffAt+5cLfWHYd6plaKt6M4NV\/CATwlFBVJIKogcYAQGtF+v7E4NfuGBdj56VnaXOLi7C+NuPUbAOPyuHhHpuzKb970vnnhREv7S545pUFoxw0uuT9\/fPI6Ztvj1oK\/XJJ7Y5JkykSQlku0NQM6aD2eG4BBs8NaA0UQeKqhx68uEYgVEwEV8EFlEo2QzXo+w6hsD111lvj8tFgcxuHu87DvwCrEznQnIJIIAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-container_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA dependency injection container with autowiring\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-container_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHlklEQVRIiX2XyY8kRxXGf2+JyKyqruplZnq8zoA3MAYsNmFkIYwlLwgBAsRikBAc4ADiwJ\/AnRsHBOIMJ8TFgAQCgS3ZEptYjbEweLwNlsczvVR3V1dmxOOQNW0EiFBGZkoZyxffFy\/el3LuNXdElIoQRK0QFXOnlkIQqAiuhqmS3Fkuj6m1QgREIICIIAxFRBARILhaImJV68mTqIiAimDumAhNM8IjhIig1IIECFBKQRgGVtUBqCjUSlKlX02AyKodJ+1FAARVeXVyufouRC2IGhGv9jOEpIbWgl\/tIChBJQI0BNFhMkJQdUDoS8UQFCFEMdUVG8NCkOHb6lrdDHdjuewQgYhhgSKKrvqaKm5GUsVDFGpZETwwQgQSgqrhppgIJoqbIlGptVJrGQZwH1ZfK6p2IpWKELUSBOsbG+xcvgJUCEEcohZUBQLMlGRG8quABFCBumJLQERXMhiKYmZkS4ybBqLn8OiIxp0mOdkTtVZK6elLAWHYL7UCcO3ZbY7350AdSItANa9AKaaDxNkUF01EdEgYSEVPNqmgZgO1llBRVAwVZ9JM2Bytc2W+i4YSJWg8oZ4hCiFC33cDQwLnz53jn888i0ggAaaCEEBCJFaSKckU15Tpg1XE2NVYAdWBHTVMjexOtoRiiCSanHjtmTUODuccdx1nr9lmeXTIfG8fEyG7UqNy9\/3v4eknnmSWG4IYIgtQHURRBRFIpmQ3PDQhaSUXQg0wUVQNFcXNcTWyZ1yEZE6SRNKGra11PvLZj7G1ucHPv\/cjnrvwHNaskXyIpun6Gnff+x7+\/IvH2GhHQCEiBjAqqICZYDqw5i44uUF6p9ZY6QugiBpqjojh5qgm3GxVE\/e879089KVP8NSv\/8LDX\/8uicJt115H1Mr+wRzPxqe\/+hV+\/f0fcsNsxrJ01OiJKIN0uoquNOyhnBRTcGkn1K4gtQ7nUABiiDhqiWSOqpHMaVNm7M7nvvhRHvjwPcyv7PPDbz5M1hGb45abb7mOg91L7B4uuPfLnyKpUC88z+uv3WZ+dMiiX1JqT6kdaCW5YSa4K8mFlAyX8QxZ9lAqAcMeQRFJqBjiiaxOmxLjlHjoM\/fxwIfvAeAPj\/6JRMN0bcrauGH\/8hHn3\/5m7v\/A3Xjb8PjXvs326XU0Onb3gr5PlBgAhVRUg5QddyElxbPgMppC7qGAhEIogoI4aMLUSebklLjzztfywY+\/9yQl7L0059TZM1x\/fpvzd9zIjW+9icnpGRHBcz9+hMkoU+oabdOTmwpSqdHR90uidqiBamBu5MbxJDjTdegLETKAiSG6DMc1oTiyOgA\/84X3nZzMAA9+\/j7+s0QELzzyG5YvX+LMa05xvJvpDnaYaYdYRSyotaP2xwg9aoK5knLGmwbX6ZRUGPIMioeSMLI4OYysRkZ5653nuP76rf8C8O+llsLTP\/kV+089TTtR2vUxZ26\/gX53wt5FQWWJ0IFkoiRE6hBhybGcsWaETzemlAKsGDIED6cVo0VpMZoq3PXOW\/4vmPnLuzzxg8dYvvIyowZQ6I4OOXylw2XJeL2hdmU4ewxUErKSS92x3KLNCL9ma0TfB7VADUVDUYwUQsJoQ2mKcNtNp\/8nkKO9Q\/766J944bdPkqVj1NYhdVSIDuqxQaPkkRJJMYmVTAk1xVJGc4OkBvIIf+N2w+GiY3lcWPaVUiqlViQEiYoVwUQ4vTk+AXEwP+LCUy\/wzO\/\/zgt\/\/gdNdIy9EKngVLJWQgMsYDnkSklB8sBNMBM0JSS3kAxyhtyAt\/gHNl\/kYFGZzzv2DirzPtg\/hsMlLDpY9kLp4Vvf+A5HB0fsXNrj4PIeuRQShUSl1crIeiYpmLWV5bjCNEghtDbYDCkd6oFlw2rQdYYxpTs2tE3sXhnT0SL33HE6Zm1isRisklsmxKk4IYmCUzXTVwhR1BObm6fY29nFzWhSovGES2VrfQLHB0wznJkE124Wtk8bk4nw7MUd5kdHlNyxcd31\/OKnv+SZi8fM2sr29pTjLnj8iQNkbWMrNGVEDUsJb1pEDc8NnjKWGlSN3LSYJ971trdw8dIut95wltJVmmZE45mttTGH+wdMsjNrE9Ns7D1\/gTVZsDmBpD3JejYmPbfdOWbn4pyXL+4xHYFLz5m77uPwjz\/Db\/\/QJ2nWZvQV2skUTw2qjpiTPCFiCEPekRB8NuGmc7A1m7C7e0DfdUzHI3p3sAn7xx21KseLYFG3kFbJyWhTpVpl0VQ622DrdbAz\/ztpJDTe0185ZO0ND+AFY354BJZY7u8jcgDo4IViMOCDFwIplUsvVqRW6mIBtZDNkBJIBFYLicEbj1NmmpypO+tNYpwE18I4w3zR8Y43zXj+ilIv98xGMN15kVsffAt+5cLfWHYd6plaKt6M4NV\/CATwlFBVJIKogcYAQGtF+v7E4NfuGBdj56VnaXOLi7C+NuPUbAOPyuHhHpuzKb970vnnhREv7S545pUFoxw0uuT9\/fPI6Ztvj1oK\/XJJ7Y5JkykSQlku0NQM6aD2eG4BBs8NaA0UQeKqhx68uEYgVEwEV8EFlEo2QzXo+w6hsD111lvj8tFgcxuHu87DvwCrEznQnIJIIAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-container_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA dependency injection container with autowiring\u003C\/p\u003E\n\u003Ch3\u003EInstallation\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs bash border\u0022\u003Ecomposer require avris\/container\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EUsage\u003C\/h3\u003E\n\u003Ch4\u003EBasics\u003C\/h4\u003E\n\u003Cp\u003EContainer resolves dependencies between defined services,\nin order to simplify the development process, avoid duplication of code,\nfacilitate interoperability and improve maintainability and testability.\nSee: \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_injection\u0022\u003EDependency Injection pattern\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$parameterProvider = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E SimpleParameterProvider([\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027ROOT_DIR\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-keyword\u0022\u003E__DIR__\u003C\/span\u003E]);\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ parameter provider is optional\u003C\/span\u003E\n\n$container = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Container($parameterProvider);\n\n$container-\u0026gt;set(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027number\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-number\u0022\u003E4\u003C\/span\u003E);\n$container-\u0026gt;set(Foo::class, \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Foo);\n$container-\u0026gt;setDefinition(Bar::class, [\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027arguments\u0027\u003C\/span\u003E =\u0026gt; [\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027$foo\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027@\u0027\u003C\/span\u003E . Foo::class,\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027$dir\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027%ROOT_DIR%\/bar\u0027\u003C\/span\u003E,\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027$number\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027@number\u0027\u003C\/span\u003E,\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027$float\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-number\u0022\u003E69.123\u003C\/span\u003E,\n    ],\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027public\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E,\n]);\n$container-\u0026gt;setDefinition(BarInterface::class, Bar::class); \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ alias\u003C\/span\u003E\n\n$container-\u0026gt;get(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027number\u0027\u003C\/span\u003E);              \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ 4\u003C\/span\u003E\n$container-\u0026gt;get(Foo::class);            \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ new Foo\u003C\/span\u003E\n$container-\u0026gt;get(BarInterface::class);   \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ new Bar(new Foo, __DIR__ . \u0027\/bar\u0027, 4, 69.123)\u003C\/span\u003E\n$container-\u0026gt;getParameter(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027ROOT_DIR\u0027\u003C\/span\u003E);   \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ __DIR__\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch4\u003EOptions\u003C\/h4\u003E\n\u003Cul\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Eclass\u003C\/code\u003E \u2013 the class of the service, will default to the service name if not given.\nIf the given class implements the \u003Ccode\u003EResolver\u003C\/code\u003E interface, it will be instantiated,\nand it\u2019s \u003Ccode\u003Eresolve\u003C\/code\u003E method executed to provide an actual value to be put in the container.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Earguments\u003C\/code\u003E \u2013 constructor arguments.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Ecalls\u003C\/code\u003E \u2013 method calls to be executed right after constructing the service (setter injection etc.)\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0027calls\u0027 =\u0026gt; [\n    [\u0027setLogger\u0027, [\u0027@logger\u0027]],\n    [\u0027registerListener\u0027, [\u0027@listenerA\u0027]],\n    [\u0027registerListener\u0027, [\u0027@listenerB\u0027]],\n],\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Etags\u003C\/code\u003E \u2013 an array of string that help group similar services together; tagged services can be injected with \u003Ccode\u003E#tagName\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$container-\u0026gt;setDefinition(HandlerA::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(HandlerB::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(HandlerC::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(Manager::class, [\u0027arguments\u0027 =\u0026gt; [\u0027$handlers\u0027 =\u0026gt; \u0027#handler\u0027]]);\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Efactory\u003C\/code\u003E -- determines if each \u003Ccode\u003Eget\u003C\/code\u003E should create a new service (\u003Ccode\u003Etrue\u003C\/code\u003E),\nor should one service be reused (\u003Ccode\u003Efalse\u003C\/code\u003E, default).\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Eresolve\u003C\/code\u003E \u2013 instead of using \u003Ccode\u003Eclass\u003C\/code\u003E + \u003Ccode\u003Earguments\u003C\/code\u003E to construct the service,\nyou can use \u003Ccode\u003Eresolve\u003C\/code\u003E to define how it should be created:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$container-\u0026gt;setDefinition(\u0027foo\u0027, [\u0027resolve\u0027 =\u0026gt; 4]); \/\/ 4\n$container-\u0026gt;setDefinition(\u0027language\u0027, [\u0027resolve\u0027 =\u0026gt; \u0027@Request.locale.language\u0027]); \/\/ $container-\u0026gt;get(\u0027Request\u0027)-\u0026gt;getLocale()-\u0026gt;getLanguage()\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Epublic\u003C\/code\u003E \u2013 determines if the service should be accessible directly with \u003Ccode\u003Eget\u003C\/code\u003E,\nor can it only be injected into other services.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch4\u003EContainerCompiler: autowiring and autoconfiguration\u003C\/h4\u003E\n\u003Cp\u003EUsually it\u2019s obvious, which service should be injected into another.\nFor instance when your service has a constructor argument \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface $cache\u003C\/code\u003E,\nand the container does have a service named \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E,\nthen explicitly writing \u003Ccode\u003E[\u0027arguments\u0027 =\u0026gt; [\u0027$cache\u0027 =\u0026gt; \u0027@Psr\\Cache\\CacheItemPoolInterface\u0027]\u003C\/code\u003E is redundant.\nYou can always specify the dependencies manually, then autowiring won\u0027t overwrite them.\u003C\/p\u003E\n\u003Cp\u003EAutowiring is not magic \u2013 it just follows simple rules to determine,\nwhich service should be injected into the constructor:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Eif the argument is a class which is defined in the container, use this service,\u003C\/li\u003E\n\u003Cli\u003Eif the argument is a class which is not defined in the container,\ntry to autowire that class and create a private service out of it,\u003C\/li\u003E\n\u003Cli\u003Eif the argument is an array and its name ends with \u003Ccode\u003Es\u003C\/code\u003E (e.g. \u003Ccode\u003Earray $helpers\u003C\/code\u003E),\ninject an array of services with a specific tag (\u003Ccode\u003E#helper\u003C\/code\u003E).\u003C\/li\u003E\n\u003Cli\u003Eif the argument is of type \u003Ccode\u003EBag\u003C\/code\u003E, inject the config value with its name\n(e.g. \u003Ccode\u003EBag $localisation\u003C\/code\u003E -\u0026gt; \u003Ccode\u003E@config.localisation\u003C\/code\u003E),\u003C\/li\u003E\n\u003Cli\u003Eif its name starts with \u003Ccode\u003Eenv\u003C\/code\u003E, inject a parameter:\n(e.g. \u003Ccode\u003Estring $envCacheDir\u003C\/code\u003E -\u0026gt; \u003Ccode\u003E%CACHE_DIR%\u003C\/code\u003E)\u003C\/li\u003E\n\u003Cli\u003Eif none of the above is true, but there is a default value, just use it,\u003C\/li\u003E\n\u003Cli\u003Eif none of the above is true, throw an exception \u2013 this argument should be defined explicitly.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EAutoconfiguration is another way to make your life simpler.\nFor instance, if you\u2019re using \u003Ca href=\u0022https:\/\/twig.symfony.com\/\u0022\u003ETwig\u003C\/a\u003E,\nyou might want all the classes in your code that extend \u003Ccode\u003ETwig\\Extension\\AbstractExtension\u003C\/code\u003E\nto be automatically registered as twig extension.\nAutoconfiguration lets you define what default config (tags, public etc.) should be added to them.\u003C\/p\u003E\n\u003Cp\u003ETo use autowiring and autoconfiguration, run the \u003Ccode\u003EContainerCompiler\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$container = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Container;\n\n$services = [\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027App\\\u0027 =\u0026gt; [\n        \u0027\u003C\/span\u003Edir\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027 =\u0026gt; \u0027\u003C\/span\u003E%MODULE_DIR%\/src\/\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027,\n        \u0027\u003C\/span\u003Eexclude\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027 =\u0026gt; [\u0027\u003C\/span\u003E\u003Cspan class=\u0022hljs-comment\u0022\u003E#^Entity\/#\u0027],\u003C\/span\u003E\n    ],\n\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027App\\Foo\u0027\u003C\/span\u003E =\u0026gt; [\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027arguments\u0027\u003C\/span\u003E =\u0026gt; [\n            \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027$bar\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-number\u0022\u003E5\u003C\/span\u003E,\n        ],\n    ],\n\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027App\\Bar\u0027\u003C\/span\u003E =\u0026gt; [\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027public\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E,\n    ],\n];\n\n$autoconfiguration = [\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027Twig\\Extension\\AbstractExtension\u0027\u003C\/span\u003E =\u0026gt; [\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027tags\u0027\u003C\/span\u003E =\u0026gt; [\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027twigExtension\u0027\u003C\/span\u003E],\n    ],\n];\n\n$definitions = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E ContainerCompiler(\n    $container,\n    $services,\n    $autoconfiguration\n))-\u0026gt;compile();\n\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/** \u003Cspan class=\u0022hljs-doctag\u0022\u003E@var\u003C\/span\u003E ServiceDefinition $definition *\/\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Eforeach\u003C\/span\u003E ($definitions \u003Cspan class=\u0022hljs-keyword\u0022\u003Eas\u003C\/span\u003E $name =\u0026gt; $definition) {\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (!$container-\u0026gt;has($name)) {\n        $container-\u0026gt;setDefinition($name, $definition);\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIn this example, the whole \u003Ccode\u003E%MODULE_DIR%\/src\/\u003C\/code\u003E except for (the \u003Ccode\u003E\/src\/Entity\u003C\/code\u003E dir) will be scanned for PHP files\nand all the found classes will be autowired as private services. If some of them are not used and not public,\nthey will be removed from the container.\u003C\/p\u003E\n\u003Cp\u003ECompiling the container has \u003Cstrong\u003Eno impact on performance\u003C\/strong\u003E on production environment,\nas long as you \u003Cstrong\u003Ecache the result of \u003Ccode\u003Ecompile()\u003C\/code\u003E\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Ch4\u003EServiceLocator\u003C\/h4\u003E\n\u003Cp\u003EService locator restricts access to services in the container only to a selected list of names:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$container = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Container();\n$container-\u0026gt;set(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027foo\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027abc\u0027\u003C\/span\u003E);\n$container-\u0026gt;set(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027bar\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027def\u0027\u003C\/span\u003E);\n$container-\u0026gt;set(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027secret\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027XYZ\u0027\u003C\/span\u003E);\n\n$locator = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E ServiceLocator($container, [\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027foo\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027bar\u0027\u003C\/span\u003E]);\n\n$locator-\u0026gt;get(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027foo\u0027\u003C\/span\u003E);     \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ \u0027abc\u0027\u003C\/span\u003E\n$locator-\u0026gt;get(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027bar\u0027\u003C\/span\u003E);     \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ \u0027def\u0027\u003C\/span\u003E\n$locator-\u0026gt;get(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027secret\u0027\u003C\/span\u003E);  \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ Exception\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EContainerAssistedBuilder\u003C\/h3\u003E\n\u003Cp\u003E\u003Ccode\u003EContainerAssistedBuilder\u003C\/code\u003E can be used to join together a couple of \u003Ccode\u003EContainerBuilderExtension\u003C\/code\u003Es\nwhich encapsulate a set of service definitions that form a library together.\nFor an example, see \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Localisator\u0022\u003EAvris Localisator\u003C\/a\u003E.\u003C\/p\u003E\n\u003Ch4\u003EMicrus\u003C\/h4\u003E\n\u003Cp\u003EThis container was originally built as a part of the \u003Ca href=\u0022https:\/\/micrus.avris.it\u0022\u003EMicrus framework\u003C\/a\u003E.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["autoconfiguration","autowiring","container","dependencies","dependency injection","library","php","programming"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avris-container_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-container_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-container_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA dependency injection container with autowiring\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-container_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-container_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA dependency injection container with autowiring\u003C\/p\u003E\n\u003Ch3\u003EInstallation\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-bash\u0022\u003Ecomposer require avris\/container\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EUsage\u003C\/h3\u003E\n\u003Ch4\u003EBasics\u003C\/h4\u003E\n\u003Cp\u003EContainer resolves dependencies between defined services,\nin order to simplify the development process, avoid duplication of code,\nfacilitate interoperability and improve maintainability and testability.\nSee: \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_injection\u0022\u003EDependency Injection pattern\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E$parameterProvider = new SimpleParameterProvider([\u0027ROOT_DIR\u0027 =\u0026gt; __DIR__]);\n\/\/ parameter provider is optional\n\n$container = new Container($parameterProvider);\n\n$container-\u0026gt;set(\u0027number\u0027, 4);\n$container-\u0026gt;set(Foo::class, new Foo);\n$container-\u0026gt;setDefinition(Bar::class, [\n    \u0027arguments\u0027 =\u0026gt; [\n        \u0027$foo\u0027 =\u0026gt; \u0027@\u0027 . Foo::class,\n        \u0027$dir\u0027 =\u0026gt; \u0027%ROOT_DIR%\/bar\u0027,\n        \u0027$number\u0027 =\u0026gt; \u0027@number\u0027,\n        \u0027$float\u0027 =\u0026gt; 69.123,\n    ],\n    \u0027public\u0027 =\u0026gt; true,\n]);\n$container-\u0026gt;setDefinition(BarInterface::class, Bar::class); \/\/ alias\n\n$container-\u0026gt;get(\u0027number\u0027);              \/\/ 4\n$container-\u0026gt;get(Foo::class);            \/\/ new Foo\n$container-\u0026gt;get(BarInterface::class);   \/\/ new Bar(new Foo, __DIR__ . \u0027\/bar\u0027, 4, 69.123)\n$container-\u0026gt;getParameter(\u0027ROOT_DIR\u0027);   \/\/ __DIR__\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch4\u003EOptions\u003C\/h4\u003E\n\u003Cul\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Eclass\u003C\/code\u003E \u2013 the class of the service, will default to the service name if not given.\nIf the given class implements the \u003Ccode\u003EResolver\u003C\/code\u003E interface, it will be instantiated,\nand it\u2019s \u003Ccode\u003Eresolve\u003C\/code\u003E method executed to provide an actual value to be put in the container.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Earguments\u003C\/code\u003E \u2013 constructor arguments.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Ecalls\u003C\/code\u003E \u2013 method calls to be executed right after constructing the service (setter injection etc.)\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0027calls\u0027 =\u0026gt; [\n    [\u0027setLogger\u0027, [\u0027@logger\u0027]],\n    [\u0027registerListener\u0027, [\u0027@listenerA\u0027]],\n    [\u0027registerListener\u0027, [\u0027@listenerB\u0027]],\n],\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Etags\u003C\/code\u003E \u2013 an array of string that help group similar services together; tagged services can be injected with \u003Ccode\u003E#tagName\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$container-\u0026gt;setDefinition(HandlerA::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(HandlerB::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(HandlerC::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(Manager::class, [\u0027arguments\u0027 =\u0026gt; [\u0027$handlers\u0027 =\u0026gt; \u0027#handler\u0027]]);\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Efactory\u003C\/code\u003E -- determines if each \u003Ccode\u003Eget\u003C\/code\u003E should create a new service (\u003Ccode\u003Etrue\u003C\/code\u003E),\nor should one service be reused (\u003Ccode\u003Efalse\u003C\/code\u003E, default).\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Eresolve\u003C\/code\u003E \u2013 instead of using \u003Ccode\u003Eclass\u003C\/code\u003E + \u003Ccode\u003Earguments\u003C\/code\u003E to construct the service,\nyou can use \u003Ccode\u003Eresolve\u003C\/code\u003E to define how it should be created:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$container-\u0026gt;setDefinition(\u0027foo\u0027, [\u0027resolve\u0027 =\u0026gt; 4]); \/\/ 4\n$container-\u0026gt;setDefinition(\u0027language\u0027, [\u0027resolve\u0027 =\u0026gt; \u0027@Request.locale.language\u0027]); \/\/ $container-\u0026gt;get(\u0027Request\u0027)-\u0026gt;getLocale()-\u0026gt;getLanguage()\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Epublic\u003C\/code\u003E \u2013 determines if the service should be accessible directly with \u003Ccode\u003Eget\u003C\/code\u003E,\nor can it only be injected into other services.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch4\u003EContainerCompiler: autowiring and autoconfiguration\u003C\/h4\u003E\n\u003Cp\u003EUsually it\u2019s obvious, which service should be injected into another.\nFor instance when your service has a constructor argument \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface $cache\u003C\/code\u003E,\nand the container does have a service named \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E,\nthen explicitly writing \u003Ccode\u003E[\u0027arguments\u0027 =\u0026gt; [\u0027$cache\u0027 =\u0026gt; \u0027@Psr\\Cache\\CacheItemPoolInterface\u0027]\u003C\/code\u003E is redundant.\nYou can always specify the dependencies manually, then autowiring won\u0027t overwrite them.\u003C\/p\u003E\n\u003Cp\u003EAutowiring is not magic \u2013 it just follows simple rules to determine,\nwhich service should be injected into the constructor:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Eif the argument is a class which is defined in the container, use this service,\u003C\/li\u003E\n\u003Cli\u003Eif the argument is a class which is not defined in the container,\ntry to autowire that class and create a private service out of it,\u003C\/li\u003E\n\u003Cli\u003Eif the argument is an array and its name ends with \u003Ccode\u003Es\u003C\/code\u003E (e.g. \u003Ccode\u003Earray $helpers\u003C\/code\u003E),\ninject an array of services with a specific tag (\u003Ccode\u003E#helper\u003C\/code\u003E).\u003C\/li\u003E\n\u003Cli\u003Eif the argument is of type \u003Ccode\u003EBag\u003C\/code\u003E, inject the config value with its name\n(e.g. \u003Ccode\u003EBag $localisation\u003C\/code\u003E -\u0026gt; \u003Ccode\u003E@config.localisation\u003C\/code\u003E),\u003C\/li\u003E\n\u003Cli\u003Eif its name starts with \u003Ccode\u003Eenv\u003C\/code\u003E, inject a parameter:\n(e.g. \u003Ccode\u003Estring $envCacheDir\u003C\/code\u003E -\u0026gt; \u003Ccode\u003E%CACHE_DIR%\u003C\/code\u003E)\u003C\/li\u003E\n\u003Cli\u003Eif none of the above is true, but there is a default value, just use it,\u003C\/li\u003E\n\u003Cli\u003Eif none of the above is true, throw an exception \u2013 this argument should be defined explicitly.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EAutoconfiguration is another way to make your life simpler.\nFor instance, if you\u2019re using \u003Ca href=\u0022https:\/\/twig.symfony.com\/\u0022\u003ETwig\u003C\/a\u003E,\nyou might want all the classes in your code that extend \u003Ccode\u003ETwig\\Extension\\AbstractExtension\u003C\/code\u003E\nto be automatically registered as twig extension.\nAutoconfiguration lets you define what default config (tags, public etc.) should be added to them.\u003C\/p\u003E\n\u003Cp\u003ETo use autowiring and autoconfiguration, run the \u003Ccode\u003EContainerCompiler\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E$container = new Container;\n\n$services = [\n    \u0027App\\\u0027 =\u0026gt; [\n        \u0027dir\u0027 =\u0026gt; \u0027%MODULE_DIR%\/src\/\u0027,\n        \u0027exclude\u0027 =\u0026gt; [\u0027#^Entity\/#\u0027],\n    ],\n\n    \u0027App\\Foo\u0027 =\u0026gt; [\n        \u0027arguments\u0027 =\u0026gt; [\n            \u0027$bar\u0027 =\u0026gt; 5,\n        ],\n    ],\n\n    \u0027App\\Bar\u0027 =\u0026gt; [\n        \u0027public\u0027 =\u0026gt; true,\n    ],\n];\n\n$autoconfiguration = [\n    \u0027Twig\\Extension\\AbstractExtension\u0027 =\u0026gt; [\n        \u0027tags\u0027 =\u0026gt; [\u0027twigExtension\u0027],\n    ],\n];\n\n$definitions = new ContainerCompiler(\n    $container,\n    $services,\n    $autoconfiguration\n))-\u0026gt;compile();\n\n\/** @var ServiceDefinition $definition *\/\nforeach ($definitions as $name =\u0026gt; $definition) {\n    if (!$container-\u0026gt;has($name)) {\n        $container-\u0026gt;setDefinition($name, $definition);\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIn this example, the whole \u003Ccode\u003E%MODULE_DIR%\/src\/\u003C\/code\u003E except for (the \u003Ccode\u003E\/src\/Entity\u003C\/code\u003E dir) will be scanned for PHP files\nand all the found classes will be autowired as private services. If some of them are not used and not public,\nthey will be removed from the container.\u003C\/p\u003E\n\u003Cp\u003ECompiling the container has \u003Cstrong\u003Eno impact on performance\u003C\/strong\u003E on production environment,\nas long as you \u003Cstrong\u003Ecache the result of \u003Ccode\u003Ecompile()\u003C\/code\u003E\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Ch4\u003EServiceLocator\u003C\/h4\u003E\n\u003Cp\u003EService locator restricts access to services in the container only to a selected list of names:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E$container = new Container();\n$container-\u0026gt;set(\u0027foo\u0027, \u0027abc\u0027);\n$container-\u0026gt;set(\u0027bar\u0027, \u0027def\u0027);\n$container-\u0026gt;set(\u0027secret\u0027, \u0027XYZ\u0027);\n\n$locator = new ServiceLocator($container, [\u0027foo\u0027, \u0027bar\u0027]);\n\n$locator-\u0026gt;get(\u0027foo\u0027);     \/\/ \u0027abc\u0027\n$locator-\u0026gt;get(\u0027bar\u0027);     \/\/ \u0027def\u0027\n$locator-\u0026gt;get(\u0027secret\u0027);  \/\/ Exception\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EContainerAssistedBuilder\u003C\/h3\u003E\n\u003Cp\u003E\u003Ccode\u003EContainerAssistedBuilder\u003C\/code\u003E can be used to join together a couple of \u003Ccode\u003EContainerBuilderExtension\u003C\/code\u003Es\nwhich encapsulate a set of service definitions that form a library together.\nFor an example, see \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Localisator\u0022\u003EAvris Localisator\u003C\/a\u003E.\u003C\/p\u003E\n\u003Ch4\u003EMicrus\u003C\/h4\u003E\n\u003Cp\u003EThis container was originally built as a part of the \u003Ca href=\u0022https:\/\/micrus.avris.it\u0022\u003EMicrus framework\u003C\/a\u003E.\u003C\/p\u003E","words":868,"readTime":4,"lang":"en"}}},"blog\/technology\/the-non-magic-of-autowiring":{"key":"blog\/technology\/the-non-magic-of-autowiring","type":"article","published":true,"meta":{"createdAt":"2017-09-01T22:58:27+02:00","publishedAt":"2017-09-05T20:00:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"the-non-magic-of-autowiring"},"content":{"en":{"slug":"the-non-magic-of-autowiring","title":"The non-magic of autowiring","intro":"\u003Cp\u003EWhen I first heard the term \u201cAutowiring\u201d, I thought it sounds exciting. But when I learned more or less what is it about, I got pretty sceptical of the idea. Too much \u003Cem\u003Emagic\u003C\/em\u003E, too much implied information... However, when I finally used it for the first time... Gosh I wish I could never define services manually again!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cp\u003EWhen I first heard the term \u201cAutowiring\u201d, I thought it sounds exciting. But when I learned more or less what is it about, I got pretty sceptical of the idea. Too much \u003Cem\u003Emagic\u003C\/em\u003E, too much implied information... However, when I finally used it for the first time... Gosh I wish I could never define services manually again!\u003C\/p\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_injection\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Dependency Injection Container\u003C\/a\u003E is definitely my favourite design pattern \u2013 so elegant, simple and flexible!\u003C\/p\u003E\n\u003Cp\u003EIt comes with one inconvenience though: you basically need to code the same thing twice. If your service requires some dependency, it cannot just \u003Cem\u003Etake\u003C\/em\u003E it or just \u003Cem\u003Ecreate\u003C\/em\u003E it. Instead, it should \u003Cem\u003Eexpect\u003C\/em\u003E its dependencies, while the container \u003Cem\u003Eprovides\u003C\/em\u003E them from the outside. When you want to add a new dependency, you need to both add it in the class and in some external service definition. This doesn\u2019t look like much effort, but when you\u2019re intensively playing around with your services, it all adds up. I didn\u2019t even realise, how annoying that process is, until I no longer had to follow it.\u003C\/p\u003E\n\u003Cp\u003EWhen I started a fresh project recently, using the latest version of \u003Ca href=\u0022https:\/\/symfony.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony\u003C\/a\u003E after over a year of working almost exclusively with \u003Ca href=\u0022https:\/\/phalconphp.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Phalcon\u003C\/a\u003E and \u003Ca href=\u0022https:\/\/micrus.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus\u003C\/a\u003E, I had already forgotten about those two new features of Symfony: autowiring and autoconfiguration. I remembered by accident.\u003C\/p\u003E\n\u003Cp\u003EI needed a \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/templating\/twig_extension.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Twig extension\u003C\/a\u003E, so I quickly created one: simple class, extending \u003Ccode\u003E\\Twig_Extension\u003C\/code\u003E, expecting some other service in its constructor, providing some filter in \u003Ccode\u003EgetFilters()\u003C\/code\u003E. I refreshed the tab in the browser and immediately realised I\u2019m gonna see an exception \u2013 in the end, I forgot to tag this class as a \u003Ccode\u003Etwig.extension\u003C\/code\u003E, I forgot to provide the dependencies, it has to fail! But no, \u003Cstrong\u003Eit just worked\u003C\/strong\u003E!\u003C\/p\u003E\n\u003Cp\u003EThe idea behind \u003Cstrong\u003Eautowiring\u003C\/strong\u003E is pretty simple: if a service requires an instance of \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, and your DI container happens to have a service called \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, which is of type \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, then it\u2019s pretty safe to assume, that\u2019s the one you want.\u003C\/p\u003E\n\u003Cp\u003EIdeally, you should depend on abstractions, interfaces. For instance when you have multiple cache adapters, all implementing \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E, your services should depend on \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E, not on any specific implementation. This way you can always switch for instance from \u003Ccode\u003EFilesystemAdapter\u003C\/code\u003E to \u003Ccode\u003ERedisAdapter\u003C\/code\u003E without any trouble.\u003C\/p\u003E\n\u003Cp\u003EBut if you have more than one implementation of an interface, how does the autowired container know, which one to use? You tell it, by creating an alias:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs yaml border\u0022\u003E\u003Cspan class=\u0022hljs-string\u0022\u003EPsr\\Cache\\CacheItemPoolInterface:\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027@Symfony\\Component\\Cache\\Adapter\u0027\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd what about the scalars and arrays? If my service expects \u003Ccode\u003Estring $baseUrl\u003C\/code\u003E, how does the container know \u003Cem\u003Ethat\u003C\/em\u003E? Of course it doesn\u2019t, I need to specify it myself:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs yaml border\u0022\u003E\u003Cspan class=\u0022hljs-string\u0022\u003EAppBundle\\Service\\ExternalSerive:\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-attr\u0022\u003Earguments:\u003C\/span\u003E\n        \u003Cspan class=\u0022hljs-string\u0022\u003E$baseUsr:\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027https:\/\/api.external.org\/\u0027\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EYou can do the same thing for services as well. For instance when all of them should use some generic logger, except for one, which requires something more specific, just overwrite its \u003Ccode\u003Earguments.$logger\u003C\/code\u003E with the other one.\u003C\/p\u003E\n\u003Cp\u003EPretty simple, right? The idea behind \u003Cstrong\u003Eautoconfiguration\u003C\/strong\u003E is even simpler. You (or libraries, like Twig) can define that all the services which are an instance of \u003Ccode\u003EFoo\u003C\/code\u003E should automatically receive some specific config, for instance a tag. That\u2019s why I didn\u2019t have to register my Twig extension.\u003C\/p\u003E\n\u003Cp\u003EMain concern one might have about autowiring is that, although pretty simple, it sure is time-consuming. Should I sacrifice my website\u2019s performance for the developer\u2019s convenience? Of course not! Symfony\u2019s container is compiled, so autowiring has absolutely no overhead on production!\u003C\/p\u003E\n\u003Cp\u003EAlso, Symfony Container has a concept of public and private services. Public ones you can just fetch from the container wherever you wish. Private ones can only be injected into other services \u2013 if they aren\u2019t used, they get removed from the container completely.\u003C\/p\u003E\n\u003Cp\u003EAutowiring is amazing. Simple, but effective. It makes the development faster, especially in the early phase. It prevents you from repeating yourself and maintaining a lengthy \u003Ccode\u003Eservices.yml\u003C\/code\u003E file full of information noise. And, although magical, it\u2019s not magic!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["autoconfiguration","autowiring","config","container","dependency injection","php","service","symfony"],"hasMore":true,"image":null,"introLite":"\u003Cp\u003EWhen I first heard the term \u201cAutowiring\u201d, I thought it sounds exciting. But when I learned more or less what is it about, I got pretty sceptical of the idea. Too much \u003Cem\u003Emagic\u003C\/em\u003E, too much implied information... However, when I finally used it for the first time... Gosh I wish I could never define services manually again!\u003C\/p\u003E","contentLite":"\u003Cp\u003EWhen I first heard the term \u201cAutowiring\u201d, I thought it sounds exciting. But when I learned more or less what is it about, I got pretty sceptical of the idea. Too much \u003Cem\u003Emagic\u003C\/em\u003E, too much implied information... However, when I finally used it for the first time... Gosh I wish I could never define services manually again!\u003C\/p\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_injection\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Dependency Injection Container\u003C\/a\u003E is definitely my favourite design pattern \u2013 so elegant, simple and flexible!\u003C\/p\u003E\n\u003Cp\u003EIt comes with one inconvenience though: you basically need to code the same thing twice. If your service requires some dependency, it cannot just \u003Cem\u003Etake\u003C\/em\u003E it or just \u003Cem\u003Ecreate\u003C\/em\u003E it. Instead, it should \u003Cem\u003Eexpect\u003C\/em\u003E its dependencies, while the container \u003Cem\u003Eprovides\u003C\/em\u003E them from the outside. When you want to add a new dependency, you need to both add it in the class and in some external service definition. This doesn\u2019t look like much effort, but when you\u2019re intensively playing around with your services, it all adds up. I didn\u2019t even realise, how annoying that process is, until I no longer had to follow it.\u003C\/p\u003E\n\u003Cp\u003EWhen I started a fresh project recently, using the latest version of \u003Ca href=\u0022https:\/\/symfony.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony\u003C\/a\u003E after over a year of working almost exclusively with \u003Ca href=\u0022https:\/\/phalconphp.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Phalcon\u003C\/a\u003E and \u003Ca href=\u0022https:\/\/micrus.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Micrus\u003C\/a\u003E, I had already forgotten about those two new features of Symfony: autowiring and autoconfiguration. I remembered by accident.\u003C\/p\u003E\n\u003Cp\u003EI needed a \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/templating\/twig_extension.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Twig extension\u003C\/a\u003E, so I quickly created one: simple class, extending \u003Ccode\u003E\\Twig_Extension\u003C\/code\u003E, expecting some other service in its constructor, providing some filter in \u003Ccode\u003EgetFilters()\u003C\/code\u003E. I refreshed the tab in the browser and immediately realised I\u2019m gonna see an exception \u2013 in the end, I forgot to tag this class as a \u003Ccode\u003Etwig.extension\u003C\/code\u003E, I forgot to provide the dependencies, it has to fail! But no, \u003Cstrong\u003Eit just worked\u003C\/strong\u003E!\u003C\/p\u003E\n\u003Cp\u003EThe idea behind \u003Cstrong\u003Eautowiring\u003C\/strong\u003E is pretty simple: if a service requires an instance of \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, and your DI container happens to have a service called \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, which is of type \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, then it\u2019s pretty safe to assume, that\u2019s the one you want.\u003C\/p\u003E\n\u003Cp\u003EIdeally, you should depend on abstractions, interfaces. For instance when you have multiple cache adapters, all implementing \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E, your services should depend on \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E, not on any specific implementation. This way you can always switch for instance from \u003Ccode\u003EFilesystemAdapter\u003C\/code\u003E to \u003Ccode\u003ERedisAdapter\u003C\/code\u003E without any trouble.\u003C\/p\u003E\n\u003Cp\u003EBut if you have more than one implementation of an interface, how does the autowired container know, which one to use? You tell it, by creating an alias:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-yaml\u0022\u003EPsr\\Cache\\CacheItemPoolInterface: \u0027@Symfony\\Component\\Cache\\Adapter\u0027\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd what about the scalars and arrays? If my service expects \u003Ccode\u003Estring $baseUrl\u003C\/code\u003E, how does the container know \u003Cem\u003Ethat\u003C\/em\u003E? Of course it doesn\u2019t, I need to specify it myself:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-yaml\u0022\u003EAppBundle\\Service\\ExternalSerive:\n    arguments:\n        $baseUsr: \u0027https:\/\/api.external.org\/\u0027\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EYou can do the same thing for services as well. For instance when all of them should use some generic logger, except for one, which requires something more specific, just overwrite its \u003Ccode\u003Earguments.$logger\u003C\/code\u003E with the other one.\u003C\/p\u003E\n\u003Cp\u003EPretty simple, right? The idea behind \u003Cstrong\u003Eautoconfiguration\u003C\/strong\u003E is even simpler. You (or libraries, like Twig) can define that all the services which are an instance of \u003Ccode\u003EFoo\u003C\/code\u003E should automatically receive some specific config, for instance a tag. That\u2019s why I didn\u2019t have to register my Twig extension.\u003C\/p\u003E\n\u003Cp\u003EMain concern one might have about autowiring is that, although pretty simple, it sure is time-consuming. Should I sacrifice my website\u2019s performance for the developer\u2019s convenience? Of course not! Symfony\u2019s container is compiled, so autowiring has absolutely no overhead on production!\u003C\/p\u003E\n\u003Cp\u003EAlso, Symfony Container has a concept of public and private services. Public ones you can just fetch from the container wherever you wish. Private ones can only be injected into other services \u2013 if they aren\u2019t used, they get removed from the container completely.\u003C\/p\u003E\n\u003Cp\u003EAutowiring is amazing. Simple, but effective. It makes the development faster, especially in the early phase. It prevents you from repeating yourself and maintaining a lengthy \u003Ccode\u003Eservices.yml\u003C\/code\u003E file full of information noise. And, although magical, it\u2019s not magic!\u003C\/p\u003E","words":680,"readTime":3,"lang":"en"}}}}}