如何处理 Laravel Eloquent 模型中的嵌套对象?

How to handle nested objects in Laravel Eloquent's models?

我有一个对象,是这样创建的:$object = new Object($datas)

这里,$datas 是一个数组 (来自 API,不是数据库) :

$datas = [
    'prop1' => 'value1',
    'prop2' => 'value2',
    'prop3' => 'value3',
    'nestedObject' => [
        'propa' => 'valuea',
        'propb' => 'valueb',
        'propc' => 'valuec',
    ],
];

如果我什么都不做,$object->nestedObject 就是一个数组。 但是,我希望它是一个实现 NestedObject class.

的对象

为了做到这一点,我为 nestedObject 定义了一个转换 属性 :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Object extends Model
{
    protected $guarded = [];

    protected $casts = [
        'nestedObject' => \App\Casts\NestedObjectCast::class,
    ];
}

和 NestedObjectCast :

<?php

namespace App\Casts;

use App\Models\NestedObject as NestedObjectModel;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use InvalidArgumentException;

class NestedObjectCast implements CastsAttributes
{
    /**
     * Cast the given value.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array  $attributes
     * @return \App\Models\NestedObject
     */
    public function get($model, $key, $value, $attributes)
    {
        if($value !== null) {
            return new NestedObjectModel($value);
        }
    }

    /**
     * Prepare the given value for storage.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  \App\Models\NestedObject $value
     * @param  array  $attributes
     * @return array
     */
    public function set($model, $key, $value, $attributes)
    {
        return [$key => $value];
    }
}

有效! 现在,$object->nestedObject 是 class NestedObject.

的实例

但有些事情困扰着我:在 NestedObjectCast class 中,在 set() 方法中,$value 应该是 NestedObject class 的一个实例(文档是这么说的),但事实并非如此。当我在这个方法中写一个 var_dump() 时,$value 是一个数组或 null。

所以,很明显,即使它能工作,我的代码也有问题,但是呢???
此外,令我感到有些惊讶的是,我必须编写一个 NestedObjectCast class 来执行如此简单的操作。 有another/better方法吗?

如果你想通过命令 $object = new Obj($datas); 获取 NestedObject 数组,只需在对象 class 中构建一个构造函数,就像我的 Obj class:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Models\NestedObject as NestedObjectModel;

class Obj extends Model
{
    protected $guarded = [];

    protected $casts = [
        'nestedObject' => \App\Casts\NestedObjectCast::class,
    ];

    public function __construct(array $attributes = []) {
        if (!empty($attributes['nestedObject'])) {
            $attributes['nestedObject'] = new NestedObjectModel($attributes['nestedObject']);
        }
        parent::__construct($attributes);

    }
}

注意:不能创建名称为Object的class,因为它是PHP中的保留字。