【问题标题】:How can I create a dependent validation rule in Nova?如何在 Nova 中创建依赖验证规则?
【发布时间】:2019-11-19 09:25:53
【问题描述】:

我在 Nova 中为资源定义了如下字段:

Select::make('Type')
    ->options([
        'video' => 'Video',
        'download' => 'Download',
        ])
    ->rules('required'),    

File::make('File', 'file_name')
    ->disk('local')
    ->path('/files')

我正在尝试根据类型字段的值为文件字段设置不同的验证规则。例如,类型是下载,接受文档 MIME 文件,最大大小为 1mb,而如果设置为视频,则接受视频文件 MIME 文件,最大大小为 30mb。

我没有真正做到这一点。

我查看了the docs,但validation rule objectscustom closure rules 都不会帮助我,因为我无法从它们那里访问类型字段的值。

同样,我想扩展 NovaRequest 对象,就像使用 FormRequest 一样,但这不会执行 Nova 应用的前端验证。

有什么方法可以实现我所缺少的吗?

【问题讨论】:

    标签: php laravel-5 laravel-nova


    【解决方案1】:

    也许你需要使用一个更大的包名 nova-dependency-container。你可以在 novapackage 阅读使用它的方法。备注:

    这是我的 Document Nova 资源代码。编码愉快,有需要可以问我!

    <?php
    
    namespace App\Nova;
    
    use Laravel\Nova\Fields\ID;
    use Laravel\Nova\Fields\Text;
    use Laravel\Nova\Fields\File;
    use Laravel\Nova\Fields\Select;
    use Illuminate\Http\Request;
    use Laravel\Nova\Http\Requests\NovaRequest;
    use Epartment\NovaDependencyContainer\HasDependencies;
    use Epartment\NovaDependencyContainer\NovaDependencyContainer;
    
    class Document extends Resource
    {
        use HasDependencies;
        /**
         * The model the resource corresponds to.
         *
         * @var string
         */
        public static $model = 'App\Document';
    
        /**
         * The single value that should be used to represent the resource when being displayed.
         *
         * @var string
         */
        public static $title = 'id';
    
        /**
         * The columns that should be searched.
         *
         * @var array
         */
        public static $search = [
            'id',
        ];
    
        /**
         * Get the fields displayed by the resource.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return array
         */
        public function fields(Request $request)
        {
            return [
                ID::make()->sortable(),
                Select::make('Type','type')
                ->options([
                    'video' => 'Video',
                    'download' => 'Download',
                    ])
                ->rules('required'),
                NovaDependencyContainer::make([
                    File::make('Video File','file_name')
                    ->storeOriginalName('file_name')
                    ->rules('required','mimes:mpga,mp2,mp2a,mp3,m2a,m3a,mp4,flv','max:30000')  //unit max is Kb
                ])->dependsOn('type', 'video'),
                NovaDependencyContainer::make([
                    File::make('Document File', 'file_name')
                    ->storeOriginalName('file_name')
                    ->rules('required','mimes:jpeg,png,jpg,doc,docx,pdf','max:1000') 
                ])->dependsOn('type', 'download'),
            ];
        }
    
        /**
         * Get the cards available for the request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return array
         */
        public function cards(Request $request)
        {
            return [];
        }
    
        /**
         * Get the filters available for the resource.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return array
         */
        public function filters(Request $request)
        {
            return [];
        }
    
        /**
         * Get the lenses available for the resource.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return array
         */
        public function lenses(Request $request)
        {
            return [];
        }
    
        /**
         * Get the actions available for the resource.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return array
         */
        public function actions(Request $request)
        {
            return [];
        }
    }
    

    更新:

    有问题:“当我使用您的代码时,它适用于上传视频(因为这是第一位的),但随后上传文档会出现错误,该错误必须是所列的视频 mimetype。选择文档还是视频;应用视频规则。”

    解决:在模型中使用虚拟属性,叫Laravel mutators,前几天听说过。请参阅我的以下代码:

    // Model Laravel: app\Document.php
    class Document extends Model
    {
        public function getFileNameVideoAttribute()
        {
            if ($this->type == "video") {
                return $this->file_name;
            }
            return;
        }
        public function setFileNameVideoAttribute($value)
        {
            $this->attributes['file_name'] = $value;
        }
        public function getFileNameDocumentAttribute()
        {
            if ($this->type == "download") {
                return $this->file_name;
            }
            return;
        }
        public function setFileNameDocumentAttribute($value)
        {
            $this->attributes['file_name'] = $value;
        }
    }
    // Model Nova: app\Nova\Document.php
        public function fields(Request $request)
        {
            return [
                ID::make()->sortable(),
                Select::make('Type','type')
                ->options([
                    'video' => 'Video',
                    'download' => 'Download',
                    ])
                ->rules('required'),
                NovaDependencyContainer::make([
                    File::make('Video File','file_name_video')
                    ->storeOriginalName('file_name')
                    ->rules('required','mimes:mpga,mp2,mp2a,mp3,m2a,m3a,mp4,flv','max:30000')  //unit max is Kb
                ])->dependsOn('type', 'video'),
                NovaDependencyContainer::make([
                    File::make('Document File', 'file_name_document')
                    ->storeOriginalName('file_name')
                    ->rules('required','mimes:jpeg,png,jpg,doc,docx,pdf','max:1000') 
                ])->dependsOn('type', 'download'),
            ];
        }
    

    【讨论】:

    • 这适用于前端 - 但是验证规则仅适用于第一个文件输入 - 即即使显示下载字段,验证规则也要求它是视频。我认为这是因为它们具有相同的输入名称
    • 是的,我测试过。它可以上传mp3文件或pdf文件!如果您想上传更多文件,请将它们添加到 nova-dependency-container 中!
    • 当我使用您的代码时,它适用于上传视频(因为这是第一位的),但随后上传文档会出现错误,该错误必须是所列的视频 mimetype。选择文档还是视频;视频规则已应用。
    • 感谢您继续努力!这种方法将正确的值存储在数据库中,但根本没有应用验证,并且 Nova 无法编辑/下载/删除创建后的文件(因为它正在尝试 /file_name_video 和 /file_name_document 而不是 /file_name)
    【解决方案2】:

    我现在通过 John Beales 提供的 here 教程完成了这项工作,他同样抱怨 Nova 不会自动接收 Laravel 表单请求。

    1:为扩展 FormRequest 的 Nova 资源创建请求:

    namespace App\Http\Requests;
    
    use Illuminate\Foundation\Http\FormRequest;
    use Illuminate\Validation\Rule;
    
    
    class StoreResourceRequest extends FormRequest
    {
        /**
         * Determine if the user is authorized to make this request.
         *
         * @return bool
         */
        public function authorize()
        {
            // Users authorized to make the request are:
            // - users updating themselves.
            // - staff
            // - guests creating a new user.
    
    
            return true;
        }
    
        /**
         * Get the validation rules that apply to the request.
         *
         * @return array
         */
        public function rules()
        {
    
            $rules = self::ruleGetter($this);
    
    
            if(empty($this->user())) {
                $rules = array_merge_recursive($rules, self::creationRuleGetter($this));
            } else {
                $rules = array_merge_recursive($rules, self::updateRuleGetter($this));
            }
    
            return $rules;
        }
    
        public static function ruleGetter( $request, $rule = null ) {
    
            $rules = [
                'type' =>  ['required',Rule::in(['video', 'download'])],
            ];
    
            if($request['type'] == 'download'){
                $rules['file_name'] = ['required','mimes:jpeg,png,jpg,doc,docx,pdf','max:1000'];
            } 
    
            if($request['type'] == 'video'){
                $rules['file_name'] = ['required','mimes:mp4','max:50000'];
            }
    
            if(!empty($rule)) {
                if(isset($rules[$rule])) {
                    return $rules[$rule];
                }
                return '';
            }
            return $rules;
        }
    
        public static function creationRuleGetter( $request, $rule = null ) {
            $rules = [
    
            ];
    
    
            if(!empty($rule)) {
                if(isset($rules[$rule])) {
                    return $rules[$rule];
                }
                return '';
            }
            return $rules;
    
        }
    
        public static function updateRuleGetter( $request, $rule = null ) {
    
    
            $rules = [
    
            ];
    
            if(!empty($rule)) {
                if(isset($rules[$rule])) {
                    return $rules[$rule];
                }
                return '';
            }
            return $rules;
        }
    
    }
    

    2:更新 Nova 资源以加载这些规则:

    namespace App\Nova;
    
    use App\Http\Requests\StoreResourceRequest;
    
    //...
    
    public function fields(Request $request)
    {
        return [
            //...
    
            Select::make('Type')
            ->options([
                'video' => 'Video',
                'download' => 'Download',
            ])
            ->rules(StoreResourceRequest::ruleGetter($request, 'type')),
    
            File::make('File', 'file_name')
            ->rules(StoreResourceRequest::ruleGetter($request, 'file_name'))
    
        ];
    }
    

    上述方法适用于两种类型的验证,并将正确的值存储在数据库中。 Nova 可以正常与文件交互。

    可惜这不是 Nova 内置的,验证逻辑必须重复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-18
      • 1970-01-01
      • 1970-01-01
      • 2020-05-25
      • 1970-01-01
      • 1970-01-01
      • 2020-07-15
      • 1970-01-01
      相关资源
      最近更新 更多