- Overview
- Transcript
3.1 The Single Responsibility Principle
Let’s see if we can decouple out code from the rest of our app. According to the single responsibility principle, every class should have one single responsibility, and that responsibility should be entirely encapsulated by the class.
1.Welcome1 lesson, 01:07
1.1Welcome01:07
2.The Absolute Basics of OOP5 lessons, 22:53
2.1What Is OOP?04:40
2.2Classes vs Objects05:42
2.3Class Constants and Internal Reference04:19
2.4Public vs Private Scope06:05
2.5Copying vs Cloning Objects02:07
3.Digging a Little Deeper Into OOP5 lessons, 43:52
3.1The Single Responsibility Principle15:18
3.2Magic Methods11:16
3.3Autoloading Through SPL03:37
3.4Working With Namespaces05:14
3.5Autoloading With PSR-008:27
4.OOP inheritance2 lessons, 12:02
4.1Class Inheritance And Protected Scope09:22
4.2Overriding Parent Methods02:40
5.OOP Abstractions5 lessons, 1:00:05
5.1Abstract Classes05:59
5.2Interfaces14:53
5.3Static Properties And Methods06:49
5.4Traits14:44
5.5Dependency Injection17:40
3.1 The Single Responsibility Principle
Hello, and welcome back to PHP OOP Fundamentals. In the previous videos we covered quite some ground, but that's left us with a user class that has way too much responsibility. So before we go on, let's see if we can improve on that. Let's just open up user.php and recap what's happening in this class, shall we? Okay? Well it's user class, so clearly it's sole responsibility should be to hold the data for a user, but right now it has multiple responsibilities. For instance, this class also takes care of validation. Here we're calling a validation method that is defined at the bottom of the class. And here we have even hard coded validation inside of the set email method. Now this poses some real problems. First of all, our validation is now tightly coupled to our user class. We cannot reuse it anywhere else inside of our application. Now let's just think about that for a moment, is that really a good idea? What if we want to check for a valid email in say our contact form? Should our user class really be responsible for validation, or can we maybe extract this away and create some sort of validation service. Also if the user class is about storing user data, do we really want a login and a logout method? Or should we maybe create an authentication service for that dedicated to logging in and logging out. And what about hashing? Is a user class really the only place in our application where we'll ever need hashing and then if not, then why is it in our user class anyway? All these considerations have to do with the single responsibility principle. Now according to the single responsibility principle, every class should have one single responsibility, and the actual responsibility should be entirely encapsulated by the class. With that in mind, let's see how we can improve on this. Okay, let's just first incorporate a little structure in our application. I'll just create a folder and call that app, and then I'll take the user class and move it inside of that folder. And maybe we'll just rename that to User with a capital U. Okay? So let's create a new class here, and we'll call that Validator. And finally let's create a new PHP file and call that Helper.php. Okay, now let's open up our validated file, and let's talk about creating a very crude validation service to our validated class. It will be far from perfect, but for now it will do the trick I think. First of all, we need something to store errors in that will default to an empty array and we'll just create that privately. And then I think we need a public method called validate. Now if validation fails we'll add errors to our private errors array so we'll also need a public method to get errors from that array. We'll just call that, sorry, we'll just call that get errors like so. And of course that will just return this errors. Okay and now for the validation method. Now that will take two parameters. The first will be an array like so, that will be called data and it will contain the data we wish to validate. Now the second will also be an array, and it will be called rules. Now this will contain the rules that we wish to validate against. Okay, now we'll start by assuming that validation has passed, so valid equals true. And then we'll end by returning that valid variable. Now, if by some chance one or more rules fail, we just set valid to false. Okay and now for our rules, we'll need to loop through them like so, for each rules has item. And let's call these, I don't know rule set I think. So item would be something like email. And let's just assume that rule set is a string. And then it's build something like this. So we have a validation rule here, then a pipe, another validation rule, another pipe, and another validation rule like so. Now, at the moment, ruleset is a string, but I would really like it to be an array, so I can loop through it. So I'll just do Explode here. I'll set the delimiter to the pipe that we just talked about. And we'll pass in the rule set as the second parameter like so. And now we have an actual set of rules that we can loop through. So we'll do for each rule set as rule. And then we'll just try and run that rule. Now, our rule could be a string like require the but our rule could also contain a parameter. Let's just say for the sake or argument. Volume that we're only accepting one parameter here. I mean I said this would be crude validation right? Okay so let's just check for a colon like so. If we have a colon inside of our rules set, we'll set a pos variable, and then we'll just adjust the rule and the parameter according to our pos variable. So let's just do a little check here. If pos does not equal false, then we have a parameter. Let's just grab the parameter from the rule string. We'll do a substring on our rule, and we want everything behind the colon here. Subsequently, our rules string will be everything before the colon. So starting from zero up to the colon. Now what will happen if we don't have a colon in our string? Well in that case parameter will be equal to an empty string, and nothing will happen to our rule. It can just stay the way it is. Now the next thing that we want to do is take our rule, say it's called Email, what we really want to do, is look for a validate email method and if that exists, we need to pass the name for the item that we're validating against, we also need to pass a value and if we have any parameters we'll just pass those as well. So in order to be able to do that we first need to construct a method name. So let's create a variable called methodName. And let's just set that to validate and then followed by use the first rule like so. Now if the rule is email than that would give us validate email. Now we need to do something that we already did before in the user class, and that is see if that method exists and then if it does we'll just call it. So then we'll just do this. Method name, all right. And then we'll just take the item that we have here and we'll pass that as the first parameter. Then we'll take a value, we'll have to define that later but okay. And finally, we'll take our parameter and just pass that in as well. Okay now, for the value how can we find the value for this particular item? Well assuming that the item is sit inside of the data array, we could just do data and then item. But it would be nice to check to see if it exists first. So we'll do isset data item, if it exists, we'll just past that in, if not, we'll set it to null, now our validation method will return true or false, so we'll just assume that this returns true. But then if it does not we'll just hit valid to false, like so. So now to make this work let's just open up index.php and set up our rules and data array. First of all we'll require all the necessary files here. So that's user, validation, and I think it was helper right, and then we just remove this all. Next we'll set a rules array, and we'll also set a data array and like so. Okay let's see, what kind of rules do we have? Well, we have a rule for e-mail. And let's make that equal to or required. Pipe email, and I think that should do. And then we'll also need validation for our password, so let's make that required as well and let's also set that to a minimum length of eight. So, if I'll just copy this and paste it inside of this array. Then we can set some data to work with. Let's just do joost@tutsplus.com and maybe for the password we'll do 1, 2, 3, 4, 5, 6, 7, 8, like so. Now to run validation, we'll just set a validator variable and we'll do new validator like so. Now remember we had a validate method, so we'll do validator validate and we'll pass the data as well as the rules like so. Now let's see if that's all filled out correctly. Okay, I need validator instead of validation right here. And I think that should do. Let's just try that out. We get a blank screen so no errors. Okay, good. Time to set up the actual validation rules. Let's go back to the validated class and create those methods. Let's just make these private for now. Okay, they were called validate email. And as you will recall, these are the three three parameters that are being passed. And we'll just copy this out twice as well and change them into validated required and validate min. Now required is a simple validation rule or a fairly simple validation rule. We'll just do a simple check here. If the value equals an empty string, or if the value equals null then validation should fail for this method. So that means we should add a message to the errors array. Let's just make that an index of item like so. And then let's just add an error. Okay? And I think that should be something like the item field is required. Now as I said it's not perfect. I mean in a perfect world you should run this through a translator class or something. But okay, this is for demonstration purposes. Also we need to return false because the validation rule did fail. Okay. Well if it's not failed, then it's probably pass. So we'll just return true. Now I would really like to find out if a validation failed or if it passed. So let's just go back to NXR PHP and do a quick conditional here. We'll just say that if validator is actually returning true, then we'll just var_dump passed. But then if it's failed, let's just var_dump something else entirely. Let's take the validated class. And dump the getErrors message right to the screen. And of course before we can check that out, we need the other validation to return something as well, like so. Okay, let's just have a look. We have a pass here, let's see if we can make it fail now. Email is required so if we delete joost@tutsplus.com, we should get a big fat fail here. Let's try that, and here it says email error, the email field is required. Although something is a bit fishy here, I'm getting this error twice. Let's see. It probably did something wrong here. Okay yeah I see I'm running validate twice, so if I just remove this instance here, then we would just get one error here. Okay cool, see if that works for password as well. We'll just remove that and reload the page we have here. Email required, password is required. Fine and dandy. Let's hit up our next two validate methods. I just want to make sure I have some values to work with here, I'll set an invalid password. And also set an invalid email, okay? Now let's quickly set up these rules here. Validate email first. I'll just copy this here and paste it in like so. Then I'll go to the user class and make sure we copy this email validation expression here, so that we can reuse it. Okay so now if that validation fails, then we'll say something like the item field should be a valid email address and then instead of string, we'll have to pass value there. Now let's just copy this once more and do our validate min method as well. Here we wanted to check against the length of the string. We'll need to pass in value there. Now that should be equal to or greater than the pass parameter. In this case, that would be eight. And then if that expression fails, then we need to set that error parameter, like so. Let's go back to the browser and reload that. And there's our errors, just like we expected. We have an invalid email address, and an invalid password. Let's just do one final check here. We'll set our email to a valid email address, and we'll change the length of the password, like so. And all errors are gone. So with this, we've taken validation outside of our user class. Now let's just remove it here. I'm thinking we can clean this up quite a bit. We don't need a MINCHARS constant here. So we can simply remove that, all we have to do here is set the password to the path string, and the same goes for email like so, and we can get rid of this validation rule as well. Now in order to facilitate method chaining, we could also do something like return this here inside of our setPassword method, and we'll do the same for setEmail, okay? Okay so now if our validation passes, we'll just create a user called joost, much like we did before. That will be a new user, and then we'll use joost.setEmail and just set that to data['email']. And then because we have method chaining allowed, we can do Set Password, and then we can paste in our password like so, password. All that's left for us to do now is hash that password, and inside of our helper file, we'll just create a helper function. So we'll do Function, gethash, that will take a string as a parameter. And that will just return hash. And let's see, that was a char256 I think, and that should take string as a parameter like so, okay? So to actually hash that password before we pass it to the joost object, we'll just do gethash and then pass in their password. Now once we've set all the properties for our object, we can simply dump it to the screen and see what we have here. And there you have it. There's our email and password for user joost. Ok, so quick recap. We've taken validation outside of our user class and cleaned it up quite a bit. We've created a validator service that we can use over and over again, throughout our entire application. And we've created a helper file that can help us do simple things like creating a hash. Now our validator class is concerned with validation and validation only. And our user class is concerned with setting up a user, and logging in and logging out but okay, because that's so tightly coupled to a user anyway. I think it's okay to leave it in here for just now. Well that's all for the single responsibility principle, I'll see you in the next video where we'll talk about magic methods, I'll see you there.







