[Music] welcome to level six advanced course beyond the basics so in this course we're exploring levo in a deeper level

today we're gonna be talking about the service container so what I have here is the documentation for service container service container is one of those imperatives things that you understand

whenever you're working with level in order for you to take your projects to the next level you need to start using the service container the service container is simply a service that level

provides for you that allows you to tell laravel how an object or class needs to be constructed and then level can figure it out from there now this is a very very powerful concept

but it is a little bit difficult to explain I do feel like it's a lot easier to see it in action than it is to try to explain it but as a side note the level service container is simply just a way

for managing your class dependencies every class is going to have some sort of dependency with it and you can inject them automatically we've done a little bit of this using route model binding

and you may be familiar with that that is one of those things however today we're gonna be exploring an example from scratch and sort of showing you how it works so I have here

a brand new fresh installation of laravel six and we're gonna start from the very very beginning so here's what I want to do I want to create a controller and in my controller I want to inject a

specific class now is a first run we're gonna do it the regular way and then we're gonna slowly refactor into more and more advanced example so here we go let's go ahead and create that

controller now so we'll say a PHP artisan make controller and we'll simply call it pay order controller the example we're gonna be working with today involves an order and a payment gateway

a typical setup for whenever somebody places an order through your site and you want to charge their credit card or their bank so here we go let's pull open that pay order controller and in here

we'll simply have a store method so in my store method I will actually have a payment gateway which I don't have yet so let's create that now inside the apps control I'm going to

create a directory and this directory is going to be called billing and inside of billing will have a new PHP class which will be called payment gateway as a side note typically you create a payment

gateway that way you can have several different payment systems in one application but you always call your payment gateway so this payment gateway will simply have a method which will be

charged charge will accept an amount and by the way this amount will always be in cents so twenty-five dollars would be twenty five hundred cents and simply in here charge the bank and all I want to

return for now just an array of information this is all made up but it gives you a real world example of how this would work so for amounts of course we will have amount and then maybe let's

have a confirmation number and this will simply just be STR that's illuminate support STR random what is that STR did get imported up here at the top alright so now we have an amount and a

confirmation number so in my payments controller I'll new up this payment gateway like this so new payment gateway and that's it so notice that payment gateway did

get imported up here at the top so now if I died and dumped payment gateway now I don't have any route right now into this so let's go ahead and just add one now and we'll simply call this one route

it's gonna be a get route this is all made up remember we're just demonstrating the concept so this will hit the pay order controller at store so in my browser let me go ahead and visit

slash pay so sure enough I have my payment gateway so of course let's go ahead and hit that charge method on it and let's go ahead and charge so 2500 cents and sure enough we get back our

confirmation pretty cool but what if I told you this what if I could get rid of this line all together so we can ask laravel to go ahead and inject this for us levels gonna use the reflection class

and the basics behind reflection is that if you asked somebody to describe themselves they wouldn't be able to unless they had a mirror or a reflection of themselves they were looking at

themselves they could tell you all about themselves but if they don't have a reflection then they don't know what they look like so same thing for objects it takes an

object and then it puts a mirror in front of it so that it can reflect on itself and conceptually speaking it can tell you a lot about itself so using the reflection class in here we can simply

type hint quote/unquote payment gateway let's go ahead and give it a variable of payment gateway and now I can actually get rid of this line altogether if we hit refresh notice we still get that so

level is injecting payment gateway for us automatically all we need to do is ask for it so we're saying this store method requires a payment gateway and then go ahead and give it a name of

payment gateway that way we can use it so that's pretty cool so this in itself is already pretty powerful however let me go back to this example and I will actually delete our injection there what

if I needed to pass something into it so let's make a modification let's go back to the payment gateway and let's pretend that now I need to be able to specify the currency so let's add a constructor

here and we'll say and the constructor you're going to receive currency so let's go ahead and initialize that field and so we have a private currency variable now what happens well you see

now that it requires that parameter so we can pass in US dollars and then let's actually modify this as well that way we know what our currency is going to be we can access that with this currency and

