Laravel Livewire 访问 json 属性失败,并出现类型错误

Laravel Livewire accessing json attribute fails with type error

提问人:lordisp 提问时间:8/21/2022 最后编辑:lordisp 更新时间:8/21/2022 访问量:584

问:

我有一个模型,其中包含一些典型列和一个 json 列。Json 被强制转换为数组:

型:

protected $casts = [
    'client' => 'array'
];

在我的 Livewire 组件中,我创建了以下验证规则

Livewire 组件:

protected $rules = [
  'editing.name' => 'required',

  ...

  'editing.client' => 'present|array',
  'editing.client.*.tenant' => 'required',
];

我调用“editModal”方法,在其中键入提示模型并使用其属性设置公共属性。已筛选到特定项目。

Livewire 组件:

public function editModal(TokenCacheProvider $provider)
{
    $this->editing = $provider;
    $this->dispatchBrowserEvent('open-modal', ['modal' => 'edit']);
}

我的叶片是一个简单的锅炉叶片组件:

叶片:

<div>
    <x-input.group inline borderless for="name" label="Name" :error="$errors->first('editing.name')"/>
    <x-input.text name="name" class="w-full" wire:model="editing.name" />
</div>

<div>
    <x-input.group inline borderless for="name" label="Tenant" :error="$errors->first('editing.client.tenant')"/>
    <x-input.text name="tenant" class="w-full" wire:model="editing.client.tenant" />
</div>

加载页面后,出现以下类型异常

foreach() argument must be of type array|object, string given

这是因为 client 属性仍然是数据库中的字符串。当我转换它时,它应该是一个数组:

public $editing

所以,我不明白为什么属性仍然是一个字符串,而不是一个强制转换的数组。client

谢谢

PHP 铸造 Laravel-Livewire Laravel-9

评论

0赞 Daantje 8/21/2022
你试过选角吗?json
0赞 lordisp 8/21/2022
是的,我已经尝试了 json 和数组
0赞 Daantje 8/21/2022
您是否尝试过在 livewire 对象中对其进行解码?forum.laravel-livewire.com/t/json-with-livewire/1420/2
0赞 lordisp 8/21/2022
这不是上述问题的重复,因为我的问题与模型属性转换有关,而不是从 API 转换 json 响应。
1赞 Daantje 8/21/2022
看这里;github.com/livewire/livewire/issues/1826这是Livewire的问题。我认为最快的解决方法是在 livewire 对象中解码。编码可以像强制转换一样正常工作。

答:

0赞 lordisp 8/21/2022 #1

好吧,这更像是一种解决方法,而不是解决方案,但 DaantjeGithub 上发现了一个 Livewire 问题,这可能解释了这种行为。

我已将体系结构从一个公共属性更改为两个公共属性。一个用于实际模型,另一个用于 json 列。

Livewire 组件(截断)

public MyModel $editing; // the model
public array $client; // for the json attribute

protected $rules = [
'editing.name' => 'required',
 ...

'client.foo' => 'required',
'client.bar' => 'required',
'client.baz' => 'required',
 ...
];


public function editModal(MyModel $model)
{
    $this->editing = $model;
    $this->client = json_decode($model->client,true);
    $this->dispatchBrowserEvent('open-modal', ['modal' => 'edit']);
}


public function save()
{
    $this->validate();

    $this->editing->client = json_encode($this->client);

    $this->editing->save();

    $this->dispatchBrowserEvent('close-modal', ['modal' => 'edit']);

    $this->event('Saved', 'success');
}

两个刀片输入字段示例:

<!-- ORM field(s) -->
<div>
    <x-input.group inline borderless for="name" label="Name" :error="$errors->first('editing.name')"/>
    <x-input.text name="name" wire:model="editing.name" />
</div>


<!-- Json field(s) -->
<div>
    <x-input.group inline borderless for="foo" label="Foo" :error="$errors->first('client.foo')"/>
    <x-input.text name="foo" wire:model="client.foo" />
</div>

好吧,这有效,但如前所述,它更像是一种解决方法