阵列验证中的Foreach表单

Thanks for reading :D

I'm creating a online order system. You will see 3 inputs. Partnumber, Quantity and Price. You will only fill in Partnumber and Quantity. Price will be checked trough my database for the right price. I tried to create that function, still not working. But anyway. I included a jQuery function so you can add extra lines into the form when you want to order more products.

A little snippet so you know what i am meaning.

    $('#addpart').click(function(){
  var loop = $('#loop').val();
  var html;
  html = '<p>';
  html += '<input type="text" name="part[]" style="margin-left:20px;" class="text medium" id="part" placeholder="SP partnumber" />';
  html += '<input type="text" name="qty[]" style="margin-left:20px;" class="text small" placeholder="Qty" />';
  html += '<input type="text" style="margin-left:20px;" class="text small" id="price" placeholder="Price" tabindex="-1" readonly />';
  html += '</p>';
  for (i = 0; i < loop; i++) {
    $("#form").append(html);
}

});

So when your post this form we dont know how many fields it will be. Sometimes it will be 5 order lines, sometimes 10. So i start using [] in my input field. The input name attribute will be like this: "part[]".

The form will be validated with the class Validation. To show my class this page will be very long ghehe. Here is a little snippet how to use this class/function so you know the structure.

if(toxInput::exists()){
    if(toxtoken::check(toxInput::get('token'))){

        $toxValidate = new toxValidate();
        $toxValidation = $toxValidate->check($_POST, array(
            'name'  => array(
                'required'  => true,
                'min'               => 2,
                'max'       => 50
            )
        ));

        if($toxValidation->passed()){
    etcetcetc..

So with the order form it should be something like this:

$toxValidate = new toxValidate();
    $toxValidation = $toxValidate->check('$_POST', array(
        'part1' => array('required' => TRUE, 'maxlength' => 14),
        'part2' => array('required' => TRUE, 'maxlength' => 14),
        'part3' => array('required' => TRUE, 'maxlength' => 14),
        'part4' => array('required' => TRUE, 'maxlength' => 14),
        'part5' => array('required' => TRUE, 'maxlength' => 14)
    ));

How can i print this line 'part1' => array('required' => TRUE, 'maxlength' => 14) for every filled in line. I tried serveral ways with foreach and []. All didnt work.. :(

I suppose that you need to extend your Validation class to be able to validate arrays in the most comfortable way.

You can try to handle array variables like this (just an example):

$toxValidate->check($_POST, [
    'name' => [
        'required' => TRUE,
        'min' => 2,
        'max' => 50,
    ],
    'qty' => [
        'required' => TRUE,
        'array' => TRUE,
        'min' => 2,
        'max' => 14,
    ],
]);

Under the hood of your Validation class, just loop through the values of the passed qty array if is_array($toxValue) and apply your rules to every member of that array (min, max, etc.).

Also, I suggest to refactor your Validation class: use callbacks or class member functions to call separate validation rules (not the best OOP-way, but feasible for easy cases). Like this:

class Validation
{
    ...

    public function ruleMax($value)
    {
        ... // Validate value max
    }

    public function ruleMin($value)
    {
        ... // Validate value min
    }
}

With this approach you won't need to fully rewrite your check function if you need to add more validation rules to your class (or subclass).

By the way, I suggest to see how it's made in popular frameworks like Laravel: https://laravel.com/docs/5.4/validation#validating-arrays

And the class itself as an easy example (not the best of course) of rules decoupling: https://github.com/laravel/framework/blob/5.1/src/Illuminate/Validation/Validator.php