ProcessWire example front-end form with file upload and fields
<?php | |
// ------------------------------ FORM Processing --------------------------------------- | |
$errors = null; | |
$success = false; | |
// helper function to format form errors | |
function showError($e){ | |
return "<p class='error'>$e</p>"; | |
} | |
// dump some variables | |
// var_dump($_FILES,$_POST,$_SESSION); | |
/** | |
* Cast and save field values in array $form_fields | |
* this is also done even form not submited to make populating the form later easier. | |
* | |
* Also used for pupulating page when form was valid | |
*/ | |
$required_fields = array(); | |
foreach($form_fields as $key => $f){ | |
if($f['type'] == 'text'){ | |
$form_fields[$key]['value'] = $sanitizer->text($input->post->$key); | |
} | |
if($f['type'] == 'textarea'){ | |
$form_fields[$key]['value'] = $sanitizer->textarea($input->post->$key); | |
} | |
if($f['type'] == 'email'){ | |
$form_fields[$key]['value'] = $sanitizer->email($input->post->$key); | |
} | |
if($f['type'] == 'checkbox'){ | |
$form_fields[$key]['value'] = isset($input->post->$key) ? 1 : 0; | |
} | |
// store required fields in array | |
if($f['required']) $required_fields[] = $key; | |
} | |
/** | |
* form was submitted, start processing the form | |
*/ | |
if($input->post->action == 'send'){ | |
// validate CSRF token first to check if it's a valid request | |
if(!$session->CSRF->hasValidToken()){ | |
$errors['csrf'] = "Form submit was not valid, please try again."; | |
} | |
/** | |
* Ceck for required fields and make sure they have a value | |
*/ | |
foreach($required_fields as $req){ | |
// required upload file field | |
if($form_fields[$req]['type'] == 'file'){ | |
if(empty($_FILES[$req]['name'][0])){ | |
$errors[$req] = "Select files to upload."; | |
} | |
// reqired checkbox fields | |
} else if($form_fields[$req]['type'] == 'checkbox'){ | |
if($form_fields[$req]['value'] == 0){ | |
$errors[$req] = "Field required"; | |
} | |
// reqired text fields | |
} else if($form_fields[$req]['type'] == 'text' | |
|| $form_fields[$req]['type'] == 'textarea' | |
|| $form_fields[$req]['type'] == 'email'){ | |
if(!strlen($form_fields[$req]['value'])){ | |
$errors[$req] = "Field required"; | |
} | |
// reqired email fields | |
if($form_fields[$req]['type'] == 'email'){ | |
if($form_fields[$req]['value'] != $input->post->$req){ | |
$errors[$req] = "Please enter a valid Email address."; | |
} | |
} | |
} | |
} | |
/** | |
* if no required errors found yet continue file upload form processing | |
*/ | |
if(empty($errors)) { | |
// RC: create temp path if it isn't there already | |
if(!is_dir($upload_path)) { | |
if(!wireMkdir($upload_path)) throw new WireException("No upload path!"); | |
} | |
// setup new wire upload | |
$u = new WireUpload($file_field); | |
$u->setMaxFiles($max_files); | |
$u->setMaxFileSize($max_upload_size); | |
$u->setOverwrite($overwrite); | |
$u->setDestinationPath($upload_path); | |
$u->setValidExtensions($file_extensions); | |
// start the upload of the files | |
$files = $u->execute(); | |
// if no errors when uploading files | |
if(!$u->getErrors()){ | |
// create the new page to add field values and uploaded images | |
$uploadpage = new Page(); | |
$uploadpage->template = $template; | |
$uploadpage->parent = $parent; | |
// add title/name and make it unique with time and uniqid | |
$uploadpage->title = date("d-m-Y H:i:s") . " - " . uniqid(); | |
// populate page fields with values using $page_fields array | |
foreach($page_fields as $pf){ | |
if($templates->get($template)->hasField($pf)){ | |
$uploadpage->$pf = $form_fields[$pf]['value']; | |
} else { | |
throw new WireException("Template '$template' has no field: $pf"); | |
} | |
} | |
// RC: for safety, only add user uploaded files to an unpublished page, for later approval | |
// RC: also ensure that using v2.3+, and $config->pagefileSecure=true; in your /site/config.php | |
$uploadpage->addStatus(Page::statusUnpublished); | |
$uploadpage->save(); | |
// Now page is created we can add images upload to the page file field | |
foreach($files as $filename) { | |
$uploadpage->$file_field = $upload_path . $filename; | |
// remove tmp file uploaded | |
unlink($upload_path . $filename); | |
} | |
$uploadpage->save(); | |
// $success_message .= "<p>Page created: <a href='$uploadpage->url'>$uploadpage->title</a></p>"; | |
$success = true; | |
// reset the token so no double posts happen | |
// also prevent submit button to from double clicking is a good pratice | |
$session->CSRF->resetToken(); | |
} else { | |
// errors found | |
$success = false; | |
// remove files uploaded | |
foreach($files as $filename) unlink($upload_path . $filename); | |
// get the errors | |
if(count($u->getErrors()) > 1){ // if multiple error | |
foreach($u->getErrors() as $e) { | |
$errors[$file_field][] = $e; | |
} | |
} else { // if single error | |
$errors[$file_field] = $u->getErrors(); | |
} | |
} | |
} | |
} |
<?php | |
/** | |
* ### Example front-end form template with file upload and fields ### | |
* | |
* - with files (images) upload to page field | |
* - adds new page on the fly and adds uploaded images | |
* - prevents CRSF attacks, this also prevents double post by refresh page after submit | |
* - has required fields with error messages inline | |
* - sanitizing and saving values to a page | |
* - jquery example with disabled submit button on form submit | |
* | |
* Edit add or remove form markup below and configure this section according to what you need. | |
* | |
*/ | |
// ------------------------------ FORM Configuration --------------------------------------- | |
// --- Some default variables --- | |
$success_message = "<p class='message'>Thanks for your message!</p>"; | |
// --- All form fields as nested array --- | |
// using html form field name => template field nam, from the page you're going to create | |
$form_fields = array( | |
'fullname' => array('type' => 'text', 'value' => '', 'required' => true), | |
'email' => array('type' => 'email', 'value' => '', 'required' => true), | |
'message' => array('type' => 'textarea', 'value' => '', 'required' => true), | |
'newsletter_subscribe' => array('type' => 'checkbox', 'value' => 0, 'required' => false), | |
'images' => array('type' => 'file', 'required' => true) | |
); | |
// --- WireUpload settings --- | |
$upload_path = $config->paths->assets . "files/.tmp_uploads/"; // tmp upload folder | |
$file_extensions = array('jpg', 'jpeg', 'gif', 'png'); | |
$max_files = 3; | |
$max_upload_size = 1*1024*1024; // make sure PHP's upload and post max size is also set to a reasonable size | |
$overwrite = false; | |
// --- Page creation settings --- | |
$template = "upload-entry"; // the template used to create the page | |
$parent = $pages->get("/uploads/"); | |
$file_field = "images"; | |
$page_fields = array('fullname','email','message','newsletter_subscribe'); | |
// $page_fields = define the fields (except file) you want to save value to a page | |
// this is for the form process to populate page fields. | |
// Your page template must have the same field names existent | |
// ------------------------------ FORM Processing --------------------------------------- | |
include("./form-process.php"); | |
?> | |
<!-- ========================= FORM HTML markup ================================== --> | |
<?php | |
/** | |
* Some vars used on the form markup for error and population of fields | |
* | |
* $errors[fieldname]; to get errors | |
* $form_fields[fieldname]['value']; | |
* | |
* Some helper function to get error markup | |
* echo showError(string); | |
* | |
* Prevent CSRF attacks by adding hidden field with name and value | |
* you an get by using $session->CSRF | |
* $session->CSRF->getTokenName(); | |
* $session->CSRF->getTokenValue(); | |
* | |
* $errors['csrf']; used to check for CSRF error | |
* | |
*/ | |
?> | |
<div class="content"> | |
<h2>Upload Images to Page Example Form</h2> | |
<?php if(!$success) : ?> | |
<?php if(!empty($errors)) echo showError("Form contains errors"); ?> | |
<?php if(!empty($errors['csrf'])) echo showError($errors['csrf']); ?> | |
<form name="myform" class="myform" id="myform" method="post" action="./" enctype="multipart/form-data"> | |
<input type="hidden" name="<?php echo $session->CSRF->getTokenName(); ?>" value="<?php echo $session->CSRF->getTokenValue(); ?>"/> | |
<div class="row <?php if(isset($errors['fullname'])) echo "error";?>"> | |
<label for="fullname">Name* </label><br/> | |
<input type="text" name="fullname" id="fullname" value="<?php echo $sanitizer->entities($form_fields['fullname']['value']); ?>"/> | |
<?php if(isset($errors['fullname'])) echo showError($errors['fullname']); ?> | |
</div> | |
<div class="row <?php if(isset($errors['email'])) echo "error";?>"> | |
<label for="email">Email* </label><br/> | |
<input type="text" name="email" id="email" value="<?php echo $sanitizer->entities($form_fields['email']['value']); ?>"/> | |
<?php if(isset($errors['email'])) echo showError($errors['email']); ?> | |
</div> | |
<div class="row <?php if(isset($errors['message'])) echo "error";?>"> | |
<label for="message">Message* </label><br/> | |
<textarea type="text" name="message" id="message"><?php echo $sanitizer->entities($form_fields['message']['value']); ?></textarea> | |
<?php if(isset($errors['message'])) echo showError($errors['message']); ?> | |
</div> | |
<div class="row <?php if(isset($errors['newsletter_subscribe'])) echo "error";?>"> | |
<label for="newsletter_subscribe">Newsletter* </label><br/> | |
<input type="checkbox" name="newsletter_subscribe" id="newsletter_subscribe" | |
<?php echo $form_fields['newsletter_subscribe']['value'] ? "checked='checked'" : "" ; ?> | |
/> | |
<?php if(isset($errors['newsletter_subscribe'])) echo showError($errors['newsletter_subscribe']); ?> | |
</div> | |
<div class="row <?php if(isset($errors['images'])) echo "error";?>"> | |
<label for="images">Images* </label><br/> | |
<input type="file" name="images[]" id="images" multiple="multiple" size="40" accept="image/jpg,image/jpeg,image/gif,image/png"/> | |
<?php | |
// show upload errors | |
if(isset($errors['images'])){ | |
// if multiple errors | |
if(is_array($errors['images'])){ | |
foreach($errors['images'] as $e){ | |
echo showError($e); | |
} | |
} else { // if single error | |
echo showError($errors['images']); | |
} | |
} | |
?> | |
</div> | |
<div class="row"> | |
<input type="hidden" name="action" id="action" value="send"/> | |
<input type="submit" name="submit" id="submit" value="Submit"/> | |
</div> | |
</form> | |
<?php else: ?> | |
<p><?php echo $success_message; ?></p> | |
<?php endif; ?> | |
</div> |
<!-- ========================= FORM Styling ================================== --> | |
<style> | |
/* basic CSS styling */ | |
.content { width: 30em; margin: 0 auto ;} | |
.error { color: red;} | |
.myform { padding: 1.618em 0; margin: 0 0 1em 0; border: 1px solid #bbb;} | |
.myform p.error { margin: 0.5em 0; border: 1px solid red; padding: 2px 5px;} | |
.myform .row { padding: 1.618em 0 0; margin: 0 1.618em 1.618em; border-top: 1px solid #aaa; } | |
.myform input[type="text"] { padding: 0.8em; background-color: #eee; border: none; width: 100%; } | |
.myform textarea { padding: 0.8em; background-color: #eee; border: none; width: 100%; } | |
</style> |
<!-- ========================= FORM jQuery Script ================================== --> | |
<script src="<?php echo $config->urls->templates . "scripts/jquery-1.7.1.min.js"; ?>"></script> | |
<script> | |
$(function(){ | |
// Avoid double posts by disabling submit button on form submit | |
$('#myform').submit(function(){ | |
$("#submit").attr('disabled','disabled'); | |
return true; | |
}); | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment