João Brazete
João Brazete

Reputation: 33

Why my data is not storing in database using eloquent?

My form submit but it isn't storing in the table. If I make dd() on Requests, the data is in, but when I do the save() dont work as expected. I want to add Users on a backoffice form just with Name, Email, Type of user and password.

Edit: I changed the question images to code to be more easier to you, sorry about the first attempt. Edit 2: Now appeared more 2 things, the validate on password_confirmation gives always false, and if I skip the validation gives me this error:

BadMethodCallException Call to undefined method App\User::forget()

Funtion store on Controller:

public function store(Request $request)
    {
        $dados = $request->validate(
            [
                'name'  =>'required|min:2|max:20',
                'email' =>'required|email|unique:App\User,email',
                'password' =>'required|min:8',
                'password_confirmation' =>'confirmed'
            ],
            [
                'required' =>'Os campos têm de ser todos preenchidos!',
                'email' =>'O email tem de ser válido!',
                'unique'=>'O email inserido já está registado!',
                'min.name' =>'O nome tem de ter pelo menos 2 caracteres!',
                'min.password' =>'A password tem de ter no minimo 8 caracteres!',
                'confirmed' =>'As passwords deverão coincidir!'
            ]
        );

        $user = new User;
        $user->forget('password_confirmation');
        $user->fill($request->all());
        $user->save();

        return redirect()->route('utilizadores.index')->with('Success','Utilizador registado com sucesso!');
    }

Route:

Route::resource('/admin/utilizadores', 'UserController');

Model:

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $guarded = [

    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token','password_confirmation'
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

Form:

<div class="modal-body">
            <form action="{{route('utilizadores.store')}}" method="POST" id="adicionarid">
                @csrf
                <input type="email" name="email" class="inputtext data" placeholder="Email">
                <div class="customselect data top1">
                    <select name="tipo">
                        <option value="revisor" selected disabled>Revisor</option>
                        <option value="editor">Editor</option>
                        <option value="revisor">Revisor</option>
                    </select>
                </div>
                <input type="text" name="name" class="inputtext" placeholder="Nome">
                <input type="password" name="password" class="inputtext" placeholder="Palavra-passe">
                <input type="password" name="password_confirmation" class="inputtext" placeholder="Confirmar palavra-passe">
            </form>
        </div>
        <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-dismiss="modal">Fechar</button>
            <button type="submit" class="btn btn-success" form="adicionarid">Guardar</button>
        </div>

Upvotes: 0

Views: 525

Answers (1)

Arun A S
Arun A S

Reputation: 7026

There are a bunch of issues I see in your code. Let's first list them out so you know what you did wrong

'password_confirmation' =>'confirmed'

I'm pretty certain this does not do what you expect it to do. the confirmed validation rule must be used on password, laravel will then automatically check if there is a field called password_confirmation (field_name_confirmation) and check if it is equal to the password field. So your validation rules can be

'password' =>'required|min:8|confirmed',

And no need for a rule on password_confirmation

Next is

$user->forget('password_confirmation');

There's no forget method in eloquent or laravel's query Builder, hence why you get

BadMethodCallException Call to undefined method App\User::forget()

There is forget method on Collections and the Arr::forget() but that's not what you want here. But since you already have $dados, it will be an array containing only the input fields for which you have defined rules in your validator, hence you can use $dados when creating the user (will show how later in the answer)

Next is

$user->fill($request->all());

Never ever do this, because malicious users could add extra fields in the form, such as an id, hence allowing them to modify existing users.

Instead you can do

$user->fill($dados);

Since $dados only contains the fields returned by the validator, it is safer to use.

Another issue I noticed is that you have a field named tipo in the form, but it's not present in the validator, hence you need to add it in the validator.

$dados = $request->validate(
    [
        'name'  =>'required|min:2|max:20',
        'email' =>'required|email|unique:App\User,email',
        'password' =>'required|min:8|confirmed',
        'tipo' =>'required' // Add whatever other validations you need
    ],
    [
        'required' =>'Os campos têm de ser todos preenchidos!',
        'email' =>'O email tem de ser válido!',
        'unique'=>'O email inserido já está registado!',
        'min.name' =>'O nome tem de ter pelo menos 2 caracteres!',
        'min.password' =>'A password tem de ter no minimo 8 caracteres!',
        'confirmed' =>'As passwords deverão coincidir!'
    ]
);

Then you can just do

$user = new User;
$user->fill($dados);
$user->save();

Next issue is that you're not hashing passwords. Unless you want to directly save the users password in the database, you should hash password; Laravel makes hashing simple by providing a Hash class you can use.

$dados['password'] = Hash::make($request->password);

be sure to add the use Illuminate\Support\Facades\Hash; at the top of your file

So overall, with some tweaking your controller should be

public function store(Request $request)
{
    $dados = $request->validate(
        [
            'name'  =>'required|min:2|max:20',
            'email' =>'required|email|unique:App\User,email',
            'password' =>'required|min:8|confirmed',
            'tipo' =>'required' // Add whatever other validations you need
        ],
        [
            'required' =>'Os campos têm de ser todos preenchidos!',
            'email' =>'O email tem de ser válido!',
            'unique'=>'O email inserido já está registado!',
            'name.min' =>'O nome tem de ter pelo menos 2 caracteres!',
            'password.min' =>'A password tem de ter no minimo 8 caracteres!',
        ]
    );

    $dados['password'] = Hash::make($request->password);

    $user = new User;
    $user->fill($dados);
    $user->save();

    return redirect()->route('utilizadores.index')->with('Success','Utilizador registado com sucesso!');
}

And it should do what you were hoping to achieve

Now, lets give you some additional tips.

Always avoid using an empty $guarded

protected $guarded = [

];

It could leave security vulnerabilities (even if you don't expose any such vulnerability, someone else who is careless might, so always try to use $fillable instead, better safe than sorry)

protected $fillable = [
    'name', 'email', 'password', 'tipo'
];

Then in your controller, you can safely use

$user = User::create($dados);

This is a more widely used method than fill(). The $fillable array also ensures that when using the create(), only the attributes inside the $fillable array get saved in the Database

Upvotes: 1

Related Questions