تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Login and Timeline Routes0:00

I originally wanted to create a Post, but I think first we need to display the timeline. The first thing I want to do is change up the log in route because I want to be sure that we have a User that has the things that we need. So we are going to select a User that has an Idea of five because I know that this User has everything that we need. It has some Posts that it has liked as well as reposted. And when it comes to displaying the timeline, we need to be sure that we provide that information.

And when it comes to displaying the timeline, we need to be sure that we provide that information. So this User is what we are going to use. And I'm gonna give this route the name of login. That's what Laravel is expecting, so that anytime that we need to be logged in and it redirects us to the login route, we get logged in. And since we're here, let's just go ahead and let's define the route that we are going to use to display the timeline.

and let's define the route that we are going to use to display the timeline. However, the timeline is for users that are signed in. So we need to ensure that the user is signed in. So we're gonna use the auth middleware, then we will group our routes together so that here we are going to have a route that, uh, let's say that goes to /home.

that here we are going to have a route that, uh, let's say that goes to /home. I know that we've been using /feed, but that's primarily just to, you know, display what we expect the feed to look like. /home is the URL that's typically used. So we'll have home, which is going to route to the PostController because it's for displaying our posts. And in this case we'll use the index method.

Planning Controller Index1:38

because it's for displaying our posts. And in this case we'll use the index method because I think that that makes sense. This is the index of showing our posts. And let's give this a name of posts.index. Alright, so with that in place, we just need to implement that method. So let's go to our PostController and let's define that index route. And I want to do something a little bit different in this

and let's define that index route. And I want to do something a little bit different in this particular case because the query is going to be a little involved because not only do we have to select all of the posts and well we, we select all of the posts of the profile and the profiles that the profile is following. That is so confusing. Uh, anyway, not only do we need to select that information, but we also need to know if the profile fire

Uh, anyway, not only do we need to select that information, but we also need to know if the profile fire pro fire, let, let's call it the viewer. Okay? So we need to also load the information as to whether the viewer has liked or reposted a particular post. So it's a little involved. I don't want to have a method that's, you know, several lines long. I know that we have that here.

several lines long. I know that we have that here and maybe we will need to come back and clean that stuff up. But this is what I'm envisioning. So we will get to the User's profile so that then we could do something like this. We'll get our posts and we won't directly use our Post model. Instead we'll have something like a timeline query for a given viewer.

Instead we'll have something like a timeline query for a given viewer and then we can provide the profile that we wanted to, you know, get the timeline for. And then we could call get, or maybe paginate or something along those lines. You know, either way, eventually we will want to paginate everything, but if we call get, then we at least get everything so that we can look at it. And then finally we would return that view of posts.

Creating Posts Index View3:32

then we at least get everything so that we can look at it. And then finally we would return that view of posts index passing in the posts that we would want to display. So that's the basic idea, but we need to create that timeline query. And before we do that, let's go ahead and create this view for our posts. So inside of resources, it's not a component. We have posts, we have show here. So let's copy that and let's rename it to index.blade.php.

We have posts, we have show here. So let's copy that and let's rename it to index.blade.php. But it's not necessarily going to be showing like it was. Instead let's take what we have for the feed and let's use that because the feed also has the post creation form, which is what we are going to need. So this way, you know, instead of including the feed item, we're not gonna call it feed items, we're gonna have posts as item, that's fine, then we can have the X post

we're not gonna call it feed items, we're gonna have posts as item, that's fine, then we can have the X post and then we would provide that item as the post. But you know, it's something that we have done before and I think it was in profiles. Profiles show, you know, here where we check if the post is repost and if it is then we provide the repost to the post component. I'm beginning to think we shouldn't do that,

Updating Post Component4:48

to the PostComponent. I'm beginning to think we shouldn't do that, we should just provide the item here. And then the PostComponent would be responsible for displaying whether or not the original post or the reposted post. That is so confusing. So let's uh, and plus that's misspelled there. So let's very briefly open up our PostComponent and let's make that change.

So let's very briefly open up our PostComponent and let's make that change. We'll say that we'll have a private $post model and we'll just call it $original. The idea being that whenever we call this constructor, I say we call this constructor. When the constructor is called, we'll say that the $original is going to be the $post that was passed to the constructor, but then we will set the $post.

original is going to be the post that was passed to the constructor, but then we will set the post based upon if it's a repost or not. So let's copy that code so that I don't have to retype that and it'll look like this. So that the post will be, if it's a repost and if the content is null, then it's going to be the repost of, otherwise it's going to be the post that was provided. We just need to change the names of the variable there and I think that that's gonna be fine.