now if we hit refresh now of course we get our currency but as you can imagine this will no longer work I'm going to actually make it fail so you see what happens let's go ahead and get rid of

this line and there is no way for me to actually add that currency and of course if I run this I get an error I get a binding resolution exception meaning I was unable to give you the dependency

that you were asking for and mostly to do with the fact again that it requires that currency parameter and actually tells you right here it says the currency parameter it is

required and you didn't pass me one so I can't make that class for you so how do we fix that well for that we bring in a service provider so if we go into app providers there's an app service

provider in the app service provider is where your application bootstraps itself of anything that it needs so we can say the following we can say in the register method we'll say this and you have

access to app and app is basically your entire app so in my app I want to bind the following thing so whenever anyone asks for a payment gateway we do need to import that up here at the top so

whenever anyone asks for a payment gateway this is how you construct it and the way that you do it is just passing a callback so we'll pass in a function and the function actually accepts your

entire app and so inside of here we construct our payment gateway so let's go ahead and return a brand-new payment gateway but this time let's pass in the currency as US Dollars and now if we

come back here and hit refresh we're back to working but now the u.s. dollars is coming from our app service provider if I change this to Euros for example yep

that changes so it doesn't matter what I put in here now let ovo knows how to construct this payment gateway now one important thing to notice here is why is this important why would anybody care

about this well mostly to do with the fact that if you ever needed to use this payment gateway again say in a different controller your controllers are no longer in charge of knowing how to

create a payment gateway furthermore if tomorrow you changed payment gateways and now you had a totally different way of charging a payment the controller doesn't need to change only your payment

gateway needs to change it wouldn't make sense for you to have to change your payment gateway and your controller to make a payment change because the controller should not

know that much about how your payment is actually processed that's not the controller's job that's the payment gateways job and again we are covering this specific example but this entices

your entire application you always need to try to encapsulate the logic so that it doesn't need to change all these different files just because you need to make one small change in one part of it

so leaking information such as how to construct a payment gateway is not the controllers fault because imagine you had 50 controllers that required this payment gateway to make that quick

change from one currency to another it would literally require you to change 50 files that never makes any sense so let's keep going with this example and let's take it to the next level imagine

now that I want to be able to apply a discount this is something typical of a payment gateway we need to go ahead and apply a discount into our payment gateway so now to create this discount

we're going to need to actually be able to have an order so what will create a whole new concept to our application which is going to be orders so we'll add a new directory under app and inside of

here let's add a PHP class for order details and order details is going to be a fairly simple class let me go ahead and clean it up and what we're gonna have is a constructor and in my

constructor I will need that payment gateway again and so notice that it is being imported up here at the top and so all I'll do is actually just initialize that as a private field you can get rid

of those comments and so we'll have this special method which will return all of the order details so we'll call that all and inside of here this is where I'm going to actually set the discount so

I'll say this payment gateway set discount this doesn't exist of course but in this particular order it's going to be five dollars off and now we'll return an array with what would be the

order details same name is Victor and we'll say maybe the address is going to be one two three coders tape Street that's good enough of course set discount doesn't exist in my

payment gateway so let's add a new public function here for set discount we'll call this a mount and in here well actually going to need a new variable so we'll call it discount and

initially this discount will be equal to zero and then if set discount actually gets called and we're going to override this count and just set it equal to whatever the amount that got passed in

as a discount this one okay so simple enough but now in my controller I don't have an order right I'm charging this amount out of here this amount is really not correct because it's just an

arbitrary amount it's not coming from anywhere so what we can actually do is we can ask laravel for as many injections as we want we don't have to do just one so we could say all right so

I also need order details we'll save that to order details and so now we are asking for an order details which do notice that it is being imported up here at the top and we're also asking for a

payment gateway so pretty cool so now my order comes from order details all remember that's that method that we created right here this all method and when we call this all method it actually

sets the discount on the payment gateway so that would be the way that our discount actually gets set so now when we charge our amount we're gonna have to make a little bit of a change here in my

