Cakephp: multiple file validation

Bigalow

I'm trying to make a photomanager in cakephp. Everything works as I expect it to do besides one thing. I just don't seem to be able to validate multiple files properly.

Im using a model called Image where I validate the data from my form. This is the form in my view

<?php
        echo $this->Form->create('Image', array(
            'type' => 'file',
            'url' => array_merge(array('action' => 'index'), $this->params['pass']),
            'inputDefaults' => array(
                'div' => 'form-group',
                'wrapInput' => false,
                'label' => false,
                'class' => 'form-control'
                ),
            'class' => 'well form-inline'   
            ));
        echo $this->Form->input('Image.image_manager.', array('type' => 'file', 'multiple'));
        echo $this->Form->input('field', array(
            'options' => $imageData['buildings'],
            'empty' => '(choose one)',
            'class' => 'form-control buildingSelector'
        ));
        echo '<div class="flatForm">';
        echo $this->Form->input('flat', array(
            'options' => '',
            'empty' => '(choose one)',
            'class' => 'form-control uploadFlat',
            'id' => "success"
        ));
        echo '</div>';
        echo $this->Form->submit(__('Submit'), array(
            'div' => 'form-group',
            'class' => 'btn btn-default pull-left'
        ));
        echo $this->Form->end();
?>

This is the model Image where I validate everything:

public $useTable = false;

public $validate = array(
    'image_manager' => array(
        'uploadError' => array(
            'rule' => 'uploadError',
            'message' => 'Something went wrong with the file upload',
            'required' => TRUE,
            'allowEmpty' => FALSE,
        ),
        'photoSize' => array(
            'rule' => array('fileSize','<=','2MB'),
            'message' => 'Photo size must be less then 2MB.',
            'required' => TRUE,
            'allowEmpty' => FALSE,
        ),
        'mimeType' => array(
            'rule' => array('mimeType', array('image/gif','image/png','image/jpg','image/jpeg')),
            'message' => 'Invalid file, only images allowed',
            'required' => TRUE,
            'allowEmpty' => FALSE
        ),
        'processUpload' => array(
            'rule' => 'processUpload',
            'message' => 'Something went wrong processing your file',
            'required' => TRUE,
            'allowEmpty' => FALSE,
            'last' => TRUE,
        ),
        'type' => array()
    ),
);

And this is how I validate in the controller:

$this->Image->set($this->request->data['Image']['image_manager']);
if($this->Image->saveAll($this->request->data['Image']['image_manager'], array('validate' => 'only')))
{
    //do something
}else{
    echo '<pre>';
    debug($this->Image->validationErrors);
    echo '</pre>';
}

The thing is, when I try to validate it returns met a false + the error message of the first validation where required is set on true.

So let's say the required of uploadError is set on false and the required of filesize is set on true I will get a false back + the error message that is defined with filesize.

When all required are set on false the uploader works as intented but I am able to upload other files, files that are to big etc...

Now I do am fairly new to cakephp so it might be something stupid I'm missing. Perhaps one of you guys has an idea how this could validate properly. Thanks in advance.

EDIT This is an example of what image_manager contains when trying to upload files.

Array
(
    [0] => Array
    (
        [name] => Hydrangeas.jpg
        [type] => image/jpeg
        [tmp_name] => /tmp/phpWfut6N
        [error] => 0
        [size] => 595284
    )

    [1] => Array
    (
        [name] => Jellyfish.jpg
        [type] => image/jpeg
        [tmp_name] => /tmp/phpLmxQtx
        [error] => 0
        [size] => 775702
    )

    [2] => Array
    (
        [name] => Tulips.jpg
        [type] => image/jpeg
        [tmp_name] => /tmp/phpi69Hsl
        [error] => 0
        [size] => 620888
    )

)

SECOND EDIT ndm his answer was correct, after reformatting my data this is what the array looks like that I send to the saveAll function

Array
(
    [0] => Array
    (
        [image_manager] => Array
            (
                [name] => Hydrangeas.jpg
                [type] => image/jpeg
                [tmp_name] => /tmp/phpWfut6N
                [error] => 0
                [size] => 595284
            )

    )

    [1] => Array
    (
        [image_manager] => Array
            (
                [name] => Jellyfish.jpg
                [type] => image/jpeg
                [tmp_name] => /tmp/phpLmxQtx
                [error] => 0
                [size] => 775702
            )

    )

    [2] => Array
    (
        [image_manager] => Array
            (
                [name] => Tulips.jpg
                [type] => image/jpeg
                [tmp_name] => /tmp/phpi69Hsl
                [error] => 0
                [size] => 620888
            )

    )

)
ndm

Incorrect formatting for saving/validating many

As already pointed out in the comments, the format of the data is not correct for saving or validating many records, as shown in the docs it should be either

array(
    array('image_manager' => array('name' => 'a', 'type' => 'b', /* ... */)),
    array('image_manager' => array('name' => 'c', 'type' => 'd', /* ... */)),
);

or

array(
    array(
        'Image' => array(
            'image_manager' => array('name' => 'a', 'type' => 'b', /* ... */)
        )
    ),
    array(
        'Image' => array(
            'image_manager' => array('name' => 'c', 'type' => 'd', /* ... */)
        )
    ),
);

With the format you are currently using it would treat the keys name, type, etc as the fields to save/validate, rather than image_manager, hence the validation errors.


Reformat the data manually

Since you cannot change how the browser sends multiple files, you'll have to reformat the data manually before saving/validating it, for example like this (probably best suited in a method on your Image model):

App::uses('Hash', 'Utility');

$data = Hash::map($this->request->data['Image']['image_manager'], '{n}', function($value) {
    return ['image_manager' => $value];
});

This would give you the former format mentioned above, and you could then directly pass it to Model::saveAll() or Model::saveMany():

$this->Image->saveMany($data, ['validate' => 'only']);

Adjust your custom validation rules accordingly

Now with the changed format you'll most likely have to adjust your custom processUpload validation rule, as the data being passed to it will be formatted differently.

On a side note, in case that rule actually moves/stores your file on disk, this is not what validation should be responsible for, that's something that should better be done afterwards in the Model::beforeSave() or Model::afterSave() callback.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related