در حال بارگذاری ...

Add Edit Profile Link0:06

Welcome back. Okay, so moving along right now, a user can sign up, but actually there's no way to currently edit their profile, so we should fix that. I'll start within my navigation section and right here, if the user is signed in, let's add a link. This one will take them to their profile. Now, we could just do slash profile, or if we anticipate having dedicated profiles, we might wanna be a little more direct,

Define Profile Edit Route0:30

or if we anticipate having dedicated profiles, we might wanna be a little more direct, like profile slash edit, either works, edit profile. Let's have a look in the browser and yep, we have an edit profile link. Alright, so of course if I click on it, we get a 4 0 4, that's our next step. Let's go to our routes file. And right down here, maybe we can place it here at the bottom route gets, uh,

And right down here, maybe we can place it here at the bottom route gets, uh, profile slash edit. And this will take us to profile controllers. Fine. All right, we'll call it edits. And once again, you gotta be signed in. Alright, do you wanna give it a name? It's up to you. Uh, why don't we call it profile edits? Uh, yeah, some people religiously use names, uh, routes. Some people don't use them at all. It's up to you.

Create Profile Controller1:11

Uh, yeah, some people religiously use names, uh, routes. Some people don't use them at all. It's up to you. I don't really have a strong opinion. All right, so I'm gonna create that. Now, make me a controller. Profile controller basic is fine. All right, we know we're gonna have an edit action and real quick, I'm going to import that. Okay? And let's return a view called profile edit. Alright, that's our next step. Let's create that file.

Build Edit Profile View1:33

Okay? And let's return a view called profile edit. Alright, that's our next step. Let's create that file. It's gonna be in our views directory, and I'll call it profile edit. Do blade, hp. So now if you think about it, this will take the same shape as our registration form. So why don't we just steal some of that and bring it in. Um, this will be edit your account, need to make a tweak.

Um, this will be edit your account, need to make a tweak. And yeah, let's see. The user is going to make, um, a patch request, I suppose, to profile slash edit. The method will be patch, and you can update your name, your email address, or your password update accounts. Let's see how that looks. If I come back, give it a refresh. And there we go. So let's go full screen. Now I can go to my homepage, I can edit the profile,

And there we go. So let's go full screen. Now I can go to my homepage, I can edit the profile, but of course it should be populated with the initial values, right? Okay, well now we can do that pretty easily. So right here we can set the value, the initial value will be, um, the authenticated user. So with that in mind, let's go into profile controller. Um, we could send through the authenticated user or just delegate to auth user.

Um, we could send through the authenticated user or just delegate to auth user. I'll do it like this though. All right, so now if I come back, yeah, I can say user, uh, name and if I come back, refresh it's populated. Do the same thing here. User email, it's populated. So in terms of password, um, there's a couple ways we can do this. Once again, we can have password confirmation to change it. I'm just gonna be very quick here

Once again, we can have password confirmation to change it. I'm just gonna be very quick here and say new password, something like that. So make it clear. If you wanna set a new password, you can do so here. If you wanna require a confirmation, that's probably a good thing you can do. And also, by the way, Laravel has support for submitting a form that requires that you enter your existing password, uh,

for submitting a form that requires that you enter your existing password, uh, and a dedicated middleware for that as well. But we're gonna skip over it. Okay? So now when I submit this form, it's gonna make a patch request to profile. And you know what? Let's just keep it simple. Actually, let's just do with profile. Maybe that's better. And then right here, profile and then patch to profile. But yeah, lots of ways to do this.

Handle Profile Update3:54

And then right here, profile and then patch to profile. But yeah, lots of ways to do this. So this will make a update, like, so, and if we scroll in here, let's add our method update. And how would we update it? Well, we're gonna have some request data. So this time, why don't we accept the request and we'll just do some inline validation here. Request validate. And you know what, you've seen me do this a bunch.

Request validate. And you know what, you've seen me do this a bunch. I don't think we have to write it out by hand. Let's paste it in, maybe something like this. Okay? You gotta give us your name. We have to give, uh, an email. And this one's a little bit unique. We're gonna say, when you give us an email, let's make sure it's unique on the user's table. Um, and we can ignore the current user ID and then the password should adhere to the initial values.

Um, and we can ignore the current user ID and then the password should adhere to the initial values. Okay? So now if we get to this point, we can die and dump the request data. And real quick, let's import these and we can ignore the authenticated user's id. All right? But anyways, let's give it a shot. So come back, edit, profile up, let's fix that. So by the way, this is a good example for why some people prefer named routes here.

So by the way, this is a good example for why some people prefer named routes here. I hard coded it, which meant when I changed the URI, I would then have to find every link to that page and update it as well. Whereas if I just used the named route, um, what is it? Profile edit, well then it would just fix it itself automatically. So if I come back, now notice that works even if I change the URL in my Rod's file.

So if I come back, now notice that works even if I change the URL in my Rod's file. Alright? So now if I tweak this, like that, update the account, you can see everything is being passed through here. Alright? So now this is very simple. We just update the user off user update and we'll do this manually. We'll say, uh, the name would be the request name. The email is the request email

