DARK MODE 

Posted on Monday, May 30, 2022 by

Create Instagram Clone with Laravel (Part 9): Upload, Save, and Display Image

In this post, I covered from minute 2:07:44 until 2:19:19 of this video.

In previous part, we are able to create a new post. However the path of the image uploaded is incorrect. Let's go ahead and fix that.

20
21
22
23
24
25
26
27
28
29
30
31
32
    public function store()
    {
        $data = request()->validate([
            'caption' => 'required',
            'image' => 'required|image',
        ]);

        dd(request('image')->store('uploads', 'public'));

        auth()->user()->posts()->create($data);

        dd(request()->all());
    }
app > Http > Controllers > ProfilesController.php

Explanation of code above:

For uploaded file, Laravel will wrap it in UploadedFile class. This will add a lot functionality like for example, we can simply call a store method on it and pass in where we want to store our file. For the store method, the first parameter is the path where you want to store it. For now, we want to upload it to uploads folder. This folder is non-existent yet so we're gonna create one later. And the second parameter is what driver or disk we want to use. If you take a look at config > filesystem.php, there are some driver that we can choose. In our case, we just want to store the image in the public directory, so we use public.

UploadedFile class when use dd(request('image');

configure > filesystem.php

When we run with the full code, you will get the file path and the image will be uploaded to storage > app > public > uploads folder






Yay, we able to store the image! However, the folder where the image is uploaded to is not accessible to the public. When you try to access it via direct link, you will get a 404 error.


For solving this, we need to tell Laravel to link those files that are inside our storage. To do that, we write the command php artisan storage:link. What it does, it creates a symbolic link between "public/storage" (public directory) to "storage/app/public" (where the files actually stored). Remember, public directory is what actually accessible to the public, nothing else is accessible. Now, we can finally view the image. Don't forget to put /storage/ in the link. We can just use /upload/ instead of /storage/upload/ but the instructor said that we are not gonna do that for this project.





Let's get rid of die dump, store the image path to a new variable. Now that we have image path, we then need to adjust the create post code. Lastly, redirect the user to profile page after the post has been created.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    public function store()
    {
        $data = request()->validate([
            'caption' => 'required',
            'image' => 'required|image',
        ]);

        $imagePath = request('image')->store('uploads', 'public');

        auth()->user()->posts()->create([
            'caption' => $data['caption'],
            'image' => $imagePath

        ]);

        return redirect('/profile/' . auth()->user()->id);
    }
app > Http > Controllers > ProfilesController.php




Right now, we should be able to create post and be redirected to our profile page after that. However, we haven't worked on our view yet. Let's remove the lines of code where we put some images in our profile just to see how the profile should look like and replace it with the code that grabs the data from table. Don't forget to also edit the Add New Post link and change the hardcoded text in post count.

10
11
12
13
            <div class="d-flex justify-content-between align-items-baseline">
                <h2 class="font-weight-light">{{ $user->username }}</h2>
                <a href="/p/create">Add New Post</a>
            </div>
14
15
16
17
18
            <div class="d-flex pt-4">
                <div class="pr-5"><strong>{{ $user->posts->count() }}</strong> posts</div>
                <div class="pr-5"><strong>165</strong> followers</div>
                <div class="pr-5"><strong>176</strong> following</div>
            </div>
24
25
26
27
28
29
30
    <div class="row pt-5">
        @foreach($user->posts as $post)
        <div class="col-4">
            <img src="/storage/{{ $post->image }}" class="w-100">
        </div>
        @endforeach
    </div>
resources > views > profiles > index.blade.php



We successfully grab data from table. As you can see, there's a lot of broken images. Let's empty the Post table in order to fix this. Enter tinker and run Post::truncate();

The problem is fixed but you need to create a new post again. Try adding several different images. You will notice there are three problems. Problem one, the post is sorted from oldest to newest. Second problem is when we uploaded an image with aspect ratio other than 1:1, it doesn't resize the image to 1:1. Third, the rows need some spacing as it's too close to each other.




To fix the post order, simply added below code in User model.

45
46
47
48
    public function posts()
    {
        return $this->hasMany(Post::class)->orderBy('created_at', 'DESC');
    }
app > Models > User.php

To understand better how we come up with the above code, go to 2021_12_31_023812_create_posts_table.php. Highlight the word timestamp and press F12. Blueprint.php will open up and you can see below code in the file. You can see that the timestamp method created two additional fields, created at and updated at. They are nullable but are updated automatically for us in the database. That's the feature of Laravel.


For fixing the spacing issue, simply add padding bottom of 4.

25
26
27
28
29
        @foreach($user->posts as $post)
        <div class="col-4 pb-4">
            <img src="/storage/{{ $post->image }}" class="w-100">
        </div>
        @endforeach
resources > views > profiles > index.blade.php

Final look :


That's all for part 9. In the next part, we will learn to resize the image with Intervention.







No comments:

Post a Comment