We just need to change the names of the variable there and I think that that's gonna be fine. Now the reason why I decided to go ahead and store the original is just in case if we need to come back and we need to, you know, actually show that a profile reposted something. So with that done, that means that when it comes to our new index view, we just need to supply the item and then the appropriate post is going to be displayed in the list.

Building Timeline Query6:23

and then the appropriate Post is going to be displayed in the list. So then all we need to do is just focus on this timeline query. So where do we wanna put this? Uh, wants to be inside of app definitely. So let's create a new file inside of app. It'll be queries and then we'll call it timelineQuery.php. And we of course want the namespace to be app\queries.

and then we'll call it timeline.php. And we of course want the namespace to be App\Queries. Then we will have our class of TimelineQuery. And let's start with the static method that we kind of pseudo coded here. It's called forViewer. So we'll start with public static function forViewer to where we will get to the $profile that we want to work with, we'll call it $viewer in this case. And this is going to return a self

with, we'll call it viewer in this case. And this is going to return a self because all we are going to do is new up a new TimelineQuery passing in the viewer so that then we will have a constructor that accepts the profile, we'll call it viewer. Once again, we're gonna make this public. Do we wanna make this public or do we wanna make it private? Let's make it private. There's no reason to make that publicly available and that's going to be our constructor.

Let's make it private. There's no reason to make that publicly available and that's going to be our constructor if you spell it correctly. Okay, so there we go, that's gonna be our starting point. Now we know that we need a get method so that we can get the results of this particular query. So let's go ahead and define get, we don't need to pass anything to it and it's going to return a collection, but this isn't going to be the only method.

and it's going to return a collection, but this isn't going to be the only method that we will need. We will also need to be able to paginate or paginate, however you pronounce it, I don't know. And in this particular case, we would want the perPage. Let's give it a default value of 20. And this is going to return a lengthAwarePaginator. So this means we're gonna have two methods that are essentially going to return the same set of data.

So this means we're gonna have two methods that are essentially going to return the same set of data. It just might be, you know, well is it technically the same set of data if one's paged and one's not. I guess that's not, but they're gonna use the same query. So really what we're gonna need to do here is call something like a base query, in which case we could paginate or paginate, paginate whatever,

in which case we could paginate or paginate, paginate whatever, and then pass in the perPage. And that would be the general idea there. So that here we would call the base query and then we would get that data. So yeah, let's do that. And the collection that we want to return is the database Eloquent collection. Okay, so now we need that private function

to return is the database Eloquent collection. Okay, so now we need that private function baseQuery, which is going to return a QueryBuilder. And we want the Illuminate\Database\Eloquent\Builder there. And this is where the fun part comes because this is gonna be a little bit involved. The very first thing that we need are all of the IDs of the profiles that the viewer is following. So we will call this followingIDs and we will use the viewer to get the followings.

So we will call this following IDs and we will use the viewer to get the followings and we want to pluck the following profileId, but that's not enough. We also need the ID for this viewer because yes, we want the posts from the profiles that the viewer follows, but we also want the posts from the viewer too. So we will prepend that with the viewerId so we get to all of the IDs of the profiles so

So we will prepend that with the viewerId so we get to all of the IDs of the profiles so that then we can get the posts wherein the profileId is in the following IDs and we want the posts where the parentId is null because we don't really want the replies, we just want the top level posts. And we will pull this information with the profile and the repost of information.

And we will pull this information with the profile and the repost of information. And this is going to look very similar because we want the counts for the repost, which means the replies, the likes, and the reposts. But we also want that information with the profile. But then after that we want the count for the replies, the likes and the reposts. But then this is where things start to get a little tricky

for the replies, the likes and the reposts. But then this is where things start to get a little tricky because now we want to pull in the information as to whether or not the viewer has liked or reposted a Post. But we're gonna have to do this at two different levels because remember that you know, every Post is a Post. It doesn't matter if it's just a normal Post, a repost or a quoted repost, they are still Posts. So we have to take that into account. So we're gonna have some attributes that are just flags, yes

So we have to take that into account. So we're gonna have some attributes that are just flags, yes or no, did the User like this, did the User repost this? You know, things like that. So with exists, let's start with the likes and let's give it an alias as hasLiked. And then our query will look like this to where the profile_id is the viewer_id. So if the viewer has liked the Post, then we're gonna have this attribute called hasLiked and it's gonna be true.

then we're gonna have this attribute called hasLight and it's gonna be true. And really we just need the same thing for the reposts. So reposts has the alias will be hasReposted, and same thing, we want it to where the profileId is the viewerId. So this is going to give us the likes, not not necessarily the likes, it will give us if the viewer has liked or reposted a post. But that doesn't help us for you know, the actual repost

