【问题标题】:Add field text from relationship in laravel nova in ONE form以一种形式从 laravel nova 中的关系中添加字段文本
【发布时间】:2019-12-04 15:42:12
【问题描述】:

我是 Laravel Nova 的新手。 我正在尝试构建一个用户表单。 在这一刻,我有这些模型: 用户、用户详情

在用户中我有:电子邮件、密码、用户名。 在 UserDetail 我有:姓名、姓氏、性别、号码等。

现在我将为用户创建 一个 表单。 为什么我专注于ONE? 因为在我的用户资源字段中,我有:

HasOne::make("UserDetail", "details"),

但是对于设置用户详细信息,我有 2 种形式: 一个用于用户数据(用户名、密码、电子邮件),保存用户后我可以设置详细信息。

所以我不想为 1 个资源编译 2 个不同的形式。

我找到了这个包,但好像坏了:

https://github.com/yassipad/laravel-nova-nested-form/issues/66

并且没有显示 UserDetails 字段。

那么有没有其他方法可以从关系中添加文本字段并合并到同一个表单中?

【问题讨论】:

    标签: laravel laravel-nova


    【解决方案1】:

    您可以使用Laravel's accessors and mutators 解决此问题。

    在这个例子中,我只会从UserDetail 添加gender,因为我很懒。因此,我们首先在 User 模型中添加性别访问器

    public function details()
    {
        return $this->hasOne(UserDetail::class);
    }
    
    public function getGenderAttribute()
    {
        return $this->details->gender ?? null;
    }
    

    此 getter 将从详细信息中获取性别,如果不存在详细信息,则为 null。

    现在我们在 Nova 中的 User 资源中添加一个新字段。

    public function fields(Request $request)
    {
        return [
            ID::make()->sortable(),
    
            Gravatar::make(),
    
            Text::make('Name')
                ->sortable()
                ->rules('required', 'max:255'),
    
            Text::make('Email'),
    
            Password::make('Password'),
    
            Text::make('Gender')
                ->rules('required'),
        ];
    }
    

    转到创建用户表单,它看起来像这样:

    当然这不会让它保存它,因为它不知道如何处理gender 字段。为了处理这个问题,我们重写了fillFields 方法。

    protected static function fillFields(NovaRequest $request, $model, $fields)
    {
        // Get all of our user details data
        $userDetails = $request->only(['gender']);
    
        // Remove them from the request
        $request->request->remove('gender');
    
        $result = parent::fillFields($request, $model, $fields);
    
        // Insert them in the details object after model has been saved.
        $result[1][] = function () use ($userDetails, $model){
            $model->details()->updateOrCreate(
                [],
                $userDetails
            );
        };
    
        return $result;
    }
    

    现在我们可以将性别字段视为用户的普通字段,并且不需要UserDetail 资源。要添加更多字段以保存在用户详细信息表中,我们必须将它们添加到我们的唯一并从我们的请求中删除它们。 (将它放在一个数组中会很有意义)

    此方法在更新用户时也适用,因为我们选择使用updateOrCreate



    关于这种方法的一个额外说明是我们刚刚引入了一个 n+1 查询,因为我们在尝试获取 gender 属性时延迟加载 details 关系。为了解决这个问题,我们只需覆盖 indexQuery 并将 details 添加到查询构建器。

    public static function indexQuery(NovaRequest $request, $query)
    {
        $query->with('details');
        return parent::indexQuery($request, $query);
    }
    

    【讨论】:

    • 有效!你救了我的命 :D 现在我只知道你做了什么以及如何做到这一点,以及你是如何理解这一点的!但它有效!非常感谢我的朋友!
    • 没问题 :) 所以基本上所有的魔法都在fillFields。那个返回一个包含两个元素的数组。第一个是保存之前的模型,但填充了属性,另一个元素是一个闭包数组,将在保存后运行。
    • 我们需要保存后的模型,否则我们没有用户 ID 来附加我们的用户详细信息。
    • 谢谢,尽快(16小时)给你赏金!
    • 我已经测试并且解决方案有效,但请注意,因为当您保存喜欢的其他资源时,您“被黑”的资源可能会在保存时抛出错误:) 但干得好! :D
    猜你喜欢
    • 2020-04-17
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    • 2019-02-02
    • 2022-06-15
    • 2022-11-23
    • 1970-01-01
    相关资源
    最近更新 更多