We'll say, uh, the name would be the request name. The email is the request email and the password is knowable. So what we could do there is say password equals do we have one for password? If so, then let's use that. Remember, that will be hashed behind the scenes, otherwise we can defer to the authenticated user's password. Or another option is just don't even fill that at all. That would work as well. Okay,

Or another option is just don't even fill that at all. That would work as well. Okay, so now it looks like I'm referencing the authenticated user a lot. Let's just go ahead and, and cache it into a variable. And then I can do user id and then this can become user password. Is that it? No. One more user update. Okay, so now we can return a redirect to a route in this case profile edit with,

Okay, so now we can return a redirect to a route in this case profile edit with, and let's give it a success message profile. Updated. Okay? So I will let you take a look at that. It's the first step, right? I you update your profile, we validate everything. We update the user record, and then we, uh, redirect. Let's give it a shot. We'll say my full name here, update the account. Oh, it fails. Uh, not null constraint, failed

We'll say my full name here, update the account. Oh, it fails. Uh, not null constraint, failed for user password. If I made a mistake, it's okay, it happens. Let's die and dump the request data and refresh. Ah, so yeah, I didn't update the password. So that is set to null and it is present. I forgot it could be present, but set to null. Okay, let's tweak this. If we have a password, if it's true, the only on

Okay, let's tweak this. If we have a password, if it's true, the only on that condition should we set it. So what we can do here is just tweak this to that. I think that should work. Let's come back, refresh, update the account and yeah, now it's working. So if I switch, come back Jeffrey Jordan way, Jeffrey Jordan, way z update it. It's working. Okay, so let's do this.

z update it. It's working. Okay, so let's do this. And now what about if I tweak my email address? Like what if I do Jeff Jordan way at Laracasts? I can do that and that's fine. However, two things. One, you need to decide. Do you require a password in order to update credentials? Or is uh, is being logged in, uh, proof enough? Depending on the scale of the project, it might be enough to just let them update it.

Depending on the scale of the project, it might be enough to just let them update it. In other cases, no, you never update the credentials without requiring a password. So be sure to think of that. Okay, next, as a general good rule of thumb, if you change, uh, an email address, you should notify the old email address that it was changed just in case, uh,

Test Email Change Notification8:29

you should notify the old email address that it was changed just in case, uh, there's something malicious going on. And again, if that's a big worry for you require a password authentication as well, but even still, somebody could, could figure out what your password is. So I wanna test now that if I change my email address, uh, a notification is sent. So let's, let's do that.

a notification is sent. So let's, let's do that. Now within my test directory, let's add a new file here for profile. All right, it edits a profile and then let's do another one that says it, um, notifies the original email if changed or update it. Okay? Uh, you wanna do the happy path first, let's do it side by side.

Okay? Uh, you wanna do the happy path first, let's do it side by side. We'll start by visiting the route for profile edit. In order to access it, you must be signed in. So let's also add that it requires authentication. Yeah, keep in mind like we're doing tests, but I can't go all in on the test because this course would be 20 hours long. I just wanna show you the bullet points so that you understand the sorts of things you wanna write.

I just wanna show you the bullet points so that you understand the sorts of things you wanna write. So yeah, if I were to visit the profile, then I could assert that I'm redirected to the login page. So if I'm doing browser testing, I might do something like this, Give that a run, it passes. Or in these cases, sometimes you don't even need to open a browser, you can just make a get request. You can say, get this page

to open a browser, you can just make a get request. You can say, get this page and then assert, um, redirect to log in, give that a run, and you're gonna get the same thing. But in this case, we're not even bothering to open a browser because we don't need to. Anyways, assuming we are signed in, we'll say user factory create, And let's say this acting as the user, we're gonna visit this profile and then let's just update it.

as the user, we're gonna visit this profile and then let's just update it. So let's say, well, let's start by saying assert value for title. Or I'm sorry, what do we have here? Assert the name is the, the user's current name. So if we do nothing else, that should be green. Yes. But then let's fill name with new name. And now if I submit it so I can submit it by clicking update accounts.

And now if I submit it so I can submit it by clicking update accounts. So I'll say click update accounts. And for one, I should see a flash message. So I could say, what was it, account updated, what did we do here? Profile controller. Profile updated. Okay, give that a run. It works. Let's also expect that the user now has an updated name.

It works. Let's also expect that the user now has an updated name. So I could say User Fresh to match array and their name should now be the updated name, new name. Oh, nope, that failed. Attribute Fresh. I'm sorry. Fresh is a method and how we get green. Okay, so yeah, we could just do a couple of these. We could say, well, we assert that the email is set to their email, but now we're gonna change it to a new email, Right?

to their email, but now we're gonna change it to a new email, Right? So now after the update, we can ensure that it is reflected. Give that a run. We get green. Good. So another thing we can do is the notification. So let's steal some of this and then just remove whatever's not necessary. Let's say create a user, sign them in, visit the profile page. And when we, let's just do this.

visit the profile page. And when we, let's just do this. When they update their email, we expect a notification to be sent to the original email here, right? Heads up, your email has been updated. If you didn't choose this, please get in touch with support, right? So here's what we do. Let's show you how we can handle this. Um, we're gonna say notification, and I'm gonna fake it. I don't want any actual notifications to be sent.

Um, we're gonna say notification, and I'm gonna fake it. I don't want any actual notifications to be sent. So Laravel has, um, a really cool fake API I call fake, and then I can perform assertions on the notification facade. It's, it's one of the coolest things, by the way, that I think Laravel offers. It's really brilliant. So anyways, at this point, after we submit the form, a notification should be sent. So I can say notification assert, excuse me,

after we submit the form, a notification should be sent. So I can say notification assert, excuse me, assert sent to user email. And if I click through here, you'll see we want the notifiable, which is the user, and then we want the notification, uh, itself. So what is the notification? Um, maybe something as simple as email changed. Yeah, maybe something like that. Okay, so I'm gonna make a notification.

Yeah, maybe something like that. Okay, so I'm gonna make a notification. The HB artisan make notification. Whoops. There we go. Email changed. Do I wanna mark down view? No. Okay, let's import that. All right, give it a run. It's probably gonna fail. Argument one must be a type object, but a string, whoops, sorry, sent to the user, not the email, but we give that a run, but it should still fail, uh,

not the email, but we give that a run, but it should still fail, uh, because we didn't actually deliver that notification. Fine, we go into profile controller right down here and we need to say, well, if the email was changed, send an email changed notification, right? That's, that's what we're doing here. Okay? So why don't we do this, let's say original email, we'll cache it and then we'll say, well, if the uh, original email does not equal the new email,

we'll cache it and then we'll say, well, if the uh, original email does not equal the new email, then they're different, of course, in which case we should notify the original email. Here's how. So we could say user notify, right? That's the normal way, but in this case it would notify. I wonder if there's a way to overwrite that. I'm not sure to be honest, but I think it's just gonna notify the new email

I'm not sure to be honest, but I think it's just gonna notify the new email because we've updated it. So in this case, we actually want to send basically an anonymous email to the original address. So here's what we do. We can use the original notification facade and say, okay, we're gonna route this. We're gonna use the mail driver to the original email address,

We're gonna use the mail driver to the original email address, and then we're gonna call notify on that. Okay? So this is how you can handle notifications to non-users. Basically, if you just need to send a notification to a random email address, you would use this, uh, method. So I instantiate new email changed, and let's include the user as well as the original email address.

and let's include the user as well as the original email address. And let's go ahead and accept that real quick. Gimme the user and the original email address. All right, we'll assign those And uh, yeah, so does this look okay? My editor doesn't think so. Let's have a look. Oh, there we go. Missing a cynic colon. Alright, does that makes sense? I think this should do the trick. So I rerun my test.

Alright, does that makes sense? I think this should do the trick. So I rerun my test. Oh, and it fails. Actually I would've expected that to pass. So let's debug. Um, oh yeah, yeah, this is exactly what we were trying to solve. We forgot when we wrote the test that the email address would change in the database. So we would notify the new email, which you still may want to do, but I also wanna notify the old email.

So we would notify the new email, which you still may want to do, but I also wanna notify the old email. So I think there's an on demand assert sent on demand. Yeah, this is the one we want. The way this works is you give it the notification class and then you'll give it a call back to perform your assertion like this. So, well first, if we just keep it like this, then we give it a run and it passes. So now we know that well at least some email changed, uh,

then we give it a run and it passes. So now we know that well at least some email changed, uh, notification is being sent, but we don't know where. So yeah, now we can just accept the email changed notification. Good. And then this should also accept the, um, the routes, I think. And then we would have the notifiable, which is the user. So it's just the three things that are sent through. So if I die and dump the notifiable,

So it's just the three things that are sent through. So if I die and dump the notifiable, we should have the user, or in this case the anonymous user that contains the original email. Yeah, that's the way it works. It's a little more complicated when you wanna send a notification to an anonymous user, um, versus an actual user in your system, but sometimes you need it.

versus an actual user in your system, but sometimes you need it. Okay, so now I can say, so we can return the notifiable routes for mail. And remember, this is what we did in the controller, uh, routes for mail. That's how we are delivering it, the mechanism. And then make sure that it equals the email address. So in this case, we could just say user email, but I'm gonna be explicit here

So in this case, we could just say user email, but I'm gonna be explicit here that we have the original email tract, even though we could still do user email in this case. So use original email and make sure it matches, give it a run and it passes. It works. So yeah, just a tiny bit more complex, but it'll do the trick. Honestly, though, as I write this, I think unless I'm missing something, again very possible,

Honestly, though, as I write this, I think unless I'm missing something, again very possible, that should be a little easier to say Aer sent to On demand. In fact, is there something Aer sent to On demand? Not that I can see. So we'll put a pin in that. Maybe there's something a little simpler, but I don't think so actually. So nonetheless, this all works and we have a series of tests that ensure that our edit profile section is working.

and we have a series of tests that ensure that our edit profile section is working. Great job.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