首页 > 解决方案 > 为什么基于注册类型容量的验证不起作用?

问题描述

我有一个选择菜单供用户选择会议的每种注册类型的数量:

@foreach($registration_types as $rtype)
<li>
    <div>
        <span>{{$rtype->name}}</span>
    </div>
    @if(min($rtype->max_participants, ($rtype->capacity - $rtype->participants->count())) == 0)
        Out of capacity
    @else
        <select
                id="rtype_{{ $rtype->id }}"
                data-price="{{ $rtype->price }}"
                name="rtypes[{{ $rtype->name }}]">
            <option value="0">0</option>

            @for ($i = $rtype->min_participants; $i <= min($rtype->max_participants, ($rtype->capacity - $rtype->participants->count())); $i++)
                <option value="{{ $i }}">{{ $i }}</option>
            @endfor
        </select>
    @endif
    <span>X {{$rtype->presentPrice()}}
        €&lt;/span>
</li>
@endforeach

我想验证用户在选择菜单中引入的数量。

如果出现以下情况,我已经有一个RegistrationTypeQuantity返回 false 的自定义规则:

否则,它会通过。

RegistrationQuantity 自定义规则:

  public function passes($attribute, $value)
    {
        $count = array_sum($value);
        if($count == 0){
            return false;
        }
        foreach($value as $key=>$v) {
            $rtype = RegistrationType::where('name',$key)->first();
            if ( !$rtype ){
                return false;
            }
            if ( $v != 0 && ($v < $rtype->min_participants || $v > $rtype->max_participants) ){
                return false;
            }
        }
        return true;
    }

所以这工作正常。

怀疑:

但也需要验证用户引入的数量考虑注册类型的容量列。每个注册类型都有一个容量。

因此,例如,如果注册类型“general”的容量为 10,并且已经有 10 名参与者在注册类型“general”中注册。如果用户为注册类型“general”引入数量“10”并单击 Next,它应该会导致验证错误。

另外,如果注册类型“general”的数据库容量为 10,min_participants 为 1,最大参与者为 3,并且注册类型为“general”的参与者有 8 名,则选择菜单中仅显示 1 和 2。因此,如果例如,用户输入数量的值“3”并单击“下一步”它应该显示验证错误,因为用户应该只被允许选择数量 1 或 2,因为 8 个参与者 + 3 = 11 并且总容量是10. 所以验证应该失败。

但是将以下代码添加到规则的passes()方法中RegistrationTypeQuantity无法实现此验证:

if ($v <= min($rtype->max_participants) 
&& ($rtype->capacity - $rtype->participants->count())){
    return false;
}

考虑到注册类型的容量,您知道如何正确验证引入的数量吗?

标签: phplaravel

解决方案


试试这个..

public function passes($attribute, $value)
{
    if(array_sum($value) < 1){
        return false;
    }

    foreach($value as $key=>$v) {
        if ( $v != 0) {
            $rtype = RegistrationType::where('name',$key)->withCount('participants')->first();

            if ( !$rtype ){
                return false;
            }

            if ($v < $rtype->min_participants || $v > $rtype->max_participants || (($rtype->capacity - $rtype->participants_count) < $v) ){
                return false;
            }
        }
    }
    return true;
}

仅当所选数量为 时,此验证规则才会通过:

介于min_participantsmax_participants小于(容量 - 当前参与者)

选修的:

您的验证规则将进行n查询次数,您可以将其减少到一个。其中n是用户选择的注册类型的数量。

看法

@foreach($registration_types as $rtype)
    <li>
        <div>
            <span>{{$rtype->name}}</span>
        </div>
        @if(min($rtype->max_participants, ($rtype->capacity - $rtype->participants->count())) == 0)
            Out of capacity
        @else
            <select id="rtype_{{ $rtype->id }}" data-price="{{ $rtype->price }}" name="rtypes[{{ $rtype->id }}]">
                <option value="0">0</option>
                @for ($i = $rtype->min_participants; $i <= min($rtype->max_participants, ($rtype->capacity - $rtype->participants->count())); $i++)
                    <option value="{{ $i }}">{{ $i }}</option>
                @endfor
            </select>
        @endif
        <span>X {{$rtype->presentPrice()}} €&lt;/span>
    </li>
@endforeach

请注意,name数量选择的属性已更改。[索引从$rtype->name变为$rtype->id

验证规则

public function passes($attribute, $value)
{
    if(array_sum($value) < 1){
        return false;
    }

    $rTypes = RegistrationType::withCount('participants')->whereIn('id',array_keys($value))->get();

    foreach($rTypes as $rType) {
        if ( $value[$rType->id] != 0) {
            if ($value[$rType->id] < $rtype->min_participants || $value[$rType->id] > $rtype->max_participants || (($rtype->capacity - $rtype->participants_count) < $value[$rType->id]) ){
                return false;
            }
        }
    }
    return true;
}

请注意,whereIn用于在单个查询中访问所有必需的记录。使用数量数组上的方法id访问的s 数组。array_keys

如果我没有测试过,请告诉我是否遇到任何问题。


推荐阅读