0

I am trying to Upload a photo for one of the models and when i am going to the edit mode. It still asks me to upload the photo when the user only wants to edit the text related to that record. Below is my Validation Rules.

    'display_photo' => array(
        'uploadError' => array(
            'rule' => array('uploadError'),
            'message' => 'Please select a Photo.',
            'allowEmpty' => true,
        ),
        'mimeType' => array(
            'rule' => array('mimeType', array('image/gif', 'image/png', 'image/jpg', 'image/jpeg')),
            'message' => 'Please only upload images (gif, png, jpg).',
            'allowEmpty' => true,
        ),
        'fileSize' => array(
            'rule' => array('fileSize', '<=', '5MB'),
            'message' => 'Photo must be less than 5MB.',
            'allowEmpty' => true,
        ),
        'photoUpload' => array(
            'rule' => array('photoUpload'),
            'message' => 'Unable to process Photo upload.',
            'allowEmpty' => true,
        ),
    ),

Upload Function

   public function photoUpload($check = array()) {
        if (!is_uploaded_file($check['display_photo']['tmp_name'])) {
            return false;
        }

        if (!move_uploaded_file($check['display_photo']['tmp_name'], WWW_ROOT . 'img' . DS .
            'portfolios' . DS . $this->data[$this->alias]['slug'].".".pathinfo($check['display_photo']['name'], PATHINFO_EXTENSION))) {
            return false;
        }
        $this->data[$this->alias]['display_photo'] = $this->data[$this->alias]['slug'].".".pathinfo($check['display_photo']['name'], PATHINFO_EXTENSION);
        return true;
    }
Harsha M V
  • 54,075
  • 125
  • 354
  • 529

4 Answers4

2

set the parameter

'on' => 'create'

just for the 'uploadError' rule

'uploadError' => array(
    'rule' => array('uploadError'),
    'message' => 'Please select a Photo.',
    'on' => 'create',
),

This way cake will force the user to upload an image just when the record is created.

The other validation rules, intead, will always be valid, but only if a file is actually uploaded.

see the manual

arilia
  • 9,373
  • 2
  • 20
  • 44
  • i want to validate the file. only if the file is selected when the record is being edited – Harsha M V Jun 07 '14 at 09:20
  • i tried that. but still its going through all the other validations as well. – Harsha M V Jun 09 '14 at 11:00
  • 1
    @HarshaMV I tried that code too and here's what happens: 1 - when I create the record I get validation error if I leave the field empty or if the file is not valid. 2 - when I update the record I get validation errors only if I upload a new ivalid file and not if I leave the field empty. At this point I think the proble is in your custom validation rule so please update your question with the code form your `photoUpload` rule – arilia Jun 09 '14 at 14:01
2

uploadError expects an upload

The code for uploadError expects an upload:

public static function uploadError($check) {
    if (is_array($check) && isset($check['error'])) {
        $check = $check['error'];
    }

    return (int)$check === UPLOAD_ERR_OK;
}

If there is no file uploaded the error will not contain that value - it'll be UPLOAD_ERR_NO_FILE.

File uploads are never empty

Putting 'allowEmpty' => true, in the rule definition won't have any effect as the value, if present, will never be empty - it's always of the form:

array(
    ...
    'error' => int
)

As such it's best to remove allowEmpty from all the file-upload validation rules.

Use beforeValidate

Instead of dealing with the validation rules, you can instead use beforeValidate to simply remove the file upload data before the validation check is made:

public function beforeValidate() {
    if (
        isset($this->data[$this->alias]['display_photo']) &&
        $this->data[$this->alias]['display_photo']['error'] === UPLOAD_ERR_NO_FILE
    ) {
        unset($this->data[$this->alias['display_photo']);
    }
    return parent::beforeValidate();
}

In this way the validation rules for display_photo are skipped entirely if there is no upload to process.

Community
  • 1
  • 1
AD7six
  • 63,116
  • 12
  • 91
  • 123
  • 1
    @HarshaMV I'm not sure why, as it doesn't influence the question/answer. On an unrelated point it's not normal to "do" anything when validating data - moving files should occur on save. – AD7six Jun 16 '14 at 18:17
  • any reference on how i can handle uploads? the existing plugins build a very complex folder structure which i do not need. i should be able to provide a folder name and just start dumping the images in to that folder for the particular model. – Harsha M V Jun 17 '14 at 05:09
  • 1
    What you're doing is fine - but it should be in beforeSave or afterSave (depending on your preference). – AD7six Jun 17 '14 at 06:22
  • thank you. will change it and get back to you if i get stuck. – Harsha M V Jun 17 '14 at 07:04
1

Try this approach, I used this several times. Replace 'Model' with your model name.

if($this->request->data['Molel']['display_photo']['name']!=''){
    // put your code here for upload image
else
{
    unset($this->request->data['Model']['display_photo']); // this will exclude this from validation
}
Krishna
  • 1,540
  • 2
  • 11
  • 25
-1

Use required = false and in your controller unset the array field that is not needed for validation based on the application logic.

user221931
  • 1,852
  • 1
  • 13
  • 16
  • didnt get u. please elaborate – Harsha M V Jun 07 '14 at 10:00
  • Sure. If you make a validation rule not required, if cake doesn't find the field in the passed array to validate, it won't complain. This is different to allowing it being empty (which means to exist). If the field comes from your view to your controller and you don't need it you can unset it there. Alternatively you can change the validation rules on the fly from the controller. – user221931 Jun 07 '14 at 14:53
  • is there any way to do it with out all the manual unsetting ? – Harsha M V Jun 09 '14 at 08:05
  • You can't have a computer guess what you want to do. You want a field to be checked by two different sets of rules depending on the situation. This has to be decided by "manually" enforcing the desired application logic in your controller or creating a custom validation rule. In this case I'd go with unsetting the unnecessary field, you can choose what you like. – user221931 Jun 09 '14 at 20:41