如何处理 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中的保留字。
我有一个对象,是这样创建的:$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中的保留字。