Images from Dropzone are lost after error on Validation with Laravel - php

So, i have this particular issue.
I have made a form with dropzone included, and the images are uploaded via AJAX, and everything is working from that point of view (selected images are stored, and can be deleted from the box).
So the problem is the following:
When i submit the form, and some validation error happens, the images i have uploaded are already on the server, but dont display on the dropzone form, i have to reupload them again, but then i just fill my storage with unwated data, and the images that were uploaded earlier before the validation cannot be accessed or deleted by any methods later on, so its basically junk data.
Is there any way to prevent this from happening? I would LOVE to show the already uploaded images after validation error (or refresh for example). If there cant be any solution for this, suggest me different approach.
Thanks.

I managed to get a working solution.
My thinking was following: If there are images posted, then using the $validator->fails() method i am deleting the images from the server.
Here is the complete code, if someone needs it:
// Validating the request
public function validate(Request $request){
$rules = []; //define your rules
$messages = []; //define your rules
// We make new validator with request data, rules and messages
$validator = Validator::make($request->all(), $rules, $messages);
// Deleting images if the validator fails
if($validator->fails()){
if(isset($request->images)){
foreach($request->images as $image){
// unlink your image here
}
}
return Redirect::back()->withInput()->withErrors($validator);
}
}
Then in the method store/edit (or custom method) just call:
public function store(Request $request){
// If it fails, return the redirect we defined.
if($this->validate($request)){
return $this->validate($request);
}
}
You can also define the validator directly in the store method, but since i use it few times in my Controller, i made a separate method just for it. We must return its value if we like to redirect back with the errors.
Cheers.

Related

In Yii2 how to validate multiple attributes together. Using AJAX

I have tried following this https://github.com/samdark/yii2-cookbook/blob/master/book/forms-validator-multiple-attributes.md
Unfortunately, it already has an issue raised that it no longer works with updates to Yii2 and I can't find any way to make it work.
I have two attributes which must be unique from each other. (Both are an array of strings.)
My validation logic works, but I can't find a way to display errors (or remove errors) on both attributes at the same time.
I have tried making a custom validator class, and also an inline validator, with the same problem:
When entering data in the form, only the attribute being edited will have its error message updated.
Below is the simplest version of my code that doesn't work, I want to display an error on both attributes after editing either one of them.
public function rules()
{
return [
[['attribute1', 'attribute2'], 'customValidator'],
];
}
// declare validator
public function customValidator($attribute, $params)
{
$this->addError('attribute1', 'error');
$this->addError('attribute2', 'error');
}

CakePHP 3 - validate data not tied to a table (validation without any database involvement)

