Laravel在没有密码输入的情况下提交表单时在数据库中插入随机密码

Laravel在没有密码输入的情况下提交表单时在数据库中插入随机密码

问题描述:

I want to insert random password in database when I submit a form without password input field.

my model User.php

protected $fillable = [
    'email', 'firstname', 'lastname'
];

public function setpasswordAttribute($value)
{
    $this->attributes['password'] = bcrypt($value ?: str_random(10));
}

my controller

public function store(Request $request)
{
    User::create(Request::all());
    return 'test';
}

my database

id
firstname
lastname
password
created_at
updated_at

my error

SQLSTATE[HY000]: General error: 1364 Field 'password' doesn't have a default value 
(SQL: insert into `users` (`email`, `firstname`, `lastname`, `updated_at`, `created_at`)

SQLSTATE[HY000]: General error: 1364 Field 'password' doesn't have a default value (SQL: insert into users (email, firstname, lastname, updated_at, created_at)

You are getting this error because the default create_users_table migration doesn't provide default value to the password field or allow null as value.

when you call

User::create($request->all()); 

laravel perform an insert query to the database and because the password is not set, MySQL will return the `SQLSTATE[HY000]

You can solve that by modifying the create_users_table migration which came by default with a new created laravel project,

  Schema::create('users', function (Blueprint $table) {
        // other table columns goes here
        $table->string('password')->nullable();
        // OR 
        $table->string('password')->default("");
        // other table columns goes here
  });

this will allow you to create new User without provide a password and that column will be set to "" or left empty depending with the method you use to modify the migration like I suggest

Secondly defyning the setPasswordAttribute on your model doesn't means when you create a new user without password it will set automaticaly a password on that, you can do that by catching the creating event before inserting the user in the database.

to do that add this in you EventServiceProvider

class EventServiceProvider extends ServiceProvider
{

    /**
    * Register any events for your application.
    *
    * @return void
    */
    public function boot()
    {
        parent::boot();
        User::creating(function($user){
            if($user->password === "" || empty($user->password)){
                $user->password  = bcrypt(str_random(10));;
            }
        })

    }
}

this event is trigger before the user is persiste in the database, and that will allow you to make some modification on all attributes that are allready set on the user you want to persiste in the database

The problem is at your controller: the User::create(Request::all()); has not a password parameter and the mysql gives the correct error: 'password' doesn't have a default value.

This is something you can do about it:

public function store(Request $request)
{
    $input = Request::all();
    $input[password] = $input[password] ? $input[password] : bcrypt(str_random(10))
    User::create(Request::all());
    return 'test';
}

Check for password input in your request and if it doesn't exist, just fake it:

public function store(Request $request)
{
    if (!$request->has('password')) {
        $password = str_random(8);
        $request->request->add(['password' => bcrypt($password)]);
    }
    User::create($request->all());
    return 'test';
}

Your method name should be setPasswordAttribute not setpasswordAttribute.