Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

muuucho's avatar
Level 11

Larvel8 using mutator when validation in a Request class

I like to add a mutator that changes any comma to a dot in a text input posted from a form. However, I don't understand how to call the element with the key of "weight_can" I try to achieve it in a mutator in my model called "setWeigtCanAttribute" that should handle $weigt_can from my form. The result is I get a failed validation error (The weight can must be a number.) of "weight_can" when I pass in e.g. "4,2" hoping that the mutator will turn it into "4,2" Model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    protected $fillable = ['title_must', 'body', 'age_can', 'age_must', 'weight_can'];
    public $timestamps = false;

    public function setWeigtCanAttribute($weight_can){
        $request->post['weight_can'] = str_replace(',', '.', $request->post['weight_can']);
    }
}

PostRequest:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    protected $fillable = ['title_must', 'body', 'age_can', 'age_must', 'weight_can'];
    public $timestamps = false;

    public function setWeigtCanAttribute($weight_can){
        $request->post['weight_can'] = str_replace(',', '.', $request->post['weight_can']);
    }
}

Controller:

<?php

namespace App\Http\Controllers;

use App\Http\Requests\PostRequest;
use App\Models\Post;


class PostController extends Controller
{
    public function index()
    {
        $posts = Post::all();
        return view('posts.index', compact('posts'));
    }

    public function create()
    {
        return view('posts.form')->withPost(new Post());
    }

    /**
     * Store a new post.
     *
     * @param \App\Http\Requests\PostRequest $request
     * @return Illuminate\Http\Response
     */

    public function store(PostRequest $request) // Inject the PostRequest
    {
        // return $request->all();
        // return $request->post('weight_can');
        Post::create($request->validated());
        return redirect('/home')->with('success', 'Post created successfully!');
    }

    public function show(Post $post)
    {
        return view('posts.show', compact('post'));
    }

    public function edit(Post $post)
    {
        return view('posts.form', compact('post'));
    }

    public function update(PostRequest $request, Post $post) // Inject the PostRequest and the Post (found with Laravel "id convention")
    {
        // return $request->all();
        $post->update($request->validated());
        return redirect('/home')->with('success', 'Post updated successfully!');
    }

    public function destroy(Post $post)
    {
        $post->delete();
        return redirect('/home')->with('success', 'Post deleted successfully!');
    }
}

View:

@extends('layouts.app')
@section('content')
    <?php #dd($post);?>
    <div class="container">
        <div class="row justify-content-center mt-5">
            <div class="col-6">
                @if (session('status'))
                    <div class="alert alert-success mb-3" role="alert">
                        {{ session('status') }}
                    </div>
                @endif
            </div>
        </div>
        <div class="row justify-content-center">
            <div class="col-4">
                @isset($post->id)
                    <h4>Edit Item</h4>
                @else
                    <h4>New Item</h4>
                @endif
            </div>
            <div class="col-2">
                <a class="btn btn-outline-secondary float-right" href="/home" role="button">Cancel</a>
            </div>
        </div>
        <div class="row justify-content-center">
            <div class="col-6">
                @isset($post->id)
                    <form method="post" action="/post/{{ $post->id }}">
                        @method('PUT')
                @else
                    <form method="post" action="/post">
                @endif
                        @csrf
                        <div class="form-group">
                            <label for="title">Title must</label>
                            <input type="text" class="form-control" name="title_must" value="{{ old('title_must', $post->title_must) }}"
                                   id="title_must">
                            @error('title_must')<span class="text-danger">{{ $message }}</span>@enderror
                        </div>
                        <div class="form-group">
                            <label for="body">Body</label>
                            <textarea class="form-control" name="body" id="body"
                                      rows="3">{{ old('body', $post->body) }}</textarea>
                            @error('body')<span class="text-danger">{{ $message }}</span>@enderror
                        </div>
                        <div class="form-group">
                            <label for="title">Age can</label>
                            <input type="text" class="form-control" name="age_can" value="{{ old('age_can', $post->age_can) }}"
                                   id="age_can">
                            @error('age_can')<span class="text-danger">{{ $message }}</span>@enderror
                        </div>
                        <div class="form-group">
                            <label for="title">Age must</label>
                            <input type="text" class="form-control" name="age_must" value="{{ old('age_must', $post->age_must) }}"
                                   id="age_must">
                            @error('age_must')<span class="text-danger">{{ $message }}</span>@enderror
                        </div>
                        <div class="form-group">
                            <label for="title">Weight can</label>
                            <input type="text" class="form-control" name="weight_can" value="{{ old('weight_can', $post->weight_can) }}"
                                   id="weight_can">
                            @error('weight_can')<span class="text-danger">{{ $message }}</span>@enderror
                        </div>
                        <div class="mt-3">
                            <button type="submit" class="btn btn-primary">Save</button>
                        </div>
                    </form>
            </div>
        </div>
    </div>
@endsection
0 likes
8 replies
Nakov's avatar

You are missing an h in your method: so setWeigtCanAttribute should be setWeightCanAttribute right?

And then you need to set the attribute on the model, not on the request:

$this->attributes['weight_can'] = str_replace(',', '.', $request->post['weight_can']);
muuucho's avatar
Level 11

@Nakov Got the typo right now, thanks. However, I still get the same validation error after implementing your code suggestion.

muuucho's avatar
Level 11

@Nakov Thanks, but I need to validate it AND change it before I can insert it in my DB as a float. And I find it strange that I can't use mutator when I validate in my PostRequset class. That should mean that the approach with a separate validation class has limitations.

Nakov's avatar

@muuucho but the mutator happens just before you store it, it does not happen before it is validated.

so in the mutator itself you can add a validation logic which will throw an exception maybe.

muuucho's avatar
Level 11

@Nakov Thanks, I got it. There is no way to string replace before validation, so I must let it through the normal validation and then string replace it in the mutator and then validate float there. My problem is that I have no idea how to do it. It is strange that there are no solutions on Google since many countries separate dollar from cent using a comma instead of a dot. So I am surprised that there are no examples ut there. It would be very helpful if you could show me a simple example where a mutator creates an error and redirects back to the form.

Edit I like to be able to enter the following examples to the form: 10000,1 So, there are no thousand separators to worry about. So in the DB 1000.1 should be stored.

mabdullahsari's avatar
Level 16

@muuucho You can "massage" the data in the prepareForValidation method in your FormRequests.

1 like

Please or to participate in this conversation.