如何使演员以这种方式工作?

时间:2017-08-07 20:09:46

标签: php laravel eloquent

我正在处理存在复选框的表单,但目标模型的字段必须是布尔类型,因为它们在我的迁移中定义为boolean。例如:

$table->boolean('is_active')->default(true);

模型的值以这种方式填充:

    foreach (static::getFillableFields() as $field) {
        $entry->$field = $request->input($field);
    }

所以我添加了强制转换来使这个字段成为布尔值:

class Entry extends Model
{

    protected $casts = [
        'is_active' => 'boolean',
    ];

但是现在我看到了:当选中表单的复选框并且我在请求中有'1'字符串时,它运行良好 - 当我访问$ entry-> is_active时,'1'给出'true'。但是当未选中复选框时,它会给出'null'值,并且 - 我不知道为什么 - 当模型的字段设置为null时,它返回null(不是'false',正如我预期的那样)。 为什么会这样?这使得演员在我的案例中毫无用处。我可以改变这种行为吗?

我对于为每个布尔字段添加此(访问器/更改器)的想法并没有太多启发(但实际上这会产生我需要的内容):

public function setIsActiveAttribute($value)
{
    $this->attributes['is_active'] = (bool)$value;
}


public function getIsActiveAttribute(bool $value): bool
{
    return $value;
}

3 个答案:

答案 0 :(得分:1)

这是控制器问题,而不是模型问题。如果未选中HTML复选框,则它们没有值,这就是它们的工作方式。

因此,在控制器中从Request对象中检索值时,应将默认值设置为false。

控制器方法示例:

$model->is_active = $request->input('is_active', false);

如果将input()的第二个参数留空,则默认为null。

答案 1 :(得分:1)

正如@Devon所提到的,未检查的复选框不包含在发送到控制器的请求数据中。 HTML规范认为未选中的复选框不成功,因此不提交它们。

用于解决此问题的一个技巧是限制"然而,是为HTML添加一个与您的复选框同名的隐藏输入,但包含false值。这个隐藏的输入必须在输入之前

这将允许您继续使用质量分配功能。

因此,您的表单应该类似于:

<input type="hidden" name="is_active" value="0" />
<input type="checkbox" name="is_active" value="1" />

现在,当使用未选中的复选框提交表单时,隐藏的输入将确保请求数据中存在具有false值(0)的输入值。

当使用选中的复选框提交表单时,两个输入都将成功提交相同的名称,但服务器端将仅采用它看到的最后值。这就是复选框必须位于隐藏输入字段之后的原因,因此服务器看到的最后一个值是复选框(1)上定义的成功值。

作为旁注,这也是Ruby on Rails如何形成帮助程序处理复选框。来自documentation

  

HTML规范说未选中的复选框不成功,因此Web浏览器不会发送它们。不幸的是,这引入了一个问题:如果Invoice模型具有paid标记,并且在编辑付费发票的表单中,用户取消选中其复选框,则不会发送paid参数。所以,任何像

这样的质量分配习语      

@invoice.update(params[:invoice])

     

不会更新旗帜。

     

为防止这种情况,帮助程序会在复选框之前生成一个辅助隐藏字段。隐藏字段具有相同的名称,其属性模仿未选中的复选框。

     

这样,客户端只发送隐藏字段(表示未选中复选框)或两个字段。由于HTML规范说键/值对必须以它们在表单中出现的相同顺序发送,并且参数提取得到查询字符串中任何重复键的最后一次出现,这适用于普通表单。

答案 2 :(得分:0)

突然:强制转换不适用于Model :: save()方法。 laravel eloquent model casts on save?

所以剩下的就是使用访问器/ mutator ..