Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Problem with multiple upload validation error messages
  • I'm having trouble setting error messages for multiple fields for extended validation functions. I created a new validation rule for files uploaded with a form. The validation rule is applied to each file field and checks Upload::get_errors() to see if there was an error for the file associated with that form field. If so, set_message() is called to set the error message for that form field. If I allow the form to upload multiple files, it appears that only one error message is being saved. For example, if file #1 fails validation because it's over the maximum file size and file #2 fails for an extension that is not allowed, only the last error message seems to be saved and will be printed out for both form fields. Is there something wrong with what I'm doing?
  • Valid point, it doesn't take into account that you can have multiple errors. I'll see if I can fix this today ('messages' has to be an array of strings, instead of a string).
  • I've been thinking about this. The way it currently works, is that checking stops after the first error encountered. There is only one error code possible, and therefore also only one error message. Changing this means changing the logic of the process() and save() methods, but it also means a significant change to the result of get_errors(), which might break current applications. I think we need to park this until after the 1.0 release. I'll add a feature request for this.
  • WanWizard, I just read your entry in the issues, and I think you may be referring to a different issue. Tell me if I'm wrong, but I believe your entry refers to the issue that if there is more than one upload error, e.g. file exceeded max size and file type not allowed, then the Upload class only saves the first error it encounters. This is true and would be nice to fix, however the issue I'm seeing is a bit more basic. For example, if I create 2 text fields and add the rule array('min_length', 3) to the first field and array('min_length', 5) to the 2nd text field, there's no problem or confusion with validation applying the appropriate rule to each field and generating a unique error message for each field. However, if I specify my own validation rule such as array(check_file_upload, $form_field) and apply it to more than 1 field, there is a problem. For example suppose for the first file field check_file_upload() calls set_message('check_file_upload', The uploaded file exceeds the defined maximum size'); And then for second file field check_file_upload() calls set_message('check_file_upload', 'The uploaded file exceeds the defined maximum size'); When the function show_errors() is called, the last error message reported is displayed for both fields. So for the example above, what gets displayed are 2 error messages that say "The uploaded file exceeds the defined maximum size."
  • Now I'm confused. This looks like your talking about validation functionality, which has nothing to do with the Upload class (and isn't used to validate uploaded files). Upload deals with $_FILES only, not with $_POST. You should not use standard form processing (including validation) for file uploads. You use the Upload class for that, and it will do a per-file validation according to your configuration (including size, extension, mime-type, naming, etc). After processing you'll use Upload::get_errors() to get info about all uploaded files that failed validation, and Upload::get_files() to get all the passed validation and can be saved. Note that you can get errors while saving as well, so get_errors() can return a different result before and after the save.
  • Oh boy, now I'm confused. I created a validation function that uses the Upload class to check for file upload errors. Because there can be more than one file upload per page, the validation function is called for each upload file field. The idea is that if file #1 fails because it exceeds the max file size, then an error message can explain why it failed. If file #2 failed because the file type is not allowed, then a different error message is displayed for the 2nd file. Maybe a quick example would help:
     public function _validation_upload_ok($form_value, $form_field)
     {
      // Get files uploaded with errors
      $upload_errors = Upload::get_errors();
    
      // Check if this form field had an upload error
      foreach ($upload_errors as $error)
      {
       if ($error['field'] == $form_field)
       {
        $this->set_message('upload_ok', $error['message'] . ' (' . $error['name'] . ').');
        return false;
       }
      }
      return true;
     }
    

  • Ah, a little bit of explanation and code helps... ;) I understand now what you're trying to do here, and if called correctly, that should work. Do I understand you correctly in that if one of the uploads failed, you'll get the same error message with all your file upload form fields? How do you call this method? Normal validation only runs on fields in $_POST, and file upload form fields are not in there.
  • Yes, the last error message seems to overwrite the others. Actually, to be clear, the Upload::get_errors() function returns the correct error messages. I guess it's the show_errors() function that displays the wrong error message. The validation function is set up in the model set_form_fields() function using $form->add(). Here's a snippet of the code:
     public static function set_form_fields_example(Fieldset $form, $example_id = null)
     {
      if ($example_id != null)
      {
       $examples = self::get_example_info($example_id);
      }
    
      // File upload - set up several fields
      for ($i = 1; $i <= Model_Mexamples::N_FILES; $i++)
      &#123;
       $field = 'file_' . $i;
       $field_id = 'file-' . $i;
    
       $form->add($field,
        "Upload File $i",
        array(
         'type' => 'file',
         'size' => 50,
         'id' => $field_id,
        ),
        array(
         array('upload_ok', "$field"),
        )
       );
    }
    
  • Can you do a \Debug::dump() of the result of get_errors() in your validate method? I have a feeling the issue is on the Validation side, I'm not sure you can have distinct error messages for a single validation method, I think it only keeps one message per rule.
  • I think you may be right. Here's the Debug::dump() output from the first time through the validation function. I attempted to upload 2 files that generated 2 different error messages. You can see that Upload::get_errors() returns the correct error messages. APPPATH/classes/validation.php @ line: 344 Variable #1:
    string(18) "Form field: file_1" Variable #2:
    array(2) {
    [0]=>
    array(11) {
    ["name"]=>
    string(18) "dbg_wizard_ide.txt"
    ["type"]=>
    string(10) "text/plain"
    ["error"]=>
    int(103)
    ["size"]=>
    int(3576)
    ["field"]=>
    string(6) "file_1"
    ["key"]=>
    bool(false)
    ["file"]=>
    string(24) "M:\xampp\tmp\php473E.tmp"
    ["extension"]=>
    string(3) "txt"
    ["filename"]=>
    string(14) "dbg_wizard_ide"
    ["mimetype"]=>
    string(10) "text/plain"
    ["message"]=>
    string(50) "Upload of files with this extension is not allowed"
    }
    [1]=>
    array(10) {
    ["name"]=>
    string(12) "Polar A3.pdf"
    ["type"]=>
    string(17) ""application/pdf""
    ["error"]=>
    int(101)
    ["size"]=>
    int(230042)
    ["field"]=>
    string(6) "file_2"
    ["key"]=>
    bool(false)
    ["file"]=>
    string(24) "M:\xampp\tmp\php473F.tmp"
    ["extension"]=>
    string(3) "pdf"
    ["filename"]=>
    string(8) "Polar A3"
    ["message"]=>
    string(50) "The uploaded file exceeds the defined maximum size"
    }
    }
  • Well, I went through the code carefully, and there's only one error message allowed per validation function. validation->error_messages[] contains those error messages. So each time the validation function fails, the error message is overwritten and the same error message is displayed for each form field that fails that validation. Normally, this is not a problem, but in the case of multiple file uploads where each file can fail for a different reason and you would also like to display the name of the file that failed, this is a problem. What is confusing is that if a form field fails validation, an array of class Validation_Error is created and added to the Validation instance. A Validation_Error is created for each field that fails. The class Validation_Error contains a variable $message. So there is a place for a unique error message for each form field, however I couldn't find anywhere that references the $message variable and it's always empty. As a quick workaround, I overwrote Validation_Error __construct() and Validation_Error get_message(). In the constructor, I save the current error message in Validation_Error->message (actually the code is $this->message). In Validation_Error get_message(), if there's a message saved, it's returned instead of the normal Validation error message. If anyone has a better idea, I'd love to hear it.
  • I suggest you add this as a feature request on http://github.com/fuel/core/issues, and ask Jelmer's opinion, he's the author of the validation class.
  • I just added the request to the issues tracker.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion