Creating order confirmation email0:00
So, besides showing a thank you message, we also want to send out an email to our User with all their information regarding their order. So let's head over to our editor and let's implement the ability to send out this email. So let's open up our terminal and let's run php artisan make:mail and let's call it OrderConfirmation. So now we can say Mail::to and pass our User and we can say send and we'll open a new instance of our OrderConfirmation mail and we'll pass the order. Now let's update our mailable itself. So let's set this properly. So here we can set the subject of our email, which is Order Confirmation, and let's add
So let's set this properly. So here we can set the subject of our email, which is order confirmation, and let's add the order ID here as well. Okay. Now here we can define the content. We don't have a view yet, so let's head over to our resources directory, views, and there is already a emails directory created by Jetstream. So let's create a new Blade file and let's name it order confirmation. Now let's make sure that we update this reference here. Now let's take a look at how we can preview this email without having to place orders.
Adding a preview route1:24
Now let's make sure that we update this reference here. Now let's take a look at how we can preview this email without having to place orders all the time. So if we go to our routes file, we can say Route::get and let's say preview and return a closure. First, let's grab an Order that we can pass to our email. Next, we'll return a new instance of our OrderConfirmationMail and we pass the order. Now if we go to our browser and hit the preview endpoint, we should get a preview of our email itself. Now we don't have everything defined yet, so if we switch back to our editor and go
itself. Now we don't have everything defined yet, so if we switch back to our editor and go to the actual Blade file, we should be able to echo out some data. Let's say this order and let's say id, sorry, without this, order id, and this is not defined and this has to do because I made this a private property. So I think if we set this to public, it works, there we go. So any public properties are automatically passed through as data to our view. So let's write our email. So let's use a basic HTML template and let's write a message that's going to be hey and then the name of the User, we're going to say thank you, order, you can find all the
Fixing order-user relationship2:53
So let's use a basic HTML template and let's write a message that's going to be hey and then the name of the User, we're going to say thank you, order, you can find all the details below. So we're currently getting an attempt to reach property name on null and I think that's because we haven't defined an inverse of the relationship. So let's do this right now. Let's say public function user(), this is going to return a belongsTo relationship and it should return our User model. Okay, there we go. So now we get our name, we get a thank you message and now we can list all the necessary.
Okay, there we go. So now we get our name, we get a thank you message and now we can list all the necessary information below. So let's create a little table. We have our item, quantity, and total. Now we can simply loop through each of our order items. So we can say item name, followed by our description. Next we'll have the price. So first we'll have item price, next we'll have the quantity, and this might be a bit confusing because the amount doesn't match up, so let's add a text column as well.
So first we'll have itemPrice, next we'll have the quantity, and this might be a bit confusing because the amount doesn't match up, so let's add a text column as well. And this is going to be amountText. So now this should match up. So if we add 311 plus 317, we get 1828. Okay, now these numbers, we need to make sure that we do the same as we did with our card and make sure that these are automatically formatted whenever we echo out these numbers into our blade file. So if we look at our cardItem, you can see what we did here. Let's take a look at our products, for example, we have price.
So if we look at our cardItem, you can see what we did here. Let's take a look at our products, for example, we have price. So let's switch to our order, and let's define the accessor for our different columns. So we have price. This actually should work if we head back and refresh. There we go, perfect. Additionally, we have amountDiscount, amountSubtotal, amountText, and amountTotal. Now this may become a bit repetitive because we have to repeat this for every column. Like I mentioned, price, amountDiscount, amountSubtotal, amountText, total. So maybe it's easier to just create a custom cast.
Building a Money cast5:40
Like I mentioned, price, amountDiscount, amountSubtotal, amountText, total. So maybe it's easier to just create a custom cast. So if we open up our terminal, we can run php artisan make:cast, and we'll say MoneyCast. So now we can simply define our cast array on our public property, and we can say price, and we're going to pass our MoneyCast. So let's remove this, and let's head over to our custom casts, and here we have our getter, we'll paste in the code that we had earlier, and simply return it. This will make it a bit easier, because now we can simply reference all our different columns.
This will make it a bit easier, because now we can simply reference all our different columns. So if we switch back to our browser, you can see that all the values are now updated except total. We had amount, oh yeah, so we've got one amount total. There we go, now all the values are updated. This also means that we can actually clean up our Product model as well, and apply the money cast here as well, and remove the protected method we have here. Now we should move to cards, this is a bit different, so we don't need to make any changes here.
Now we should move to cards, this is a bit different, so we don't need to make any changes here. Let's take a look at cardItem, the subtotal, I can change and stay the same. So I don't think we need to make any additional changes. Okay, so we have each of our items, we have the price, quantity, tax, total, and now we can have a totalAmount listed on the bottom. So let's create a footer, and let's list all the data that we have. So if orderAmount shipping is higher than zero, we'll say shippingCost, and return this value. Now we can repeat this, and do the same for amountDiscount, the totalAmount of tax,
this value. Now we can repeat this, and do the same for amountDiscount, the total amount of tax, subtotal, and finally the total amount. Now we take a look, we can see that we have the additional prices, which are above zero. Now these aren't formatted at this time, so let's head over to our Order, and let's add these casts. There we go, so now if we head back, we get an error, because this is now returning a Money object instead of a number. So I think instead of saying it's more than zero, I think there's a helper method, which is positive.
So I think instead of saying it's more than zero, I think there's a helper method, which is positive. Let's see if that does the trick. Yeah, there we go. Now we just need to make sure that these columns align, and let's increase the call span to be 1, 2, 3, 4. There we go. So let's apply this to each and all of our columns. There we go, so now everything is aligned properly. So this doesn't look that great, but luckily Laravel ships with some default templates.
Switching to markdown templates9:15
There we go, so now everything is aligned properly. So this doesn't look that great, but luckily Laravel ships with some default templates that we can use, which will make it look a lot nicer. So let's switch back to our editor, and first let's go into our blade file, and let's remove all this HTML boilerplate. Instead, we'll use markdown for some of our elements. So we can reference a default component by using the @component directive. We'll enter the mail namespace, and we'll want to render the message components. All the way to the bottom, we will add the components. So now if we switch back to our browser and refresh, you will get an error, no hint at
All the way to the bottom, we will add the components. So now if we switch back to our browser and refresh, you will get an error, no hint at the final email. This is because we have switched to a markdown style syntax, which is required in order for the components to render. So if you go back to our OrderConfirmation mailable, all we have to do is change the view to markdown. Now if you refresh, you can see this is already looking a lot more better. Now $name is rendered correctly, but then you see all the HTML is currently escaped. So if we switch back to our blade file, we need to make sure that we put everything at
Now hey name is rendered correctly, but then you see all the HTML is currently escaped. So if we switch back to our blade file, we need to make sure that we put everything at the start, so we don't want to use any tabs when we want to actually render HTML. So if you grab this table and move to the left, this will render as HTML. We can remove the paragraph tags because markdown will automatically render these as paragraphs because there's a space between them. Now if we refresh, you can see that this is already looking better. Make sure in your order you can see that this line of text is still not rendered correctly, so let's move this to the start. Okay, that looks better.
so let's move this to the start. Okay, that looks better. Let's make sure that our table is utilizing the entire width. Okay, so you can continue on and use HTML to style this table, but we can also look at an alternative approach and use markdown for our table as well. So you can choose. You can either continue styling this table using CSS, or you can move to the next video and we'll use markdown to render the table instead, and this will automatically inherit some of the styles that get applied by the default boilerplate that Laravel provides.
some of the styles that get applied by the default boilerplate that Laravel provides.