Yesterday I posted a question CakePHP 3 - Using reusable validators but am still struggling to see how to validate data when it is not tied to a particular database table, or set of fields in a table.
What I'm trying to do is upload a CSV file. The data in the CSV may well end up in the database, but before any of that happens, I want to validate the file to make sure it's valid - extension is .csv, MIME type is text/csv, file size is <1 Mb. This particular validation has absolutely nothing to do with a database.
Where does such validation go, since it's nothing to do with a database table?
The approach I've used is as follows - but this does not work:
I have a UploadsController.php with an upload() method. This method handles the upload (form posts to /uploads/upload)
I have added the following to my src/Model/Table/UploadsTable.php (because I don't know where else to put such code):
public function validationDefault(Validator $validator)
{
$validator
->add('submittedfile', [
'mimeType' => [
'rule' => array('mimeType', array('text/csv')),
'message' => 'Upload csv file only',
'allowEmpty' => TRUE,
],
'fileSize' => [
'rule' => array('fileSize', '<=', '1MB'),
'message' => 'File must be less than 1MB.',
'allowEmpty' => TRUE,
]
]);
return $validator;
}
In UploadsController::upload() I have this:
if ($this->request->is('post')) {
debug($this->request->data['submittedfile']);
$uploads = TableRegistry::get('Uploads');
$entity = $uploads->newEntity($this->request->data['submittedfile']);
debug($entity);
}
No matter what file I upload, no errors are returned. Even if I comment-out the entire validationDefault method, the behaviour doesn't change.
This is becoming very frustrating as all of the documentation on Cake's website talks about data relating to DB tables. Well, what if you're trying to validate something that's nothing to do with a DB table?
I've opened this as a new question, because the last one doesn't really address this problem.
Other questions posted about this do not address this problem, because in this case they are writing the file info to a DB table, and therefore validating the file at the same time. In my case I'm not trying to do that, I just want to validate the file, before considering anything to do with the DB at all. I also want the code to validate a CSV to be re-usable (i.e. not in one specific Controller method) because if I want to check for a valid CSV in 5 different parts of the application, why should I repeat code that does the same thing all over?
Use a model-less form, it has validation built in, to validate your uploaded file. If you want your validation code to be reusable put it in a trait or separate class
In theory you could then do something like this:
$form = new CsvForm();
if ($this->request->is('post')) {
$result = $form->execute($this->request->getData());
if ($result && $this->Model->saveMany($result) {
$this->Flash->success('We will get back to you soon.');
} else {
$this->Flash->error('There was a problem submitting your form.');
}
}
Let your form validate the CSV document and return the pure CSV data, or already turn the rows into a set of entites you save.

Force Validation error in Laravel 5.1

Is there a way to force an error when using Validator Class in Laravel 5.1?
For now, I've done the traditional way calling $validator = Validator::make($request->all(), $rules), which is working fine. Also, I'm attempting to make another validation (manual one) and push it into $validator, but I can't get true when I call $validator->fails().
Even using $validator->errors()->add('field','message') I couldn't force it. Is there another way?
In order to make validation fail, you need to define a validation rule that won't be met. Easiest way is to require some non-existent field.
This will do the trick:
$rules['some_non_existent_field'] = 'required';
$validator = Validator::make($request->all(), $rules);
dd($validator->fails());
I had the same problem too
adding error to Validator doesn't make It to fail, so you need to make a trap for It that forces It to, maybe a required input that doesn't even exist...
but that will make a confusing error for user (example: unreal_input is required), you'd easily change the message to explain what actually made you to fail the process...
$req = Request::all();
$rules = [/*...*/];
if(/*something's wrong*/){
$rules['unreal_input'] = 'required'; // a confusing error in your errors list...
$messages['unreal_input.required'] = '/* explain the real problem in here*/';
}
$validator = Validator::make($req, $rules,$messages);
if ($validator->fails()) return redirect()->back()->withErrors($validator)->withInput();
so in the code above you've manually checked if something's wrong, then you've made a trap for Validator, then you've changed the message to what the real problem was.
NOTE: I suggest you to use a random value instead of something like unreal_input , because If you do this, the user may(?) guess the input's name, and easily using F12 he/she would pass the validation and give some invalid data to you

file field removed autometically on save yii model

I am trying to update a record which consist of a pdf file . record is updating successfully but the file field becomes empty on update .
my controller code is
$model2=$this->loadModel($alldata[0]->frm_id,'Forms');
$values=array();
$tagsarray=$_POST['searched_tag']; // matched tag values
$pdfval=$_POST['searched_tag_pdf']; // pdf form values
for($i=0;$i< count($pdfval);$i++)
{
$values[$pdfval[$i]]=$tagsarray[$i];
}
$model2->analyse_data=json_encode($values);
$model2->frm_status=2;
if($model2->save())
{
Yii::app()->user->setFlash('pdfupload','Form analysis done! data saved.');
$this->redirect(Yii::app()->createUrl('/formsupload'));
}else
{
Yii::app()->user->setFlash('pdfupload','Some error to save the data.');
$this->redirect(Yii::app()->createUrl('/formsupload'));
}
and model rules is
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('frm_code,frm_desc,frm_pdf', 'required'),
array('frm_code', 'unique'),
array('is_approve', 'safe'),
//array('desc', 'min'=>1, 'max'=>200)
array('frm_pdf', 'file', 'types'=>'pdf','allowEmpty'=>true),
);
}
Update
also tried this solution here
unable to catch the problem .
Handling file upload updates in yii can be a bit tricky. Try setting the file attribute to be unsafe and see if that helps. Yii seems to set the value of that attribute to null if it cannot find an uploaded file. Setting it to unsafe should prevent that.
You can check my answer at the yii forum link below to someone running into a similar problem for more info.
http://www.yiiframework.com/forum/index.php/topic/63506-how-can-i-update-records-without-adding-same-image-again/page__p__279888#entry279888

CakePHP form validation before sending post to the requested controller function

My validation is working as it stands, but I want to display the validation error prior to the search controller. I understand this might not be possible within the CakePHP framework.
I have a model plan.php. And in the plans_controller.php, I have a function called search().
My form calls search() as expected (because there is no search model):
echo $this->Form->create('Plan', array('action' => 'search'));
As it stands, when I submit my search, the errors are displayed and the url changes to .../search, so no results are displayed ("There are 0 results for that search criteria", but the correct validation errors are displayed below required form fields.
I do not want the .../search url to be displayed. I want the form to "halt" and just display the validation errors w/out changing the url to the search function.
I am calling the search form within an element because the search form displays on several different pages.
To sum this up: The search form should validate w/out changing the url path to the controller action name of the search. Of course, the validation is done IN the search() and plan.php model, so I just don't know how to work around this and wondering if its even possible.
You can use the validates() method of the model to check whether it validates and then redirect back.
Assuming your model is called Plan, this would be your controller
$errors = array();
if (!$this->Plan->validates($this->data)) {
//errors occured
$errors = $this->Plan->invalidFields();
$this->Session->save('Plan.errors', $errors);
$this->redirect('/plans');
}
And in your view.
if ($this->Session->check('Plan.errors')) {
$errors = $this->Session->read('Plan.errors');
$this->Session->delete('Plan.errors'); //don't want it again
}
In both cases, make sure Session helper/component is actually assigned to your view and controller
OK. Cracked out a working solution w/ implode, but now my errors are only displayed in the default layout and no longer under the form fields where that belong.. So now I need to know how to get the errors back below the form fields..
Working code:
...else {
$errors = $this->Plan->invalidFields();
$error_messages = implode(' ',$errors);
$this->Session->setFlash($error_messages);
$this->redirect('/');
}...

Categories