it will give us if the viewer has liked or reposted a Post. But that doesn't help us for you know, the actual repost because remember that that's a completely different Post. So we need to take that into account and be sure that the viewer has liked or reposted the repost of, so we're gonna call this repost of as likedOriginal. Then the query is going to look somewhat similar. So we want the reposts of where hasLikes where the profile_id is the viewer_id.

So we want the reposts of where hasMany likes where the profileId is the viewerId. So it's practically the same thing except that we're doing it now at the level of the repost of, and then we just need to do the same thing for the actual reposts. So let's copy that, we'll paste it in and this will be called repostOriginal. And then we want the reposts and then we will get the latest,

And then we want the reposts and then we will get the latest, then we will return the posts. So it's a little bit involved, it's kind of confusing, there's no kind of about it. It is confusing. So let's just go over it again just so that we understand what's going on here. So we are going to get the posts where the profileId that created the post is in the followings id. We aren't going to get any replies.

that created the post is in the followings id. We aren't going to get any replies and we are gonna pull in the profile and the repost off. We're gonna get the counts, but then we need to get whether or not the viewer liked or reposted the post. So we check for the the current post, but we also need to check the original post if it is a repost. Now one thing to note is that these flags here hasLiked, hasReposted, likeOriginal, repost, original, all of

Now one thing to note is that these flags here has liked, has reposted, like original, repost, original, all of that is going to be on the record itself. So that means if we want really any continuity between a Post or a repost, we need to normalize these things because you know, when it comes time to displaying a Post, once again, if we take a look at the Post component, now you know we're either going to show the Post or we're going to show the repost. So the repost also needs to have these flags.

or we're going to show the repost. So the repost also needs to have these flags. The hasLiked and the hasReposted. So we need to do a little bit of extra work kind of like this to where we will have a function, we'll just call it normalize. We will accept a post and then we are just going to work with that post. We're gonna return here so that if the post is a repost and the content is null, you know, that means

We're gonna return here so that if the post is a repost and the content is null, you know, that means that it is, I'm gonna call it a pure repost. It's not a quote repost. Then we need to say that the repost of has light is equal to the post like original. You see how that's gonna work? Now hopefully that that's clear as to what I was thinking of. We should probably cast that too.

to what I was thinking of. We should probably cast that too. So that then we will do the same thing for the repost. So hasReposted will be equal to the repost original and we need to use Post for our post. Do we? I thought we've already pulled in Post we have. Oh, it's because I haven't returned it dur. So we will return post there so that now if the post is a repost, then we will set the hasLiked

that now if the Post is a repost, then we will set the hasLiked and hasReposted on the repost of, so that is loaded and so that we can use those inside of our views without any issues. Then. So that means that when it comes time to getting the information, we will call the base query, then we will call get, but then we'll call map. And for every Post we will call this normalize passing in the post.

And for every Post we will call this normalize passing in the post. And then that will get us our collection of posts that we can then display and everything should be fine. For the paginate method, we'll call paginates. Then we'll call through, in which case, once again we will call this normalize and then pass in the post. I'm so used to typing $q. There we go. Okay, so that should work.

I'm so used to typing $q. There we go. Okay, so that should work. We can get it, we can paginate it and we are going to get all of our posts so that now take a look at the controller, we are getting our posts, we are passing them on to the view so that if we take a look at the index view, we shouldn't have to change anything else. We should be able to go to /home. That will sign us in. And voila, we see our timeline.

Styling Like/Repost States16:52

We should be able to go to /home. That will sign us in. And voila, we see our timeline. Now we aren't taking into account anything as far as the engagements. So what we need to do is inside of the post view, we need to use our new flags. So that we're gonna do this here. I would like to add a class to the containing div around, you know, the like or the repost, but that throws the styling off.

you know, the like or the repost, but that throws the styling off. So what we're gonna do here is this at class and we're gonna set the textPixel class based upon the Post has liked. That's all we are gonna do. But we're gonna do that for the button. And then we need to do it down here for this span element that has the text. So we'll just paste that in

that has the text. So we'll just paste that in and then we'll just scroll on down to where we find the reposts and we will do the same thing. So that for the button we will have that class. Then we need to find the text for the repost, which is this span element here, and we will have that. So if we take a look inside of the view as we scroll through here, we should see those items light up. And I thought we would've seen one by now,

through here, we should see those items light up. And I thought we would've seen one by now, but uh, okay, here's one. Well, the the repost, it's kind of important. If it's a repost, they didn't like it, they reposted it. Okay, so now we can see that the light has lit up. If we scroll up here, I know that there's a couple of reposts, there's a repost there. So we can see that now the engagements light up based upon if the viewer has liked or reposted those posts.

So we can see that now the engagements light up based upon if the viewer has liked or reposted those posts. And if we scroll up to the top, we have our form for submitting a post. And I think we will tackle that in the next episode.

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