【问题标题】:Only User Model is saving with empty Values to database只有用户模型将空值保存到数据库
【发布时间】:2017-09-01 02:57:04
【问题描述】:

在 Laravel 5.4 中,当我尝试将用户模型保存到数据库时,值不会保存。我也设置了可填充属性。

它在 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']
        ]);

然后会调用BaseModel的create方法,下面是它的代码。

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);
}

【问题讨论】:

  • 问题是什么?
  • 向我们展示如何保存代码
  • 在用户模型中一切正常(没有特征)。您可以使用 try-catch 块来捕获堆栈跟踪错误,并与我们分享结果。
  • @SteD 在我的问题中提到了它。我如何保存用户。
  • 当您致电$user = $this->model->create 时,$this 是什么?

标签: php laravel eloquent laravel-5.4


【解决方案1】:

原因很可能是 Laravel 5.4 中称为“请求清理中间件”的新中间件,如 https://laravel.com/docs/5.4/releases 中所述。

在 app/Http/kernel.php 中禁用 \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, 看看你会得到什么。

您还可以检查 /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);

如果字段可以为空,请在您的迁移文件 f.ex 中注明。 $table->string('all')->nullable();

如果完成,只需运行 $user->save();

【讨论】:

  • 事实并非如此。中间件并非如此。上面的代码适用于所有其他模型。只是遇到用户模型的问题。
【解决方案2】:

从 5.4 开始,create() 函数不再在 Illuminate\Database\Eloquent\Model 中定义:

作为动态方法调用处理,即通过调用这些函数之一(取决于它是否被静态调用):

public static function __callStatic($method, $parameters)
// or
public function __call($method, $parameters)

Illuminate\Database\Eloquent\Model 类中。

现在我没有你所有的代码,但是恕我直言,我会尝试在你的 BaseModel 类中更改这一行:

return parent::query()->create($attributes);

到这里:

return $model->create($attributes);

或者,对我来说更好的是:

return (new static)->newQuery()->create($attributes);

【讨论】:

  • 当我使用 $model->create() 时,它只会调用该模型 baseModel 函数,而不是 Laravel 照明。另一种选择不适用于用户模型。
  • 请尝试最后一个
  • 试过但没有成功。我想这是 CanResetPasswordContract 的情况。如果我没有实现它,上面的代码将起作用。
【解决方案3】:

documentation 它说:

$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 是什么,但应该是文档中示例中的模型。

为什么不使用资源控制器?或者,如果您需要填充数据库,请使用播种机 我认为它会更容易管理。

【讨论】:

  • 我不想这样做。因为我正在记录每个活动,所以我只需要绕过它 baseModel 。它正在与其他模型一起使用,但问题仅在于用户模型。
  • @ViralSolani 你能发布更多代码,只是为了了解$this 是什么?
【解决方案4】:

所以我可以考虑两件事

第一个没有必要使用

受保护的 $guarded = [];

受保护的 $fillable = [];

Guarded 将假定所有内容都可填充,如果其不在此处,而 fillable 将假定所有内容均已保护,除非在此处。

引用文档

虽然 $fillable 用作应可批量分配的属性的“白名单”,但您也可以选择使用 $guarded。 $guarded 属性应包含您不希望被大量分配的属性数组。不在数组中的所有其他属性都可以批量分配。因此,$guarded 功能类似于“黑名单”。当然,您应该使用 $fillable 或 $guarded - 不能同时使用。

第二次排除任何 $this->model 东西尝试先实例化类并保存它们

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();

【讨论】:

  • 我不想这样做。因为我正在记录每个活动,所以我只需要绕过它 baseModel 。它正在与其他模型一起使用,但问题仅在于用户模型。
【解决方案5】:

伙计们,我可以使用 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 上添加了构造,这也会导致问题。所以如果我删除它,一切都会像以前一样工作。

【讨论】:

    【解决方案6】:

    是的,你不能在 Traits 中使用 __construct 方法。

    有关 trait 的更多详细信息,请参阅 PHP.net,他们说“在 __construct 方法(可能还有其他魔术方法)上使用 AS 真的非常糟糕。”

    你可以像下面这样使用 trait。

    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

    请尝试一下,如果它不起作用,请告诉我。 谢谢

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-07
      • 1970-01-01
      • 2021-08-22
      • 1970-01-01
      • 1970-01-01
      • 2019-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多