从FilamentPHP/Livewire表单更新模型状态(laravel-model-state)

carvr3hs  于 2023-11-20  发布在  PHP
关注(0)|答案(1)|浏览(140)

我在FilamentPHP(v3)项目中使用spatie/laravel-model-states。为了让状态在表单中正确显示,我必须在state类中实现Wireable,看起来像这样:

abstract class InventoryItemState extends State implements Wireable {
    public static function config(): StateConfig
    {
        return parent::config()
            ->default(Received::class)
            ->allowTransition(Received::class, Sanitized::class)
            ->allowTransition(Sanitized::class, Sold::class)
            ->allowTransition(Sold::class, Sanitized::class);
    }

    public function toLivewire() {
        return [
            'name' => $this->getValue()
        ];
    }

    public static function fromLivewire($value) {
        return new static($value);
    }
}

字符串
示例状态如下所示:

class Received extends InventoryItemState {
    public static $name = 'received';
}


在表单中,我显示了这个特定项目可以转换到的可用状态:

namespace App\Filament\Resources;
class InventoryItemResource extends Resource
{
    protected static ?string $model = InventoryItem::class;

    protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';

    public static function form(Form $form): Form
    {
        $potential_states = $form->getRecord()->state->transitionableStates();
        // Some other stuff not relevant
        $formSchema = [
            // other form options
        ];
        if (!empty($potential_states)) {
            $options = collect($potential_states)
                ->keyBy(fn ($item) => $item)
                ->toArray();
            $formSchema[] = Forms\Components\Radio::make('state')
                ->options($options);
        }
        $schema[] =
            Section::make()
                ->compact()
                ->columns(2)
                ->schema($formSchema);

        return $form
            ->schema($schema);
    }

    // Other stuff removed
}


这可以将可转换状态显示为单选按钮:

然而,在保存时,我得到了这个错误:
foreach()参数必须为数组类型|对象,给定的字符串
来自Livewire\Features\SupportWireables\WireableSynth.php

function hydrate($value, $meta, $hydrateChild) {
    foreach ($value as $key => $child) {
        $value[$key] = $hydrateChild($key, $child);
    }

    return $meta['class']::fromLivewire($value);
}


很容易看出原始值是一个数组:

并且表单将其设置为的值不是:

所以WireableSynth::hydrate显然期望一个数组,而当值被更改并提交表单时,它并没有得到这个数组。

sqyvllje

sqyvllje1#

我目前在我的项目中有一个类似的流程,也停留在保存步骤上。首先,我认为你的'fromLivewire'方法的实现不好,因为State类的构造函数需要模型。这里有一个'make'方法可以使用。这里是我的state类。但是这里有另一个使用'static'关键字调用'make'方法的问题,代码福尔斯错误,因为检查状态类是否是父状态类的子类,在这种情况下,两个值相同。(如果屏幕截图上的条件)

<?php

namespace App\Models\States\Project;

use App\Models\Project;
use App\Models\States\Project\Transitions\ProjectCompleted;
use Livewire\Wireable;
use Spatie\ModelStates\Attributes\AllowTransition;
use Spatie\ModelStates\Attributes\DefaultState;
use Spatie\ModelStates\State;

#[
    DefaultState(ToDo::class),
    AllowTransition(from: ToDo::class, to: InProgress::class),
    AllowTransition(from: InProgress::class, to: ToDo::class),
    AllowTransition(from: InProgress::class, to: Done::class, transition: ProjectCompleted::class),
]
abstract class ProjectState extends State implements Wireable
{
    protected static string $modelClass = Project::class;

    public function label(): string
    {
        return ucwords($this->getValue());
    }

    public function toLivewire(): array
    {
        return [
            'model' => $this->getModel()->id,
            'value' => $this->getValue()
        ];
    }

    public static function fromLivewire($value): static
    {
        return self::make($value['value'], static::$modelClass::find($value['model']));
    }
}

字符串
State class 'make' method code

相关问题