获取包含所有属性的 Laravel 模型

36

有没有一种方法可以在Laravel中检索一个模型的所有属性,即使它们为null也是如此?它似乎只返回那些不为null的属性。

原因是我有一个函数,它将更新模型属性从一个数组中,如果该属性存在于模型中。我使用property_exists()函数来检查模型是否具有特定属性,然后设置它。预期数组键和模型属性匹配,所以它的工作方式就是这样。

如果模型已经设置了属性,它会正常工作,因为属性存在并从数组中获取值。但是如果属性先前为null,则不会更新或设置任何内容,因为它无法通过property_exists() 检查。

最终发生的是,我有一个属性的单个数组,然后可能有两个模型。我运行我的setter函数,传递属性数组和每个对象分别调用。如果模型具有匹配的属性,则它将被更新。

6个回答

37

以下是两种方法。一种方法是在模型中定义默认属性值。

protected $attributes = ['column1' => null, 'column2' => 2];

然后,您可以使用getAttributes()方法获取模型的属性。

如果您不想设置默认属性,我写了一个快速方法应该可以解决问题。

public function getAllAttributes()
{
    $columns = $this->getFillable();
    // Another option is to get all columns for the table like so:
    // $columns = \Schema::getColumnListing($this->table);
    // but it's safer to just get the fillable fields

    $attributes = $this->getAttributes();

    foreach ($columns as $column)
    {
        if (!array_key_exists($column, $attributes))
        {
            $attributes[$column] = null;
        }
    }
    return $attributes;
}
基本上,如果属性没有被设置,这将向该属性附加一个空值并将其作为数组返回给您。

如果目标是将空值设置为null,最简单的方法是在迁移中将->nullable()附加到字段。您无需编写新方法或在模型中设置它。话虽如此,这两个都不应该是必要的。 - tam5
目标是让他在属性尚未设置时能够获取所有属性,而唯一的方法就是将值设置为null(或其他默认值)。 - Thomas Kim
3
至少,因为我们看不到任何代码,我假设他正在使用一个空实例,因为他说“getAttributes()”无法工作。例如,像$user = new User; $user->getAttributes();这样的东西将不会返回属性,因为它没有设置。 - Thomas Kim
啊,确实如你所说,如果他正在调用 new User;,我会更新我的答案以在这种情况下与你不同。 - tam5
谢谢!这让我朝着正确的方向前进了。实际上,我并不需要模型上的每个属性。只需要更新一些精选属性,巧合的是,当我考虑时它们也在$fillable数组中。因此,我实际上可以使用$fillable来检查模型是否应该具有该属性。 - kenshin9

28
$model->getAttributes();

以上将返回原始属性数组(存储在数据库表中)

$model->toArray() 
以上将返回模型的所有原始、修改(如果已使用)和附加属性。 希望这有所帮助!

如果您想要类似于$model->getAttributes()的效果,但是带有类型转换等应用,则$model->attributesToArray()是一个不错的选择(因此没有关联)。$model->toArray()也可以,但它还会递归地运行toArray()在任何已加载的关联上,并将其包括在内。 - iamacarpet

1

更新:

如果您在像这样实例化之后尝试执行此操作:

$model = new Model;

如果不是,请参考Thomas Kim的答案。
否则: 您可以在模型实例上使用 toArray() getArributes()方法,它将返回包括null在内的所有属性。然后您可以使用 array_key_exists 进行检查。
像这样:
if (array_key_exists('foo', $model->getAttributes())) {
    $model->foo = 'new value';
}

我尝试实例化一个新模型,但在尝试其中任何一个函数时,我都得到了一个空数组。虽然我认为这应该是可以预料的。至少从getAttributes()的文档中来看,它说“获取模型上所有当前属性”。 - kenshin9
你是在你的项目中实例化还是只在 Tinker 中实例化? - tam5
抱歉,我没有想到要提到这一点。我确实在我的项目中实例化了它。 - kenshin9
很奇怪,对我来说它可以工作。你能发一下你的代码吗? - tam5

1
我在另一个项目中有这个片段,可以加载所有模型属性和关系。
public function forModel($with)
{
    $this->load($with);

    $attributes = $this->toArray();

    // Normalize Null Relation To Empty Model
    foreach ($attributes as $key => $value) {
        if (
            is_null($value) && 
            method_exists($this, Str::camel($key)) && 
            $this->{Str::camel($key)}() instanceOf \Illuminate\Database\Eloquent\Relations\Relation
        ) {

            $relation = $this->{Str::camel($key)}();
            $model = $relation->getModel();
            $attributesForRelation = $model->getAttributes();
            foreach ($model->getFillable() as $column)
            {
                if (! array_key_exists($column, $attributesForRelation))
                {
                    $attributesForRelation[$column] = null;
                }
            }

            $attributes[$key] = $attributesForRelation;
        } else {
            $attributes[$key] = $value;
        }
    }

    return $attributes;
}

0
如果您明确声明要返回的所有字段,会怎样呢?
public function getSomeModelFromArray(Request $request)
{
    // This will only give back the columns/attributes that have data.
    // NULL values will be omitted doing it this way.
    //$model = $request->all();

    // However by declaring all the attributes I want I can get back 
    // columns even if the value is null. Additional filtering can be 
    // added on if you still want/need to massage the data.
    $model = $request->all([
        'id',
        'attr1',
        'attr2',
        'attr3',
        //...
    ]);

    //...

    return $model;
}

这是一个相当通用的例子,但希望有人会发现它有用。


0

这对我有用:

$attributes = new App\Models\NameModel();
$attributes->getFillable();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接