Dependency Injection in Magento 2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello guys in this video we will learn about the dependency injection dependency injection is a very important part in magento 2 and how to understand it how to master it is very crucial thing in order to become a competent magento developer so this is the initial setup i've done for the new module i've created and this is how it looks like so what i've done is i've created the dependency example module i have created the module skeleton by module xml file and a registration php file you can check my how to create a module in magento2 if you want to and this is the first bit of this module the second bit is the controller i've created so the controller basically it just a routes and has the configuration and also we have a controller called index and in the index we just return the page object and we set dependency injection as a title in the page and in the configuration we have the route id as dependency and the front name as dependency as well so you can see here is a dependency and then render the page uh you can also check my controllers in magento 2 video if you want to uh how we did to create this and also the last bit is we created a block the block has just say just inheritance or template and has a constructor called but it doesn't have anything yet but we will uh in a bit and then we created the layout file which is dependency index index and has the what the block we created and then assign it to a template file the templates is just this one and has dependency examples as a h2 tag you can also have a look at my video blog in magento 2 to know more about how to create blocks in in magento 2. so this is it and now let's start with the dependency check injection the first bit we will handle is the injecting the injectable classes so first of all let's have a class called let's have a model folder and then it has this is the model and then i will have a class called injectable it's just given a name as a reference to the idea of injectables so i will just make it injectable and it's a class now we just have a declare type and then name space it has training dependency example dependency example model class injectable and this is the class i want to use as in inject it into a another class so before we use this class i will need to create another class and this will be main class that i use so if i go and create a class called main and then in the main training and then see example model class name so this is the class main i will create now i will have a public method called get id and we'll return a string and then we'll return just class name now this class main will be used i will inject it into the block now to inject a class into a constructor i will inject it inside here main main and then give it the comma now you cannot inject the class after the array data because this is optional the optional arguments are always comes in the last and then the ones required comes first so you cannot bring this main if you create it if you want to inject it you cannot say something like this this will give you an error because this is an optional the optional will come last and then the required will comes first before the optional this is required we know because it has no default value anything with the default value is optional anything without default value is required so this has a default value as an empty array then it's an optional this one has no optional value this one has no option of value and then you would see these are required and this is a optional now what i'm going to do here is i just returned the main public function get name simple get in main and then return this mix we don't have this main yet so let's initialize the main so the class main is initialized and we're good to go now domain has a method called get id and this is the id now if i go to the template the only thing i can do here is if i go p tag and then class name is id is block get main get id now if i refresh nothing because i need let's learn page cache cache flash or disable page let's clear full page class magento magento now we clear cache refresh and then we can see there is a class main id is class main so this is the first example of having an injectable classes this class is being injected so you just specify it here you don't need to worry about initializing and injecting the class magento has an auto injection automatic injection in the constructor so the constructor automatic injection happens on the on the time when you run the page the application and magento figure out oh there is a main class and need to be injected in this constructor so i will create it and inject it once you inject it then you can use it so this is a first example of injectable class but i will provide more readable examples on how you inject classes into constructors now i will use the class main as the main class i use and then i will make all the examples inside this class so since i have the class main injected in the example i can inject whatever class i want into this main class and then i can use and i can output the data in the template here so this is the first example we have done and we injected the class main and we got the id of it now let's go back to the main class i will have a constructor and then in the constructor i will have an optional argument and i will see how i can use it now let's go and try that so i will create array data equals this now if i do this it will nothing happen now if i can refresh again it's just nothing happen because there's no use of the data now i want this to comes from the data this data class main i want it to come from this data and not from a hard coding to do this you will need to go to the etc and then create a di dot xml file and then you create the dependency injection file config configuration file now you will need to do is right type and type you will specify the class you want to specify arguments for each constructor now this is the main class i'm looking for i will put here the main the class name and then i will add the arguments in the arguments i will have data the data will be an array exercise array and then inside the array inside this argument i will have items the first item i will have his id the id is a string or i will have hsi type string and then i'll give a value now this class main will be injected automatically into array data now to call it and use it make use of it you go to the class name you are just have initialized this data initialize and then you will say this data id remember this id this key matches whatever you set in the dixml file so the id will become will have the value of class main so this is the data now if i flush cache and then refresh so you see nothing changed now the only thing change changes is this piece of data class main comes from whatever you added in the configuration file and it's not hard coded in the class now if you go to the main you get the id from the data you don't have specifically or explicitly added this id to the data it's not in here in in the class but you have done it from the configuration and this is the first example of how to make a configuration for optional uh argument and is as array and you add to it as id and then class main so this is the first example of doing it now let's go to the injectable in the injectable i will create a function called id as well it id and then we'll return a string now we'll return class injectable so this will be class injectable the id of this class to do this i will add this injectable and the class main so i will say injectable injectable and then initialize it as injectable and then here i will say popular function get injectable returns injectable return this in general i don't need this i'll return an injectable i'll just fix it to display the data here to display in the html file we will create another p tag then class injectable id is block main get injectable get id now this id should come from this injectable and then work within this piece of data by refresh you see class injectable id is class injectable now this is an injectable because you inject it here and then you get the object the injectable is always one object so if you use this injectable class in another class or if you use it in multiple places but they are all invoked within one page so if you refresh and then there are three times you have injected so you have injected the injectable class in three areas or four areas magento will give you one copy think of this injectable class as a singleton every time you inject it you will get exactly the one created only once it's not going to be recreated again when you use it again in a different area or a different class this will be always one instance this will be only one object lives in the memory and whenever you use it whenever you call for it magento will give it to you this is not going to be two objects when you use it in two areas or three areas or four areas it's not going to be multiple objects it's only one object lives in the memory whenever you call for it you will get it this is the injectable class and this is how you get it in the application no matter how many times you call for it you will get the one object the one stored in the memory by magento so the object manager will give you the object exactly the same object you are injected in the first place or second place or third place so this is the injectable example and i think i have the injectable explanation already here so i think this is it for the injectable and next i will go to the non-injectable classes non-injectable classes will be as follows so if i create a class called non-injectable non-injectable and then i will create the class training and then for example model class non-injectable look function get id and this is the class non-injectable it's exactly the same as interval they don't have any differences but the thing is if i go to the injectable here if i go in injectable but i don't want it to be non-injectable i don't want it to be injectable i want it to be newable so it's like you are creating a new object every time you call for it so the thing you append to it factory this factory will tell magento to create a factory and every time you say non-injectable battery will get you a new instance a new object and opposite to the injectable class injectable class will always give you the same object this non-injectable class will give you a new object so let's have a factory here and then let's initialize it initialize now let's get like function getting an injectable return non-injectable then return this non-injectable battery create now let's have a look at the generated folder you go to generated code you will see there is a training and in the training there is only controller and then index index interception now if you refresh the page class interval you will see there is none injectable packaging created in the generate folder what does this do we'll get created the class none injectable factory and then in the create will get the object manager to create rather than get so just create this instance the instance is this which is the one class we created he will create it and then there is a data argument if there is any so this is a constructor argument will be like a constructor argument we will come to this next so we will create this class for us and then every time you call for this you will get a new object and opposite to injectable injectable will give you the one object created and stored in the memory but the non-injectable class will always get you a new object and you insist of the object so now if we go to the template and then we have just copy this and then paste it class non-injectable id is get non-injectable id now if we refresh you'll get class non-injectable id glass non-injectable so this is the difference between injectable classes and non-injectable classes injectable classes will give you the same instance every time you call for it non-injectable classes you will call it by factory you append the factory to it and then it will give you a new instance every time you call for it this is for injectable and non-injectable now you also will have interfaces to be injected here so it's very difficult to have in interface and you have to explicitly define what implementer for that interface to be injected in the class so let's have a look and create one for the injectable so i will create an interface called injectable interface and this injectable interface in space and this injectable interface will be interface injectable interface and here we can say public function get id and the string turns a string or this injectable interface will get this id and the injectable class will implement the immense injectable interface and this interface is injected by sorry this get id is implemented by the injectable interface now if we copy this or we just don't copy we go to the main the injectable we will say injectable interface now if we refresh you will get an error cannot instantiate interface and magento doesn't know what to give you because you injected an interface and magento doesn't know what object requires to give you to instruct magento to tell magento when i ask for injectable interface i want an implementer the implementer will be the injectable class this class because this implements the injectable interface but magento still doesn't have a way of understanding how to get you the injectable because you have this interface in the constructor and you are expected injectable to be given back magento knows this injectable maybe implements injectable interface but it doesn't look for that interfaces can be implemented by many many implementers by many many classes so it doesn't know which class to give you this just happens to be implemented by one class now we need to give an instruction to magento to say hey magento whenever i ask for this injectable interface i want you to give me the injectable class to do this you will have to do it from the di configuration file now i will make this is first so the thing we will denote we will use is the preference for which interface or for which object instruct magento what you want to give me and then i give you back so the instruction is for i want the interface for the interface injectable interface if i ask for the injectable interface i want the injectable class so i will go to the class and then i copy and then text here and this will tells magento when i ask for injectable interface i want you to give me the injectable class now let's refresh the flush cache and refresh and here we go we got the injectable class and this is the id so this is how you specify a implementer for interface by using the di xml file you can say i want for this interface to bring me or to give me this class and this is now how imagine to understand when you give me this interface i magento will know from the di configuration file magento will know that is injectable class will be returned will be applied for the same thing when you use an injectable factory let's do this let me have a interface called non-injectable interface interface and injectable interface and we'll have the get id method which is a string now i will have non-injectable for implementing an injectable interface and will have this now in the main you can see there is none injectable factory but instead i will call it by non-injectable interface fact none injectable interface factory is exactly as you say in an injectable factory but you can use it with the internet injectable interface factory this will be applied the same so i will have this and copy it i will configure it the same here so i will have reference and then it will be for the interface non-injectable interface and then it will be will return me back in an injectable class so this is how magento would understand it now you can see there is injectable here i want in an injectable this is why we got an error so i will say none here and then i will say none here now i flush cache and refresh now we have a type error that will create an object none injectable must be an instance of training that's i think we need layer model on the generated we just delete it and their refresh will be the same type of third model name tidy so if we go to the main what we would see here an injectable space factory so this will be the type and now we get we get it fixed this was because the protected non-injectable factory instead of non-injectable interface factory now we have done this we would know you can create factories out of the classes and out of the interfaces as well when you append it to the interface you're really you're really asking for the for the uh implementer because if you look in me here none injectable interface factory will have a look at the implementer so this is the interface and when you ask for the interface you will try to create an instance of the interface when you have defined in the di configuration when i ask for the interface give me the class i will always give you the class so you call for the interface but you actually it's like you have a an array the key is this name and the value is this object so this is how you create the interfaces you map them against their classes and then you can call the interfaces and then you can render whatever output from those classes to the to the page or use them in the logic whatever the use case now what is the benefit of having those interfaces the interfaces tend to be a a public apis that hide the implementation now if i um come after you or if you create me this interface i can just use the interface and i don't need to worry about the implementation the implementation is your concern is your cons is your responsibility to make this works without breaking so every time i come i use the interface as a third-party developer or if you create a piece of functionality even locally if you give it an interface the interface will be used you don't want other developers to go to the implementers which is the class then you see what the what happened what is happening in here they want to use this get id will give me an id then i just call it and that's it i don't need to go through and search what happens here so it's a way of hiding the implementation by using the interfaces so this is the main benefit of the interfaces and also they don't break you can always get the id you don't need to worry about the implementation as as we said now we have done those the injectable are non-injectable now let's have a look how we handle the abstract classes so let's try to create a class called abstract youtube and then in space training dependency example model abstract class abstract youtube this abstract util will have a popular abstract function name string now it has a string now let's go to the main and then i will have a struct util youtube and then initialize it and then say public function get you to abstract youtube within this youtube now if i go to the page and refresh you will get an abstract util they cannot be instantiated and cannot be used so the rsas cannot instantiate abstract class training dependency example model abstract youtube so how we tell magento to use a concrete class that is extending an abstract class let's go ahead and try to figure this out so in the model i will create a class called youtube and in space training dependency example model class youtube extends abstract youtube and it has a method to implement because we have an abstract method get named and now what we going to return is class youtube now we have the class youtube we want this to be used whenever we ask for the abstract youtube in the main we ask for the where it is we ask for the abstract tutor but we want the youtube concrete class to be injected instead so to do this in order to let magento knows that when i ask for the abstract util i want the youtube class i will have two different methods one of the methods is to use preferences so i can have preference and then for the abstract youtube i will have this abstract youtube when i ask for abstract youtube give me the youtube class give me the youtube class so this way i flush cache and then i go to the dependency injection to the sorry the template and then i will have class util id is get you to get name because we have get name method here will be name now if we refresh now you can see class name is youtube class youtube but this is not the preferred way this is not the preferences are not made for the abstract classes classes abstract class can be extended by many by many concrete classes and if you specify this every time you call this you will get this specific class and if you have a five or six classes implementing this class extending this class then every time you inject this class and then you ask for util2 it will always give you this one and this is not a preferred way this is not a smart way to use it i would recommend not to use preferences with abstract classes instead i will give you a better way to do this so let's remove this and then flush cache again and let's go back and make sure it will break on the front end so it will break here so now it's broken the better way to do it is we have arguments inside the arguments i will have an argument called util and since i specify the abstract class i now i can go ahead and inject the concrete class instead of the so i will replace it with this and this one will be an object object and now magento will know when we call the class main with injected abstract class abstract util will give me this implementer or this class that child the class of the abstract class so this is a better way of dealing with abstract classes now if we flush cache and refresh now you can see it works fine so we'll get the class util whenever you do this is the better way of having you can do this even with the interfaces but anyway you have preferences for interfaces or you might be having different maybe three or four concrete classes implement the same interface and then you would specify an interface and then you can use this with the interfaces as well but these are mainly for preferences preferences is when a class when a interface is created only for one class and when only one class implement that interface you create this preference there is another use case for preferences is to overwrite rewrite classes but it's not very preferable way of doing things but you might have a situations where are you forced to do this and it's okay and it's acceptable but most of the time try to avoid using preferences of rewriting the functionality of the core or third party extension now we have these preferences we have this constructor there is another thing how another technique in magento used to handle like a performance thingy is created for performance which is the proxies now let's have a class called heavy operation and then we can see how that works now let's go and create a class called heavy operation and then in heavy operation we create the class and space training dependency injection model as heavy operation in the heavy operation we will have a string name then we have constructor the constructor we will have a method called init this in it called the database and it has very complex query and it's very it's a like a relatively slow but we will we will have this uh set in the name this name equals last heavy operation suppose we are getting from a very complex query and it takes very long time so this is just a dummy this is not the case and then you will say public function gate name and will return a string return listening and of course this returns void now this class not always used is only used in specific cases and you don't want this in it to be called inside the contractor every time the application load or the page load so you only want this to be called and this in it to be triggered when is used to do this we will use proxies now let's have a look here and then let's inject the heavy operation heavy operation and then we initialize it initialize the heavy operation and then we get the function and get heavy corporation the operation to this the operation now this is how we get it we go to the template we will say class have the operation class the operation name is get heavy the operation get named now if we go to the the operation so we don't want this to be called every time the page load the only thing we can do is we go here in the di xml file and we specify the argument on its heavy operation and will be a site type object and to make a proxy of this one we will go to the class heavy operation copy the class paste it here then we will have proxy this is the way how you proxy class and make it called on the on demand this will be an on-demand class whenever i you i need it it will be called if i don't need it it won't be called and in this way this any heavy operation can be hidden inside method they're not necessarily called until they are called they are used when they are in demand they will be invoked not all this complex queries complex logic will be hidden will not be used will not be called until you actually need it so now that's splash cache and then refresh and you can see here it's called now let's go see the implementation behind it now if we go to the generated and then we have model inside model we have heavy operation we don't have the heavy operation holder anywhere except in generation or generated generated code and this is because we have this training dependency injection model heavy operation and then proxy and then inside the heavy operation you will see proxy so this is the class we have created but we want it to be on demand we added the proxy to it and this is the proxy and if we can see how they get named get subject and then get name if you look at the get subject if is not initialized then initialize it and then return the subject you only get this subject or this object heavy operation created when you called the get name on it so will not be created will not be instantiated the only thing is going to be instantiated is the proxy so in this way this is a lightweight it doesn't call the constructor of the of the parent class and it doesn't call this heavy method it will be created will be instantiated as broxy but this heavy this heavy method will not be called until will not be triggered until is on demand until it is called in the code so this is how you create a proxy it's a normal class and then you append proxy to it and magento will handle the rest so this is a the use cases or this is the use case of using proxies the next step we will have a look at is how do we create how do we use virtual types i will create a folder called virtual type and inside it i will have a name this last name will be name this class name will be public function get name and will return a name just return a name so this is just a simple class will be created here now we will have a default name class default name and type namespace training dependency injection model virtual type class default name and the default name will be public or we need a constructor here and inside the constructor will be name name initialize it so you would see this is a injectable class and then play function get name from the default name and this name get name default name now this is the default name we will have this default name injected in the main we will have here default name default name and we will have to initialize it and then function get default name and this default name now in the template i will use this default name is default name name now if i refresh you can see we get the default name here now if i have a specific requirement to get this as uppercase instead of lowercase what i'm going to do is i will have class here called our case name is named in space training dependency injection model virtual type class uppercase name extends name and then public function get name what i'm going to do here is we just have this str to upper so i want to inject the upper case instead of the name so i want to inject the upper case name instead of the name here and then i get this as uppercase instead of this default name text to do this i don't want to corrupt this class i won't need it as is here but i want it to be uppercase only in one place and this one place i don't want to corrupt this i don't want to have another class to do this to do this you will go here and then you will see there is a virtual type the name will be uppercase name you just give it a name and then the type will be the default name i want this one this is the virtual type i'm creating also i'm creating uppercase name as a subclass or subtype of this class and then now in the arguments one of the argument is name because the default name has an argument name in the constructor so i call it name and then xsi tag equals object and now instead of having the name here i will copy this class and inject it instead now if i flush cache i refresh [Music] you see there's nothing changed when i refreshed and when i added this because this is not used this is just a subtype of this type and it's not used anywhere so we haven't spoiled we haven't corrupted this class so this class is just functional as is by default now we want this to be a capital big letters we will go to the di and then here in the arguments the argument there is a default name and the default name is object i object and then i will add this virtual type here simple this uppercase will take over and will be given to the default to the main with glass uppercase now let's flash cache refresh now you can see these are coming as capital letters all uppercase because what we've done here is we created a virtual type which is a subtype of another complete type and then we can manipulate how it works so you can see we added the uppercase name instead of the regular name and then we'll convert everything to the capital letters if we remove this we'll revert by to default if we keep this we will override it by this uppercase the uppercase text now there is another thing called optional optional we've already seen the optional here in the main if we go to the main we already seen this optional but let's have a optional classes say for example if i create a class called optional name of spain now this is optional if i go to the main i'll type optional optional equals no by giving a default value null will be treated as optional and now i need to initialize it to know now i will need to get it public function get optional this is an optional argument and return this optional now if i go here and then do this class optional name get optional get name now if i refresh will give me an error because this class optional has no value and then it should return an optional but we don't have it but if we don't use it we remove it now all works just fine because we never used it now how do we add this optional inside class if you want to use it now i want to use it but i want it to be injected in the main this is simple if i just copy the class and then i go to the arguments the arguments i will have optional and the optional will be object and then clear cache so it's just a normal injection through the dixon file now i will refresh and you can see there is a class optional the last bit i want to talk about is the method injection method injection is very simple so let's have a look and see how we can do the method injection so method injection class now in the get name i will inject data object and then what i'm going to return is data object data name now you can see the method will accept an object and this is called a method injection once i inject something into the method now if i go to the main class and then how the method injection method injection initialize it now what i'm going to do is we're watching the method injection name will return a string now return this method injection get name the get name i'm going to inject the data object data object is will be in h needs to be created a data object need to be created and injected into the get name method there is no automatic method injection you have to create it yourself and inject it into the method there is always a automatic constructor injection but with the message there is nothing to say there is a automatic injection into method so we will need to do is we create a data object equals new data object and then we'll have a name we call it method injection in the constructor and then you pass you inject the data object here so this is the only way you can work with method injection and there is no automatic method injection in here so what we need to do here is copies on the class method injection name get it name and now refresh and here we go how we get the method injection method injection is always explicitly injected and there is no automatic injection i think this is it if you like this video please like and subscribe and i'll see you next video
Info
Channel: Alaa Al-Maliki
Views: 2,411
Rating: undefined out of 5
Keywords: dependency injection in magento 2, magento, magento2, magento 2, magento overview, magento guide, magento howto, magento developers, learn magento, magento tutorials for beginners, alaa almaliki, alaa maliki, magento module development, magento backend, magento frontend, dependency injection, dependancy injection in magento 2
Id: TBZUCKb8Gyo
Channel Id: undefined
Length: 39min 37sec (2377 seconds)
Published: Tue Dec 15 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.