Laravel 10 与 FilamentPHP 3 - 重叠日期范围验证

问题描述 投票:0回答:1

如何防止数据库中现有日期范围的日期重叠?

我有 SchoolPeriod 模型和 school_periods 表,其中包含 date_from 和 date_to 列,它被定义为受保护的可填充用于批量分配。

我已经为 SchoolPeriod 生成了一个灯丝资源,我想对 date_from 和 date_to Forms\Components\DatePicker 进行验证。如果 date_from 或 date_to 已存在于数据库中现有记录的日期范围内,则闪烁验证消息。

学校期间迁移:

    public function up(): void
    {
        Schema::create('school_periods', function (Blueprint $table) {
            $table->id();
            $table->date('date_from');
            $table->date('date_to');
            $table->timestamps();
            $table->unique(['date_from', 'date_to']);
        });
    }

受保护可填充的SchoolPeriod模型:

    protected $fillable = [
        'date_from',
        'date_to',
        'name',
        'is_active',
        'created_by',
    ];

学校期间资源表:

public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\Components\DatePicker::make('date_from')
                    ->label('Start Date')
                    ->required()
                    ->beforeOrEqual('date_to'),
                Forms\Components\DatePicker::make('date_to')
                    ->label('End Date')
                    ->required()
                    ->afterOrEqual('date_from')
                    ->unique(modifyRuleUsing: function(Unique $rule, callable $get){
                        $start = $get('date_from');
                        $end = $get('date_to');
                        return $rule->where(function ($q) use ($start, $end) {
                            $q->where('date_from', '>=', $start)
                            ->where('date_from', '<=', $end);
                        })
                        ->orWhere(function ($q) use ($start, $end) {
                            $q->where('date_to', '>=', $start)
                                ->where('date_to', '<=', $end);
                        })
                        ->orWhere(function ($q) use ($start, $end) {
                            $q->where('date_from', '<', $start)
                                ->where('date_to', '>', $end);
                        });
                    }),
            ]);
    }
laravel validation laravel-livewire laravel-filament filamentphp
1个回答
0
投票

这应该可行,已插入注释来解释代码:

 public static function form(Form $form): Form
{
    return $form
        ->schema([
            DatePicker::make('date_from')
                ->label('Start Date')
                ->required()
                ->beforeOrEqual('date_to')
                // Enable live updating, required for disabled rule, see below
                ->live(),
            DatePicker::make('date_to')
                ->label('End Date')
                ->required()
                ->afterOrEqual('date_from')
                // disable the date_to field to force the users to select the date_from first
                ->disabled(fn(Get $get): bool => !$get('date_from'))
                ->rules([
                    function (Get $get) {
                    // Define a custom validation rule to check for overlapping school periods
                        return function (string $attribute, $value, Closure $fail) use ($get) {
                            $start = $get('date_from');
                            $end = $get('date_to');

                            // Query the SchoolPeriod model to check for any existing periods that overlap with the selected date range.
                            $exists = SchoolPeriod::whereBetween('date_from', [$start, $end]) // Check if date_from is between 'start' and 'end'
                                ->orWhereBetween('date_to', [$start, $end]) // // Check if date_to is between 'start' and 'end'
                                ->orWhere(function ($query) use ($start, $end) {
                                    // Additional condition for when date_from is before 'start' and date_to is after 'end'
                                    $query->where('date_from', '>', $start)
                                        ->where('date_to', '<', $end);
                                })->exists();

                            if($exists) {
                                $fail('The dates overlap');
                            }

                            // add notification here: https://filamentphp.com/docs/3.x/notifications/sending-notifications#overview
                        };
                    },
                ])
        ]);
}
© www.soinside.com 2019 - 2024. All rights reserved.