Okay, guys, I think that next up we can implement this show action that should display one single
blog post.
So we've got the list of the recent blog posts already, and I think that we can create a link that
will display one single blog post together with a comment.
That should be pretty interesting.
We've already got the controller, so let me list the steps.
So we need to fetch the blog post.
Now if it's non-existing.
So for whatever reason the link is incorrect, then we would need to display a not found page and then
we need to load any comments if there are any related to this blog post, obviously.
Next up we should increment the view number.
So we are counting the views of every single blog post and this would be pretty simple With every single
visit, we just increment the counter by one.
And finally we render the blog post with the comments.
So the first part is pretty easy to do.
We've got the post model which just has the find method, and we can just pass the ID and get the post.
So the step number two if the post variable is falsy, which probably means it's just null and that
means the post wasn't found, we should use the router class and just return a not found response.
Now I'm not seeing a static not found method and I think we would need that.
I don't see us creating the router instance just for that.
Just to return a 404 response.
Let's find the not found method.
There it is.
For some reason it's not static, so we need to create an object first.
We can change that.
However let's see what are the references to it.
So it means where is it used.
We can quickly see on the right in the results.
It's just used inside this patch method.
That means I can make it static.
So I'm going to make it static.
And in this place.
I'm just going to do static not found.
And by changing this I can now call this method inside my controller action.
Now as you see this returns the not found text.
So while we are here, why don't we just fix this?
So instead I think we should just echo something else.
I think we should use the view class instead and its static render method, and render one of the errors.
This is 404.
In this case, let's skip the layout.
The exit should stay as we want to make sure that's the last thing that is run in this script.
We don't have this view.
Let's create it quickly.
So inside the errors let's make 404 PHP.
And this should just have a header that can say 404 page not found.
We can also say the page you are looking for could not be found.
And as a last thing, there should be some way to recover.
That means I'm going to add a link to a home page that will say Return To home page.
Okay, now let's go back to the router.
And now to the post controller.
We've got that solved.
The next step is to load the comments.
Okay.
So we won't be loading all the comments and then filtering for this specific post ID.
As all the comments have the post ID column, we could do that.
That would be very ineffective though.
We might have maybe thousands or even hundreds of thousands of comments in our system.
And the most effective way to fetch the comments for this post is to do it on the query level.
This means I will use the comment model, but instead we need another method we can call it for posts
and just pass the post ID it's non-existing.
We need to add it.
Let's add it right away so it won't be very complicated.
It's static code for post accepting an ID.
Let's not worry about the types yet.
We can figure this out later on.
And it returns an array.
Now we need to write a query.
But first we need to get access to the database.
So we use app get database.
And recently we have modified the fetch all method of the database class.
So it gives us some interesting possibilities out of the box.
So let me write the query.
We did that before.
We fetch all columns from comments table, we add some filters using the where statement and we check
if the post ID is the question mark.
So we're going to be using the prepared statements.
We also want to order those comments by createdat date using descending order.
Nothing fancy here.
We just want to have the comments that have the post ID set to our post.
We are passing the parameters in the specific order.
We've just got one single parameter here, and this third parameter of fetch all optional.
One is which class should we use?
Well, we should use the current class, which is the comment.
And finally we just need to return that.
Okay we can go back.
And here we just got the comments.
Next up we need to increment the view count.
I think we can also add new methods to the post model.
Let me call this increment views and we are just passing the model ID.
So this method does not exist.
We need to add it.
So we are jumping to the post and we are adding it.
So this is public static function.
So a public static method called increment views.
And it is accepting an ID and it doesn't return anything.
Or optionally later on we might return the new value of the views.
So first we are getting the database from the container.
Then we are just running a query.
So we are not fetching anything.
Here we are running a query.
This time it would be an update query.
I don't think we've ever run an update query before, and the update query is supposed to change an
existing record in a database table.
So we would like to change the posts table record and the set keyword follows which basically says which
columns should be modified.
We'd like to modify the views column.
How would we like to modify it.
Well I'm going to assign a new value to it, which is the value of the views column plus one.
We can do such things inside SQL.
But the most important thing is to add a where query to say which records do we mean?
Because if we don't add the where query, every single record inside posts will be updated with the
new view count.
Never skip this.
And the ID is.
The prepared statement parameter goes at the end of the query and we pass the value for that parameter,
which is the id.
So nothing is being returned from here.
And this would just update one single post views.
All right.
So we've got this implemented.
Finally we just return the view class render.
Okay.
So the template here is.
The posts show same as the controller plus an action name.
Action is the method.
Then we've got the layout.
This would be layouts forward slash main and the data.
This is an array.
And here we will be having two.
So the post is our post and the comments.
The comments variable semicolon.
And we are almost done because what we are missing is the view for this post controller show action.
So let's add a new folder.
Let's add the post folder inside it, a missing show php file.
And the final step is to just implement this template.
So we might be moving pretty fast, but my goal is to show you how quickly we can move if we have solid
foundations using our own framework.
So let me add an article tag in here and start with H1.
So let's use HTML special characters and get the post title.
The next thing would be the views.
So we've got the views And here we don't think.
I don't think we need to escape anything.
Let's just display the views and then let's add maybe another paragraph.
And here I'd like to do HTML special chars for the post content.
Let me close that.
But additionally I'd like to wrap that with something else.
So I'd like to use NL two BR, which would convert all the new lines that might have been entered using,
for example, a text area input when someone has added the blog post.
So those new lines would be then converted to BR elements, which would be nicely displayed as new lines.
Okay, so that's the article.
Now we need the comments.
Let's just add a section for it.
Let me add an H2 element.
And let's say comments.
We might have more than one comment.
That's why I'm using for each.
So we go over every comments.
Then let me add a close and for each.
And inside we are just displaying this specific comment.
So a paragraph.
And here I'd like to output using also NL to be our HTML special chars.
And we are getting the comment I think it's called content.
So that's the comment content.
Then let's use the small element and just say when this was posted.
So let's say posted on.
And here I'm just using command created at.
In the future we're going to have a link here to the sign in form, because you need to be logged in
to leave a comment.
And if the user would be authenticated already would be signed in.
He would see a form to add his own comment to this post.
I think we are ready to try out this page, but before we do on the home page we.
We are listing the blog posts and I've mentioned that we might wrap this with a link, so let's do that.
So this would be a link and the title would be the link.
So first off this needs to be I think the root is post.
Let's see that.
Yes that's posts.
Okay so this is posts.
And here we need to output the post ID.
Now we are ready to try this out.
Okay.
So we are on the main page.
Let's see how does this work.
Hmm.
Something went wrong.
So PDO statement fetch argument.
Second must be of type int.
Okay so let's jump to database.
PHP.
So the problem is with the fetch method.
As we can see in the stacktrace that we are in the post controller, we are trying to find the model
with id one.
So this has to be post.
And yeah I think I've just mistakenly used the wrong parameters.
So fetch is a little different than fetch.
All I forgot about this And I've assumed that the second argument would be the class name, and that's
not the case.
So I forgot about another method of the statement, which is set fetch mode, where we can well set
the mode depending on whether the class name is passed or not.
So we need to change that.
So if the class name is specified the fetch mode needs to be fetch class.
Otherwise it needs to be fetch associative array.
Then the set fetch mode accepts a second argument which is defaulting to null, and that would be the
class name.
Since our parameter is also defaulting to null, we can just pass it.
If someone would not like to have an object returned from this method, then he can skip this parameter.
So let's leave it like this.
And instead we can just.
I think we can just go statement fetch because everything was already prepared.
Oh, and it seems that I just need to add a semicolon here and instead just call this on the statement
object like that.
Okay, so we are setting the fetch mode.
We are setting the class properly.
We are fetching properly I guess.
Let me refresh that again.
We've got the same problem as with the post with creating dynamic properties that weren't defined.
This means I need to jump to the comment and add all the fields that match the columns.
So we've got Createdat, I think we've got the content and we probably got the post ID.
Let me see if there is anything else.
I just honestly don't remember the other columns, so there is user id and post ID additionally.
Okay, so that's post ID.
Let's also make it a user ID.
So it's time to test.
The first problem that I see here is apparently we don't have a template.
Okay.
Let's take a look at the post controller.
All right I see what the problem is.
So I've assumed that the folder would be called posts and it is post without the s.
Let's quickly fix that.
Not a big problem.
Okay.
Next up we've got some parse error inside the template line 19.
Okay, let's take a look.
Um, yes.
Right.
I probably should use the full BHP starting tag.
Let's refresh.
It's looking better, but.
Hmm.
Okay, we are attempting to read property content on an array on the template on line 14.
The content is read here.
Okay, this makes sense.
I am accessing the array here.
This should be just the comment variable, not comments.
I think it might fix everything.
Okay, so finally everything is looking good.
We've got the content of the post.
I can see that views are increasing every time I refresh.
And then there are some comments.
Let me take a look at another post.
This also looks great and that one also looks great.
Okay, so we are done and I think this wasn't very hard to do.