如何在 Nova 中创建依赖验证规则?
How can I create a dependent validation rule in Nova?
我在 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 and neither validation rule objects or custom closure rules 会帮助我,因为我无法从他们那里访问类型字段的值。
同样,我考虑过像扩展 NovaRequest 对象那样扩展 FormRequest,但这不会执行 Nova 应用的前端验证。
有什么方法可以实现我所缺少的吗?
也许您需要使用更大的包名nova-dependency-container。你可以在 novapackage 阅读它的使用方法。备注:
- 将文件 php.ini 行
upload_max_filesize=2M
更改为 upload_max_filesize=30M
- 参考这个 link 定义 mimes 类型:http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
这是我的 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'),
];
}
我现在通过 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 内置的,验证逻辑必须重复。
我在 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 and neither validation rule objects or custom closure rules 会帮助我,因为我无法从他们那里访问类型字段的值。
同样,我考虑过像扩展 NovaRequest 对象那样扩展 FormRequest,但这不会执行 Nova 应用的前端验证。
有什么方法可以实现我所缺少的吗?
也许您需要使用更大的包名nova-dependency-container。你可以在 novapackage 阅读它的使用方法。备注:
- 将文件 php.ini 行
upload_max_filesize=2M
更改为upload_max_filesize=30M
- 参考这个 link 定义 mimes 类型:http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
这是我的 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'),
];
}
我现在通过 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 内置的,验证逻辑必须重复。