Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Validate multiple uploaded files separately
  • (using FuelPHP 1.2/master) I have a form with multiple upload fields of different types, i.e. one icon upload field (image) and a certificate field (text).
    To validate these uploaded files I would like to restrict the mime_type of the icon to only images and the mime_type of the text field to only text/plain. Is this in any way possible? The \Upload::process() method only allows for a single 'mime_type' array. I tried to do it by registering a 'validate' callback to the Upload class, but don't know how to continue from there.
    A possible solution would be manually checking the mime_type inside the callback, but how can I create validation error messages? Sample code:
                \Upload::register('validate', function (&$file) {
                    switch($file['field'])
                    {
                        case "certificate":
                            $file['mime_whitelist'] = array('text/plain');
                             // check $file['mime_type'] manually, how to generate an error message?
                        break;
    
                        case "icon":
                            $file['ext_whitelist'] = array('img', 'jpg', 'jpeg', 'gif', 'png');
                            // check $file['ext_whitelist'] manually, how to generate an error message?
                        break;
                    }
                });
    
                \Upload::process($some_config);
    
    

    Any help is appreciated!
  • The 'validate' callback will be called after all generic validations have taken place, so you can't use it to alter validatio rules. You have to make sure your generic rules are generic enough so that both files pass validation, then in your validate callback do all specific checks manually. The validate callback method has to return:
    - true in case the file validated
    - a number in case you want to return a predefined error message If you want to add a custom error message, set $file to true, and add the message to $file.
  • Awesome thanks!
  • Ok I tried it, almost there, but there is something weird going on with setting the error message:
    // custom validation for the different file types
    \Upload::register('validate', function (&$file) {
        switch($file['field'])
        {
            case "production-certificate":
            case "test-certificate":
                if ($file['mimetype'] !== 'text/plain')
                {
    
                    $env = substr($file['field'], 0, strlen($file['field']) -strlen('-certificate'));
    
                    $file['error'] = true;
                    $file['errors'][] = array('error' => \Upload::UPLOAD_ERR_MIME_NOT_WHITELISTED, 
                        'message' => "The $env certificate is not valid, please upload a plain/text certificate");
    
                    return false;
                }
            break;
    
            case "icon":
                if ( ! in_array($file['extension'], array('img', 'jpg', 'jpeg', 'gif', 'png')) )
                {
                    $file['error'] = true;
                    $file['errors'][] = array('error' => \Upload::UPLOAD_ERR_EXT_NOT_WHITELISTED, 
                        'message' => 'The icon is not a valid image, please try another icon');
    
                    return false;
                }
            break;
        }
        return true;
    });
    
    \Upload::process(array('randomize' => true,)); 
    
    \Debug::dump(\Upload::get_errors());
    
    

    For both fields 'production-certificate' and 'icon' the error message is correct (the one manually set).
    But the 'test-certificate' field gets the error message that belongs to the error constant (i.e. "Upload of files of this mime type is not allowed")
    not the custom message... (different error constant gives different message) Any idea what's going on?
  • Yes. You're using a reserved error number. The process() method internally only works with error numbers, the messages are added based on that number after all uploaded files have been processed. So because you use a reserved number, you message is overwritten in that process.
  • Thanks Harro for the quick replies, appreciate it! Ok, so how should I set a real custom error message without the Process method overwriting it?
    (And how come do the other two fields work correctly, i.e. they have the same reserved error number, but the message is still custom) If I try a totally random number, the message gets overwritten with 'null'.
    See this Debug output of \Debug::dump(\Upload::get_errors()); after the Process method is called:
    http://cl.ly/text/400l19053e3U First two fields are correct, last field ('test-certificate') not, using the same code as above, but different error number.
    (Btw. I use the core upload config, only 'randomize' => true is set)
  • After all validation of an uploaded file is done, the code loops over all defined errors, and tries to load the error message, overwriting any message already defined. So why some fields still have a custom message is beyond me. This issue is only with 'process', the error detection in 'save' deals with custom messages correctly, so I would consider this a bug. I've pushed a fix (to 1.3/develop) so that it will only get messages for error numbers that don't have one defined.
  • Nice, thanks Harro. I just figured out what the root problem is, the overwriting of the error message is done outside of the for loop. (1.2/master)
    But this is already fixed in 1.3/dev in commit c1b2485489 Maybe I should switch to the develop branches...
    Anyway, thanks again for all the help!

Howdy, Stranger!

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

In this Discussion