In my application, I have a field that contains an array of objects, and I would like to cast it to access it more easily.
I found https://github.com/spatie/data-transfer-object/ and following some examples i wrote all the classes and cast and now i can access to the object like this:
$val1 = $obj->fields_mapping->mappedField[0]->theField;
$val2 = $obj->fields_mapping->mappedField[1]->theField;
What I would prefeer is to access fields_mapping directly, and not using mappedField again, so something like this:
$val1 = $obj->fields_mapping[0]->theField;
$val2 = $obj->fields_mapping[1]->theField;
Below i show you the code i wrote to accomplish the first version. What i need to change to obtain the "desidered" notation? So:
$val1 = $obj->fields_mapping[0]->theField;
Model
class MyModel extends Model
{
use HasFactory;
protected $casts = [
"fields_mapping" => MappedFields::class,
];
}
DTO Using DataTransferObject
use Illuminate\Contracts\Database\Eloquent\Castable;
use Spatie\DataTransferObject\DataTransferObject;
class MappedFields extends DataTransferObject implements Castable
{
#[CastWith(ArrayCaster::class, itemType: MappedField::class)]
public array $mappedField;
public static function castUsing(array $arguments)
{
return MappedFieldsCast::class;
}
}
AND
use Spatie\DataTransferObject\DataTransferObject;
class MappedField extends DataTransferObject
{
public string $theField;
}
CastsAttributes implementation
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class MappedFieldsCast implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
if (is_null($value)) {
return;
}
$decoded = json_decode($value, true);
return new MappedFields([
"mappedField" => $decoded,
]);
}
public function set($model, $key, $value, $attributes)
{
if (is_null($value)) {
return;
}
return json_encode($value);
}
}
AND a little factory to populate the object, just for test
class MyModelFactory extends Factory
{
protected $model = MyModel::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
"fields_mapping" => [
new MappedField([
"theField" => 23,
]),
new MappedField([
"theField" => 47,
]),
],
];
}
}