payment gateway we need to actually account for that discount in my charge method so I can say okay so the amount that we're going to charge is amount minus this discount and then finally

let's go ahead and add a whole new section here so that we know what the discount actually was for this particular payment so we'll output that as discount okay so let's give this a go

and let's see what actually happens I hit refresh you notice that my discount is zero you may be wondering why that is I mean we actually set a discount of $5 but it's

not showing up and of course this has to do with the fact that whenever you bind into the container every time that the class actually gets asked for your returned a brand new object Lenovo will

actually invoke this function every single time a new payment gateway gets called so what it's going to happen is in my order details this payment gateway that we're receiving here is a fresh one

and then again inside my pay orders controller this payment gateway is a fresh one they don't know anything about each other now typically payment gateways will only be one instance of it

and you will use that instance in your entire request so to do that instead of binding into the container we can use something called a singleton and a singleton is a way of telling laravel

that there's only ever going to be one of these payment gateways so what happens is the first time that somebody requests a payment gateway laravel invokes

this callback but then every subsequent time after that it just simply returns whatever the first one actually passed back so in essence you get the exact same object so with that small change

into a singleton go back to Chrome and notice how it says discount zero I'll hit refresh and sure enough now our discount is showing up and then notice that the amount that we got charged is

actually two thousand not twenty five hundred so he went down to $20 because of the five dollar discount so that's how a singleton would work so what is happening again just to run through the

flow one more time is whenever my order details gets created it requests a payment gateway levels going to look inside the container to find a payment gateway so it finds this payment gateway

it right here and we have instructed this particular callback to tell laravel how to actually make up a payment gateway so it will actually invoke this function and save the results then it

will pass them into my order details so then it gets to the second parameter where we actually need a payment gateway so it goes back into the container and says wait a minute

I've already got one of those so here it is so it doesn't run this again it just simply returns the results of the first time that this was invoked and then it passes it in as a second argument so

whatever we have here is the exact same payment gateway that we had inside my order details so now let's take it even another step further what if I had a bank payment and maybe a credit card

processing company two different things how would I be able to dynamically choose which one it is that I want to use for this particular order so for that let's turn this payment gateway

into my bank payment gateway let me go ahead and rename this payment gateway class to bank payment gateway let's all refactor that and all we'll do there is simply just rename it because what I

want to do is I want to extract an interface phpstorm makes this very easy to do but again you could do it manually so we're going to extract an interface that will have a charge and a set

discount so let's give it a name of just simply payment gateway contract okay so this is what the interface looks like an interface is just simply a road map of how a class needs to be constructed so

the way that this works is in my bank payment gateway we are now implementing payment gateway contract so my payment gateway contract is a way of us adhering to the same API

from class to class so I can blindly call this charge method because I know that as long as it implements the payment contract it is required for you to have one of those methods and the

other method that is required is of course the set discount method so now here's one thing that I can do so instead of requesting a bank payment gateway I just want to request a payment

gateway at this point the controller doesn't care if the user used a credit card where the user used a bank so Lester's request a payment gateway contract not a particular implementation

of the payment gateway but just the contract in general again I don't care what type of credit card or bank my user is using but now of course if we go back to Chrome we hit refresh well we have a

problem and the first thing is that you cannot actually generate an interface and interface is not something that you can new up and so of course we need a concrete implementation of this

interface so the way that we would do that in laravel is in my app service provider so we're still going to have a singleton but we're not requesting the bank payment gateway we're gonna be

requesting the payment gateway contract so whenever anyone wants a payment gateway contract here's the concrete implementation of it so this is what you're actually going to use and so now

if we come back here and hit refresh now we get an error but this one is actually coming out of something else because if you remember we actually used this payment gateway in two places so we need

to change it in the order details because notice that here we're still using a bank payment gateway so let me go ahead and change this over to payment gateway contract instead and we can

clean up this use statement and just have the one and now we hit refresh we're back to working notice that this count is working and everything is working so you may be wondering how is

