Только модель пользователя сохраняет с пустыми значениями в базе данных
В Laravel 5.4, когда я пытаюсь сохранить модель User в базе данных, значения не сохраняются. Я также установил свойство fillable.
Он работал в Laravel 5.3. Эта проблема возникает после обновления приложения в Laravel 5.4.
Ниже представлена модель пользователя.
class User extends BaseModel implements AuthenticatableContract, CanResetPasswordContract, JWTSubject
{
use SoftDeletes,
UserAccess,
UserAttribute,
UserRelationship,
Authenticatable,
CanResetPassword,
Notifiable;
/**
* Database Table
*
* @var string
*/
protected $table = "users";
/**
* The attributes that are not mass assignable.
*
* @var array
*/
protected $guarded = ['id'];
/**
* Fillable Form Fields
*
* @var array
*/
protected $fillable = [
'name',
'first_name',
'last_name',
'email',
'password',
'status',
'confirmed',
'api_user',
'confirmation_code',
'account_id',
'role_id',
'cw_contact_id',
'all',
'all_locations',
'username',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = ['password', 'remember_token'];
/**
* Select HTML Preference
*
* @var string
*/
protected static $selectHTMLFormat = "[email]";
/**
* @var array
*/
protected $dates = ['deleted_at', 'last_login'];
}
Обратите внимание, что проблема связана только с моделью пользователя.
Я сохраняю пользователя, как показано ниже.
// Create User
$user = $this->model->create([
'first_name' => $input['first_name'],
'last_name' => $input['last_name'],
'username' => $input['username'],
'email' => $input['email'],
'password' => bcrypt($input['password']),
'confirmation_code' => md5(uniqid(mt_rand(), true)),
'confirmed' => 1,
'api_user' => (isset($input['api_user']) ? $input['api_user'] : 0),
'account_id' => $input['account_id'],
'role_id' => (isset($input['role_id']) ? $input['role_id'] : 0),
'all' => (!isset($input['associated-permissions']) || $input['associated-permissions'] == 'all') ? 1 : 0,
'status' => (!isset($input['status']) || $input['status'] ? 1 : 0),
'all_locations' => $input['all_locations']
]);
Затем будет вызываться метод create BaseModel, а ниже - его код.
public static function create(array $attributes = Array())
{
$user = access()->user();
if($user)
{
$attributes['account_id'] = (!isset($attributes['account_id']) ? $user->account->id : $attributes['account_id'] );
}
$childClass = get_called_class();
$model = new $childClass;
$model->runActionLogger(false, 'create');
return parent::query()->create($attributes);
}
Ответы
Ответ 1
Ребята, я могу решить проблему с помощью метода Fill().
public static function create(array $attributes = Array())
{
$user = access()->user();
if($user)
{
$attributes['account_id'] = (!isset($attributes['account_id']) ? $user->account->id : $attributes['account_id'] );
}
$childClass = get_called_class();
$model = new $childClass;
$model->fill($attributes);
$model->save();
$model->runActionLogger($model, 'create');
return $model;
}
Также по ошибке я добавил конструкцию CanResetPassword Trait, которая также вызывает проблему. Поэтому, если я удалю, все будет работать по-прежнему.
Ответ 2
Причиной является, скорее всего, новое промежуточное ПО в Laravel 5.4, называемое "Request Sanitization Middleware", как описано в https://laravel.com/docs/5.4/releases.
Отключить \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
в приложении /Http/kernel.php и посмотреть, что вы получаете.
Вы также можете проверить /config/database.php и настройки подключения mysql: 'strict' => true
, если это так, установите false
.
Хорошей практикой является использование модели для ввода пользователем. В этом случае вместо $user = $this->model->create(...)
заполните модель с помощью
$user = new \App\User($input)
и обновите свои значения там, f.ex.
$user->confirmation_code = md5(uniqid(mt_rand(), true));
и
$user->password = bcrypt($user->password);
Если поля имеют значение NULL, укажите в файле миграции как таковой, f.ex. $table->string('all')->nullable();
Если сделано, просто запустите $user->save();
Ответ 3
В 5.4 функция create()
не более определена в Illuminate\Database\Eloquent\Model
:
Выполняется как вызов динамического метода, то есть путем вызова одной из этих функций (в зависимости от того, вызвана ли она статически или нет):
public static function __callStatic($method, $parameters)
// or
public function __call($method, $parameters)
В классе Illuminate\Database\Eloquent\Model
.
Теперь у меня нет всего кода, но, IMHO, я попытаюсь изменить эту строку в классе BaseModel:
return parent::query()->create($attributes);
:
return $model->create($attributes);
или, еще лучше для меня:
return (new static)->newQuery()->create($attributes);
Ответ 4
В документацияон говорит:
$post = App\Post::find(1);
$comment = $post->comments()->create([
'message' => 'A new comment.',
]);
Итак,
$user = $this->users()->create([
'first_name' => $input['first_name'],
'last_name' => $input['last_name'],
'username' => $input['username'],
'email' => $input['email'],
'password' => bcrypt($input['password']),
'confirmation_code' => md5(uniqid(mt_rand(), true)),
'confirmed' => 1,
'api_user' => (isset($input['api_user']) ? $input['api_user'] : 0),
'account_id' => $input['account_id'],
'role_id' => (isset($input['role_id']) ? $input['role_id'] : 0),
'all' => (!isset($input['associated-permissions']) || $input['associated-permissions'] == 'all') ? 1 : 0,
'status' => (!isset($input['status']) || $input['status'] ? 1 : 0),
'all_locations' => $input['all_locations']
]);
где users()
- ваша публичная функция, но я не знаю, что такое $this
в вашем случае, но должно быть моделью, как в примере из документации.
Почему вы не используете контроллеры ресурсов? Или, если вам нужно заполнить db, используйте сеялку
Я думаю, с ним будет легче справиться.
Ответ 5
Итак, 2 вещи, которые я могу придумать
В-первых, нет необходимости использовать
protected $guarded = [];
и
protected $fillable = [];
Охраненный будет считать, что все заполняется, если его не здесь и заполняемый будет считать, что все охраняется, если только здесь.
Чтобы процитировать документы
В то время как $fillable служит как "белый список" атрибутов, которые должны быть назначены массой, вы также можете использовать $guarded. Свойство $guarded должно содержать массив атрибутов, который вы не хотите назначать массе. Все остальные атрибуты, не входящие в массив, будут назначаться массами. Итак, $охраняемые функции, такие как "черный список". Конечно, вы должны использовать либо $fillable, либо $guarded - не оба.
2nd, чтобы исключить любой из $this- > model stuff, попробуйте сначала создать экземпляр класса и сохранить его
use App\Path\To\Model as user;
$user = new user();
$user->first_name = $input['first_name'];
$user->last_name = $input['last_name'];
$user->username = $input['username'];
$user->email = $input['email'];
$user->password = bcrypt($input['password']);
$user->confirmation_code = md5(uniqid(mt_rand(); true));
$user->confirmed = 1;
$user->api_user = (isset($input['api_user']) ? $input['api_user'] : 0);
$user->account_id = $input['account_id'];
$user->role_id = (isset($input['role_id']) ? $input['role_id'] : 0);
$user->all = (!isset($input['associated-permissions']) || $input['associated-permissions'] == 'all') ? 1 : 0;
$user->status = (!isset($input['status']) || $input['status'] ? 1 : 0);
$user->all_locations = $input['all_locations'];
$user->save();
Ответ 6
Да, вы не можете использовать метод __construct в чертах.
Пожалуйста, обратитесь к PHP.net для получения дополнительной информации о признаке, они сказали: "Использование AS для метода __construct (и, возможно, других магических методов) действительно действительно плохо".
Вы можете использовать черту, как показано ниже.
class User extends BaseModel
{
use userRelation
}
Trait userRelation
{
public function getUserName()
{
return "Jhon Doe";
}
}
Я создал "userRelation" Trait, который содержит несколько полезных кода для повторного использования.
Для получения дополнительной информации см. следующую ссылку - http://php.net/manual/en/language.oop5.traits.php
Пожалуйста, попробуйте и дайте мне знать, если это не сработает.
Благодаря