Tony Chan
Tony Chan

Reputation: 309

Wrongly update all the record after calling a function

I am creating an edit function which can edit the posts' caption. Actually, it can successfully update record but it updates all the posts' caption when I just edit one of them. When I submit a edit request, it changed all the post at once.

The project is under Php Laravel and using sqlite for the database management.

PostsController.php

public function update(Post $post){
    auth();
    $userid = auth()->user()->id;
    $postuid = $post->user_id;

    if ($postuid == $userid) {
        $data = request()->validate([
            'caption' => 'required',
        ]);

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

        return redirect("/p/{$post->id}");
    }else return abort('403');
}

Create_posts_table.php

Schema::create('posts', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->unsignedBigInteger('user_id');
        $table->text('caption');
        $table->string('image');
        $table->timestamps();

        $table->index('user_id');
});

create_user_table.php

Schema::create('users', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name');
        $table->string('email')->unique();
        $table->string('username')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
});

Expected: it updates each record if I access to its edit page. Actual: access one of the edit page and update all the record at once.

Upvotes: 3

Views: 281

Answers (3)

Elisha Senoo
Elisha Senoo

Reputation: 3594

Do it this way:

public function update(Post $post){
    auth();
    $userid = auth()->user()->id;
    $postuid = $post->user_id;

    if ($postuid == $userid) {
        $data = request()->validate([
            'caption' => 'required',
        ]);

        // update only the specific post, not all posts belonging to user
        $post->update($data);

        return redirect("/p/{$post->id}");
    }else return abort('403');
}

Upvotes: 2

N69S
N69S

Reputation: 17216

You should not use the method update without some security.

First rule in dev is to never trust client input. For example, if the request contain the input user_id having a value other than the id of the current user, your code will change the owner of the post.

In this case there is no sensitive fields but...

Here is a good example (will explain it in the code):

public function update($postId){ //remove model injection and use the post ID.

    //validate data you can use FormRequest class extention in the method parameters instead
    $data = request()->validate([
        'caption' => 'required',
        'not_required_field' => 'string',
    ]);

    //get the post from the relation of the user, if the post doesnt exist or is not the user's post, it will return a 404 response.
    $user = auth()->user();
    $post = $user->posts()->findOrFail($postId);

    //get the data one variable at a time it's more safe. The input method second parameter is the default to set
    $caption = request()->input('caption');
    $notRequiredField = request()->input('not_required_field', '');

    //now you can update
    $post->caption = $caption;
    $post->not_required_field = $notRequiredField;
    $post->save();

    //result of success
    return redirect("/p/{$post->id}");
}

Dont forget to change {$post} to {$postId} in the route.

Upvotes: -1

Tim Lewis
Tim Lewis

Reputation: 29288

auth()->user()->posts()->update($data); is going to update all posts() that are associated with the current auth()->user(). If you want to update only the current Post, simply do

$post->update($data);

Route Model binding, via Post $post in your function will find a Post instance related to the ID in the URL, so you can simply update that.

Upvotes: 3

Related Questions