I'm working on Zend Framework 1.11.12 version. In my add form where we've to put file upload (for photo upload) field and it has few validations as required, file extensions and size specific criteria mentioned as below, which is declared under my zend form:
// part of my form class (Default_Form_Photo::init)
$photo = new Zend_Form_Element_File('photo', '', array('required' => true));
$photo->setLabel('Photo')
->setDestination('/var/www/zendframework/public/uploads/');
// ensure its mandatory
#$photo->addValidator('required', true);
// ensure only one file
$photo->addValidator('Count', false, array('min' => 1));
// max 2MB
$photo->addValidator('Size', false, 2097152)
->setMaxFileSize(2097152);
// only JPEG, PNG, or GIF
$photo->addValidator('Extension', false, 'jpg,jpeg,png,gif');
$photo->setValueDisabled(true);
$this->addElement($photo, 'photo');
Now I have taken a hidden field, for edit page which will return me current image name, if no new image uploaded:
// hidden element for edit time photo save
$this->addElement('hidden', 'photo_uploaded', array( ));
I set this hidden element value from controller by $form->photo_uploaded->setValue($result['photo']).
Now the problem is: when user edit information, it does not allow saving because the file upload field is blank as no new image uploaded, but in my case have to use existing current image, which I am passing from hidden element to my controller.
So validation causes problem here, any idea how can i remove validation for my edit page where users do not have to upload new image every time, they are editing information.
Earliest response will be appreciated.
Thanks !
The answer to this requires you to add two functions to your form: isValid and getValues. First of all, remove required from the photo element as we are going to check for this in isValid:
/**
* Check if a photo has been submitted. If not, set the form element as required.
* #param $data Array of values
* #return Boolean true if all form element requirements are mets
*/
public function isValid($data)
{
//A photo has not been uploaded this time, nor previously.
if(!$data['photo'] AND !$data['photo_uploaded'])
{
$this->photo->isRequired(TRUE);
}
return parent::isValid($data);
}
/**
* Return an array of form element values
* #return Array of values
*/
public function getValues()
{
$values = $this->getValues();
//if photo has been uploaded, but no previous photos have been uploaded, then set photo_uploaded value.
if($values['photo'] AND !$values['photo_uploaded'])
{
$values['photo_uploaded'] = $values['photo'];
}
//if previous photo has been uploaded, but photo has not been uploaded this time, set photo value
if($values['photo_uploaded'] AND !$values['photo'])
{
$values['photo'] = $values['photo_uploaded'];
}
return $values;
}
Related
Within Laravel, I am successfully able to have a user upload a file on a page, but I want to know if there is a way for there to be an error displayed to that user before they submit the page that the file is too big. Something like "The file you selected to upload is 25MB. Get it below 20MB."
Is there some kind of package that can handle this?
Validating the file size on client side. (Mentioning this because you have mentioned that you would like to alert the error before form submit.)
Check the example code below which uses jQuery :
$(document).ready(function() {
$('input[type="file"]').change(function(event) {
var fileSize = this.files[0].size;
var maxAllowedSize = //add your value here;
// check the file size if its greater than your requirement
if(size > maxAllowedSize){
alert('Please upload a smaller file');
this.val('');
}
});
});
Validation on server side(you can change mime types as per the file type you want to allow) :
<?php
public function store(Request $request){
$request->validate([
'file_input_name' => 'file|max:25000|mimes:jpeg,bmp,png',
// add validations for other fields here
]);
}
For more check documentation
You don't need a package to do this, you can create either a Request class or use a validator:
1. Create a Request class:
Run the command php artisan make:request FileRequest
Then, on the File generated under App\Http\Requests\FileRequest do the following:
Change the authorize method to return true instead of false.
Under the rules method you return your validation rules:
return [
"file_input" => "max:20480", //If your input type's file name is "file_input"
];
According to documentation, max rule verifies that the input size from the user will not exceed the specified number in kilobytes for files.
2. You can also create a validator in your controller method:
use Validator;
public function store(Request $request)
{
$validator = Validator::make($request->only('file_input'), [
'file_input' => 'max:20480',
]);
if ($validator->fails()) {
return redirect()
->route('your.route.name')
->withErrors($validator)
->withInput();
}
// other code here
}
I have a single input field (using select2 plugin) in a blog post form which allow user to insert post tags from existing tags in the table or create new ones and store them in the Tag table and also attach them to the post when they hit submit post button. I've managed to get this work by filtering the input with array_filter(), if the input is !is_numeric the input will first get stored in Tag table and then attach the id to the post.
The problem with this is that it's not working when the new tag from the input is in full numeric type, like 2017 tag. Is there a solution to get this working so the new tag is not limited to string only but also numeric type ? and if possible, I don't want to use any package for this.
The post store method :
public function store(PostsReq $request) {
$input = $request->all();
$post = Post::create($input);
//Handle the tags
$getTags = $request->input('tagspivot');
$oldTags = array_filter($getTags, 'is_numeric');
$newTags = array_filter($getTags, function($item) {
return !is_numeric($item);
});
foreach ($newTags as $newTag) {
if ($tag = Tag::create(['title' => strtolower(trim($newTag))])) {
$oldTags[] = $tag->id;
}
}
$post->tags()->attach($oldTags);
// Upload Image
if ($request->hasFile('image')) {
$input['image'] = $this->uploadImage($request, $post);
}
return redirect()->route('postindex')->with($this->postStoreSuccess);
}
Here is three lines of code would be more than enough:
$tag = Tag::firstOrCreate([
'title' => $request->input('tagspivot'),
]);
You don't need to check for !is_numeric. However, in your form don't use tag id as value. use the title.
I have a registration form that need to upload image as profile image during registration, I want to remove this uploading field from registration form as the user can upload it later but the problem is the registration form is connected to image process so the field can not be empty, this is the code for store propose inside registration controller:
public function store(RegisterUserRequest $request)
{
$newUserProfileImagePath = $profileImagePath = App::make('ProcessImage')->execute($request->file('profileimage'), 'images/profileimages/', 180, 180);
$newUserBirthday = Carbon::createFromDate($request->year, $request->month, $request->day);
$newUser = $this->dispatchFrom(RegisterUserCommand::class, $request, [
'birthday' => $newUserBirthday,
'profileImagePath' => $newUserProfileImagePath
]);
return redirect()->route('feeds_path');
}
How can I give a default value or disconnect it from image process?
You can set value like this:
$newUserProfileImagePath = $profileImagePath = "any image path";
OR you can try to remove All things about file uploading from this method and from this class "RegisterUserCommand. and after this you are still facing error then please upload "RegisterUserCommand" class. I will give you more instructions.
Happy Coding!
I have a script that pulls in data from a 3rd party file. My import simply parses and inserts rows, which is working fine.
The problem comes with images.
When the import script runs, it first deletes all the current items and then the import begins, inserting all products and images into the gallery.
On the first import, everything is fine, the images go in and I see them on the frontend no problem. The problem comes with everytime I then re-import these products, it doesn't seem to delete all images, as when the products re-import, I see, for example the 4 images correct, then then loads of blank rows, like images should be there, but can't be found.
I don't want to see these blank lines, but I'm not sure why they are there.
Could it be because the images for the product are already in the catalogue?
I am really unsure what and why this is doing what it is.
Thanks
EDIT:
My code is:
require_once('app/Mage.php');
$app = Mage::app('default');
$product = Mage::getSingleton('catalog/product');
$txt_file = file_get_contents('test.txt');
$rows = explode("\n", $txt_file);
array_shift($rows);
foreach($rows as $row => $data)
{
//get row data
$row_data = explode('^', $data);
$info[$row]['uniqueid'] = $row_data[0];
$info[$row]['client'] = $row_data[1];
$info[$row]['make'] = $row_data[2];
$info[$row]['model'] = $row_data[3];
$info[$row]['adtext'] = $row_data[4];
//display images
$row_images = explode(',', $info[$row]['picturereference']);
foreach($row_images as $row_image)
{
$product->addImageToMediaGallery(Mage::getBaseDir('media') . DS . 'import/' . $row_image, array('image', 'small_image','thumbnail'), false, false);
}
$product->setStoreId(Mage::app()->getStore(true)->getWebsite()->getId());
$product->setWebsiteIds(array(Mage::app()->getStore(true)->getWebsite()->getId()));
$product->setId($info[$row]['id']);
$product->setSku(strtolower($info[$row]['make']).'-'.strtolower($info[$row]['model']));
$product->setName($info[$row]['make']);
$product->setDescription($info[$row]['adtext']);
try {
$product->save();
echo "Saved";
}
catch (Exception $ex) {
echo "<pre>".$ex."</pre>";
}
}
Is this because the addImageToMediaGallery is called on each iteration and adding all images to each product?
Thanks
Ok so I figured out my problem
Inside the foreach I moved the call to the getSingleton and I added the the following: $product = Mage::getModel('catalog/product');
I then, after each iteration, unset the following:
unset($product);
unset($info);
unset($stockData);
unset($row_images);
This seemed to fix my script and now imports each products images into the proper product rather than importing other and adding random blank entries
Thanks all
A few files you'll want to examine to break down addImageToMediaGallery and determine what exactly its doing.
app/code/core/Mage/Catalog/Model/Product.php - Contains the method your using, breaking it down more you'll find...
app/code/core/Mage/Catalog/Model/Product/Attribute/Backend/Media.php - Contains more of the "bits and pieces" of addImageToMediaGallery like addImage etc.
Some possibilities to try would be either
A) determine if the files already exist and are attached to the product and ignoring them upon a second round of import. Perhaps looking for different file stamp. getMediaGalleryImages within Product.php.
B) clear the media files associated with the products BEFORE importing again? clearMediaAttribute and removeImage within Media.php.
I would also try the $move option set to true within your addImageToMediaGallery call as well.
/**
* Add image to media gallery
*
* #param string $file file path of image in file system
* #param string|array $mediaAttribute code of attribute with type 'media_image',
* leave blank if image should be only in gallery
* #param boolean $move if true, it will move source file
* #param boolean $exclude mark image as disabled in product page view
*/
public function addImageToMediaGallery($file, $mediaAttribute=null, $move=false, $exclude=true)
{
Another option would be to try to specify null for the second param, if you note the PHPDoc comments, leaving it blank will only be for the gallery which sounds like what you are wanting...
foreach($row_images as $row_image)
{
$product->addImageToMediaGallery(Mage::getBaseDir('media') . DS . 'import/' . $row_image, null, false, false);
}
Let me know if any of these help.
Give something like this a try:
//Check if gallery attribute exists then remove all images if it exists
//Get products gallery attribute
$attributes = $product->getTypeInstance()->getSetAttributes();
if (isset($attributes['media_gallery'])) {
$gallery = $attributes['media_gallery'];
//Get the images
$galleryData = $product->getMediaGallery();
foreach($galleryData['images'] as $image){
//If image exists
if ($gallery->getBackend()->getImage($product, $image['file'])) {
$gallery->getBackend()->removeImage($product, $image['file']);
}
}
}
This blog posting may also help, as its where I got the code snippet form also:
http://www.sharpdotinc.com/mdost/2010/03/02/magento-import-multiple-images-or-remove-images-durring-batch-import/
I'm building an admin utility for adding a bulk of images to an app I'm working on. I also need to to log certain properties that are associated with the images and then store it all into the database.
So basically the script looks into a folder, compares the contents of the folder to records in the database. All of the info must be entered in order for the database record to be complete, hence the form validation.
The validation is working, when there are no values entered it prompts the entry of the missing fields. However it happens even when the fields ARE filled.
I'm doing something a bit funny which may be the reason.
Because I'm adding a bulk of images I'm creating the data within a for loop and adding the validation rules within the same for loop.
Here is the results:
http://s75151.gridserver.com/CI_staging/index.php/admin_panel/bulk_emo_update
Right now I have default test values in the form while testing validation. The submit button is way at the bottom. I'm printing POST variable for testing purposes.
Here is the code:
function bulk_emo_update() {
$img_folder_location = 'img/moodtracker/emos/';//set an image path
$emo_files = $this->mood_model->get_emo_images('*.{png,jpg,jpeg,gif}', $img_folder_location); //grab files from folder
$emo_records = $this->mood_model->get_all_emos(); //grab records from db
$i=1; //sets a counter to be referenced in the form
$temp_emo_info = array(); //temp vairable for holding emo data that will be sent to the form
//loop through all the files in the designated folder
foreach($emo_files as $file) {
$file_path = $img_folder_location.$file;//builds the path out of the flder location and the file name
//loops through all the database reocrds for the pupose of checking to see if the image file is preasent in the record
foreach($emo_records as $record) {
//compairs file paths, if they are the
if($record->picture_url != $file_path) {
//FORM VALIDATION STUFF:
$rules['segment_radio['.$i.']'] = "required";
$rules['emo_name_text_feild['.$i.']'] = "required";
//populating the temp array which will be used to construct the form
$temp_emo_info[$i]['path'] = $file_path;
$temp_emo_info[$i]['name'] = $file;
}
}
$i++;
}
//sets the reference to validation rules
$this->validation->set_rules($rules);
//checks to see if the form has all it's required fields
if ($this->validation->run() == FALSE) { //if validation fails:
print_r($_POST);
//prepairs the data array to pass into the view to build the form
$data['title'] = 'Bulk Emo Update';
$data['intro_text'] = 'fill out all fields below. hit submit when finished';
$data['emos_info'] = $temp_emo_info;
$this->load->view('admin_bulk_emo_update_view',$data);
} else { // if it succeeds:
//printing for test purposes
print_r($_POST);
$this->load->view('form_result');
}
}
I'm new to codeigniter and php in general so if anything looks outrageously weird please tell me, don't worry about my feelings I've got thick skin.
if ($this->validation->run() == FALSE)
if you are calling the run() method of the validation class every time the script is run, will it ever return TRUE and run the else? Maybe a different return?
I'm a little cornfused by what's going on. Generally, if I'm having a problem like this, I will figure out a way to force the result I'm looking for. e.g. in your code, I'd force that else to run... once I get it to run, break down what happened to make it run. Rudimentary, but it has served me well.
You use array of rules in
$this->form_validation->set_rules()
wrong.
If you want to pass the rules in array you must stick to the key names like described here http://codeigniter.com/user_guide/libraries/form_validation.html#validationrulesasarray
So instead of
$rules['input_name'] = "required"
try this:
array(
'field' => 'input_name',
'label' => 'Name that you output in error message',
'rules' => 'required'
)