this any better I don't understand how this is any better than what we had before the exception now that we're requesting this contract well check this out let's create another payment gateway

I will go ahead and save this one and this one is going to be called credit payment gateway so this is gonna be representing my credit card processing so credit payment gateway will still

implement the same contract so it's going to be adhere to the same rules as my bank payment gateway so now this one will say the following credit cards they have a fee so maybe the

fee needs to be charged whenever a credit card is process so let's create this new idea here of a fee I'll just call it fees and in this particular one the fee is going to be 3% so we'll say

okay so the fee is amount times 0.03 so that will give me the fee associated with each charge so the amount that we're going to charge is going to be the amount minus the discount but then 3%

off of the original amount so what I'll actually do is why don't we put this in a variable so we'll say okay so my fees are going to be that amount and then in here we could just simply

use fees and so the charge amount is amount minus discount plus any fees that got associated with this charge so now let's switch over from the bank payment over to the credit payment so back in my

app service provider whenever any one request a payment contract notice how easy it's going to be to change from a bank to a credit card all I need to do here is I will actually comment this

line out but all I would need to do is return a new credit payment gateway and it's still going to be u.s. dollars so now if we go back here and hit refresh notice that now we are charging the fee

and just like that we change from one payment gateway to another payment gateway and we didn't change the order details and we didn't change our controller we're simply requesting a

contract we don't care if it's a bank or if it's a credit card that's for somebody else to worry about so of course you can dynamically choose which one you're going to use so for a

very simple example let's do the following let's say okay if the request has a key of credit that means they want to use a credit card so in that case this is the payment gateway that we're

going to use otherwise we're gonna use our bank payment gateway now this of course could be calculated in any way shape or form of course one of the ways would be

if the user selected credit or Bank from your checkout process in that case that is how we would determine if it's a credit card or if it's a bank payment gateway so let me go ahead and hit

refresh on this one and we are back to our bank because notice that it has no fee but now if I said okay let's say credit gets set this basically equal to anything we'll just set it equal to true

now we're running this as a credit charge instead so notice how both of those implementations work and all it does is this just checking this right here and again we could check the order

we could check just about anything we want to make that switch from one to another so we can make that check anyone in our application and then all we need to do is make sure that we use the

correct payment gateway when it comes time to actually perform the charge so that's gonna wrap it up for this lesson this is level 6 advanced and talking about the service container if you've

enjoyed this lesson of course go ahead and subscribe and share it throughout all your social media networks that way we can continue to grow the coders tape channel my name is victor thank you for


    container laravel eloquent Eloquent polymorphic relation#3 explain facades in laravel extend laravel facade in laravel facade laravel example Facade Pattern generator php higher order functions how laravel facade works laravel laravel 5 laravel 6 laravel 6 tutorial laravel 6 what's new laravel advanced laravel advanced project laravel best packages laravel best practices laravel best tutorial laravel binding laravel collections laravel composer install laravel container laravel facade tutorial laravel facades laravel facades explained laravel filter products laravel filters tutorial laravel functions laravel generator laravel helper functions laravel installation mac laravel ioc container laravel ioc service container laravel lazy collection laravel macro laravel macroable laravel macros laravel mixins laravel notification laravel notification tutorial laravel pass data to view from controller laravel pipe dream laravel pipeline laravel preview laravel query builder tutorial laravel query string route laravel repositories laravel repository design pattern laravel repository interface laravel repository pattern laravel route model binding laravel service container laravel singleton laravel soft delete laravel soft delete tutorial laravel table filter laravel traits laravel tutorial laravel view composer laravel view data from database lazy collections macroable macroable laravel mixins laravel notification laravel notification laravel database notifications laravel php generator php generators polymorphic relation polymorphic relationship polymorphic relationships polymorphic relationships laravel polymorphism repositories in laravel repository pattern repository pattern laravel service container service container laravel soft delete in laravel 5.7 soft delete in php soft delete laravel traits php view composer view composer laravel what is facade in laravel