Intro to Chart.js Charts0:00
Welcome to the Laravel Cookbook. This series will focus on building features you might typically see within a Laravel application. Let's start off with charts or graphs, which is something you would use if you wanted to visualize or analyze your data. There are many graphing libraries out there, but I'm going to make use of chart.js, which is probably the most popular one. So, I do have some starter code in place for a Laravel app. I have Tailwind pulled in, I have a layout with a few pages, and I have an Order model, which we'll take a look at in a second. So, let's start off by making use of chart.js and see if we can render a chart within this page here. So, let's go to the documentation for getting started. It's pretty straightforward. We just need a canvas element. We need to pull in the library here. We can provide a few labels with the corresponding data for those labels, in this case, this array here, and then just provide a
Add Chart.js to Blade0:37
need a canvas element. We need to pull in the library here. We can provide a few labels with the corresponding data for those labels, in this case, this array here, and then just provide a whole bunch of other options like colors and the type of graph we're using. So, let's go ahead and do that. Let's start by pulling it in from the CDN. So, let's grab this. Let's go into our code. And this is the charts.blade.php, which is making use of this app.layout. And within my app.layout, you'll see I have this stack scripts, which we can push to to add our scripts. You can also add it globally if you're using it on multiple pages, but for now, we'll just put it on this charts page. So, we can say push scripts and then add that import here. And then I'll put another one for the actual JavaScript we need to write. So, I'll just put it in line here. So, let's go back. Let's add this canvas element. So, we'll grab this and it says we need to put it within a container,
config. So, let's grab this and let's put it underneath all of this. Okay. So, now if I did that right, we should have the chart rendering within our page. And there it is. Cool. And just so we can fit this chart better on the screen, I'm going to give our container a margin. Let's say mx-40. And now that should be smaller. Okay. So, they are using a line graph here. You can see the corresponding points here. So, zero is the first one and 30 is the last one. I actually think they have too many data points here. You can see 45 is the last one here. But since there's only six labels, it only takes the first six. So, these labels correspond to this data here. So, we don't even need this one here. So, if you wanted to change it to a bar graph, you can do that here. I actually prefer bar graphs most of the time. There it is. You can even have it horizontally if you prefer that way. I believe there's an option called indexAxis. So, we can say index.
Okay, cool. And we can change the label here as well and the color if you like. I'm going to leave the border color out. Let's change this one to say light gray and this one to light green. And how about for our actual data? Let's compare this year's number of orders to last year's. So, this one will be last year's orders or last year orders. And then this one will be this year orders. And I'm also going to add all of the months for the year here. So, let me just paste that in. Okay, let's try that out. And that looks pretty good. Let me just pad the rest of this data here. Okay, let's save that and let's give that a look. Okay, so that looks pretty good. Again, chart.js is pretty extensive. Just take a look at the documentation if you need a certain type of graph or a certain option. But for now, I think our graph is set up. Now we just have to pull in data from our backend. I do have an Order model and all I've added is a total,
Review Seeded Order Data5:08
a certain type of graph or a certain option. But for now, I think our graph is set up. Now we just have to pull in data from our backend. I do have an Order model and all I've added is a total, which you can see here, which we won't make use of now. Like I said, we're just going to count the number of orders per year, but we might make use of it later on. You can also see I have a random created_at timestamp between now and five years ago. And you can see I have 5,000 records seeded. And for users, I also have a random created_at date, and I have 1,000 users here. So, if you take a look at our seeder, you can see 1,000 and 5,000. And for our order factory, you can see I have a random date between five years ago and now. So, if we go back to our Blade view, we kind of have everything set up already. We just need to pass in the correct array here. So, we want the number of orders corresponding to each month. So, four is January, 10 is February,
Write Monthly Counts SQL6:00
view, we kind of have everything set up already. We just need to pass in the correct array here. So, we want the number of orders corresponding to each month. So, four is January, 10 is February, and so on and so forth. So, this will be last year's orders, and we also want this year's orders. So, let's just start with the current year's orders. Let's formulate a query for that, and then we'll pass it in here to our JavaScript. So, how about we write raw SQL for now, and then we'll convert it into Laravel. So, let's go into our SQL Ace. Let's go into query here, and let's go ahead and write a query here. Let's start off by counting everything, and you saw it should be 5,000. So, select count(*) as count, and that should be from orders. Let's run that, and it is 5,000. Let's grab a specific year. So, we want the count for only, say, this year. We can say where. We can use the year method
and that should be from orders. Let's run that, and it is 5,000. Let's grab a specific year. So, we want the count for only, say, this year. We can say where. We can use the year method within MySQL. The field is created_at, and it's 2022. Okay. Let's run that, and we get zero. I think we don't need the quotes here. Okay. Now, like I said, we want a breakdown for each month, and we can make use of the month method within MySQL to do that as well. So, we can say month created_at as month comma. Let's run that. It says we need group by, so let's add that as well. So, group by month. Let's run that, and there is our month with the corresponding count. Let's make sure to order by month as well. So, order by month. So, you can see for every month, we have a corresponding count for our orders. Now, there's only six because currently it's June, but if I were to change the year, say last year, this should have all 12 months, and it does. Cool.
Convert Query to Eloquent7:49
we have a corresponding count for our orders. Now, there's only six because currently it's June, but if I were to change the year, say last year, this should have all 12 months, and it does. Cool. So, this is our query. Let's see if we can get this working within Laravel. Let's just do it from within our routes file, and then maybe we'll move it to a query scope. Let's go to our routes file, and let's do it right here for now. So, let's start with this year's orders. So, this year orders. Let's say order. I'm going to use query here just so I can line everything up, but you don't have to do that. Let's start with the where clause to grab the year. So, this one right here, where year created_at equals the year. Let me just grab this, actually, and paste it within here, but let's comment that out. So, we can make use of the whereYear method to do that. So, the field we're looking at is created_at,
and paste it within here, but let's comment that out. So, we can make use of the whereYear method to do that. So, the field we're looking at is created_at, and we can provide the year here, and we want the current year, so we'll just use the date method and say Y. Now, let's take care of selectMonth created_at as month. So, we can do a selectRaw here, and it's pretty much the same thing. Month created_at as month, and for the other case, we can just duplicate the selectRaw, and this will be count(*) as count, and for the groupBy and orderBy, we can make use of those methods. So, say groupBy the month, and same for orderBy. Okay, let's get this for now, and let's dd it. I believe we can do this. Save that. Let's go into our browser, and let's refresh this.
Okay, let's get this for now, and let's die and dump it. I believe we can do this. Save that. Let's go into our browser, and let's refresh this. Order not found. Let's make sure to import that. Okay, let's try again. Okay, so we do get this array of six, which looks like it's correct. So, if we go into the attributes, we get the month and the count. So, one and 79. Let's make sure that's correct from our raw SQL here. So, let's change this back to 2022, and that is correct. And that is correct. So, we only want these fields here, so we can pluck them out. So, let's say pluck after orderBy. pluck. Let's pluck out the count and the month, and let's see what we get now. And we don't need get anymore, so let's get rid of that.
Pluck. Let's pluck out the count and the month, and let's see what we get now. And we don't need get anymore, so let's get rid of that. Save that. Let's try it again, and now we are getting an array, and this array corresponds to our raw SQL. So, 79, 64, 83, and that is correct. So, again, these indexes correspond to the month. So, one is January, two is February, and so on. But in our case, we just need the values. So, we can grab the values like this. Let's save that, see what we get. Okay, and the indexes are zero based now. And this should be the array we need to pass into our front end. So, let's see if we can do that. Let's get rid of this SQL query, and let's pass in this yearOrders into our Blade view. Or you can use the compact method if you like. Sorry, this should be a string.
Let's get rid of this SQL query, and let's pass in this yearOrders into our Blade view. Or you can use the compact method if you like. Sorry, this should be a string. So, yearOrders is actually still a collection. So, if we dd it, and check it out in the browser, you'll see that it's still a collection, but we do want an array. So, let's change this to an array. Just call the toArray method, and now it should be an array. Okay, so let's get rid of this. Let's go back to our Blade view. Now, we just have to convert that PHP array to a JavaScript array. We can do that in several ways. We can make use of json_encode. So, if I add the double curlies here, you can say json_encode and pass in our variable. So, yearOrders. Or we can make use of JS::from, which does almost the same thing. So, we can say JS::from.
you can say json_encode and pass in our variable. So, this year's orders. Or we can make use of JS::from, which does almost the same thing. So, we can say JS::from. Let's save that. Check it out in the browser. And somewhere down here, you can see encode gives us the actual string. And JS::from gives us json_parse. So, either one works fine. I'll make use of JS::from since it's a few characters less. So, let's grab that to get rid of this. So, this year's orders would go into our JavaScript here. And we can make one for last year's orders as well. But you can see this data does correspond to this year's orders. So, there should be only six for now. So, the green ones should end right here after I refresh. And it does. Cool. And this is the correct data. So, this is January 79. And that is correct. 6483. Cool. So, we can do the same thing for last year's orders as well. So, back to our routes file. We can duplicate this. Let's
Let's go into our query. Change it to last year. And it is. Okay. Let's clean up some of our duplication here. Again, we are duplicating our code here. So, let's move it to a query scope. So, all of this is duplicated. So, let's grab this. How about we call it groupByMonth. And same for this here. Okay. Let's go into our Order model. Let's create that query scope. So, scopeGroupByMonth. That takes in a query. I believe it's of type Builder. And let's just import this. I believe it's this one here. And we can return query and paste that in. Let me just indent this once. Let's save that again. And let's see if this still works. So, back here, if I did everything correctly, this should still work. And it does. Let's move one more thing into a query scope. So, where the year is. Actually, I'll just leave it for now as it is pretty readable here already. How about we finish
And it does. Let's move one more thing into a query scope. So, where the year is. Actually, I'll just leave it for now as it is pretty readable here already. How about we finish off by actually adding the total number of orders for each year. Some are in the view here. So, let's go back here. Let's just put it above the actual chart. So, above our canvas element. Let's put a div here. my-6. And let's say div lastYear. And since we already have the array, we can just say array_sum lastYearOrders. Or you can pass it from the routes file if you want. This is fine. And we can do the same for this year as well. So, let me just change this. Let's save that. Let's give that a try. And that looks pretty good. We have a visual representation of our data using chart.js. Now, what if we wanted our graph to be more dynamic and show information for previous years as well. So, you could do something like adding a query
Plan Dynamic AJAX Charts15:58
representation of our data using chart.js. Now, what if we wanted our graph to be more dynamic and show information for previous years as well. So, you could do something like adding a query string and pulling from that year. So, we can say year equals say 2020. And then the current year will be 2020. And the previous year would be 2019. And that would be fine. But that would still require a full page refresh. So, to make it dynamic, we need to make an AJAX call. And we can do that either using JavaScript. Or if you want to stick to the more Laravel way, you can make use of Livewire. So, we'll take a look at how to do that in the next video. But for now, I will make a commit here for this specific episode. Let's say git add, git commit, say episode one. Let's call it charts and queries.
say episode one. Let's call it charts and queries.
