Ive been looking for ages for some information about how to create a form for users to submit their information and a file
How i want it to work:
The information must go to my email
The file to go to a folder on the websites sever
One of those Anti Spam things
I would prefer if i could have this in a category page though i assume it could be applied in more than that place.
Running Opencart version 1.5.1.3
Any help is greatly appreciated
Thanks
Bob
Feel free to take a look at the screenshots and demo site, and if you're interested let me know at www.getclearthinking.com/contact if you have any further questions.
I'm currently implementing a custom form into an Information page, and would be happy to share with you how it is done once this contract is finished. If you aren't in too much of a hurry, I had been thinking of writing up a tutorial on it sometime next week (Feb 28 - Mar 1)-ish.
At the moment the form doesn't require any files to be uploaded so we'll see if I get that in there, but you should be able to get the gist of how to add it to a category page even if I'm talking about adding it to an Information page.
I heart cmd-f, cmd-c, cmd-v, cmd-z + vQmod.
My favourite page...
v1.5.4.1
For the love of God don't spend money on a simple contact form and file upload. OC is chalked full of forms that use basic HTTP POST to send data where it needs to go.BobDougan wrote:Hi
Ive been looking for ages for some information about how to create a form for users to submit their information and a file
How i want it to work:
The information must go to my email
The file to go to a folder on the websites sever
One of those Anti Spam things
I would prefer if i could have this in a category page though i assume it could be applied in more than that place.
Running Opencart version 1.5.1.3
Any help is greatly appreciated
Thanks
Bob
Perhaps entertain doing this:
1) First realize that you are using an MVC(model-view-control) framework so you will be needing to create or alter at least 2 of the 3 files, probably just the view and control if you are not bothering your Database. The files will go in the, you guessed it, the view folder, control folder, and if you use a model file the model folder.
You will be using one of the many all ready existing forms that are all through out open cart along with upload code the works fine. You will also be using existing code to send an email to yourself. It's all there.
Down the road I hope to turn this into a VQmod, but for the time being you'll need to be comfortable with just altering core files of OpenCart. Best thing here is to make a backup of the original file and just keep it in the same directory in case you need to backtrack. You'll want to be especially careful when upgrading OpenCart that you make a copy of these modified files before upgrading otherwise you'll lose these changes.
These are the files you will be editing:
/catalog/controller/information/information.php (Information Controller)
/catalog/language/YOUR LANGUAGE/information/information.php (Information Language)
/catalog/view/theme/YOURTHEME/template/information/information.tpl (Information Template)
You'll need these file for reference and to glean some code out of:
/catalog/controller/information/contact.php (Contact Controller)
/catalog/view/theme/YOURTHEME/template/information/contact.tpl (Contact Template)
/catalog/language/YOUR LANGUAGE/information/contact.php (Contact Language)
Step 1:
- Open Contact Template and locate the <form> element in the file.
- Copy everything between <form> and </form>.
- Open Information Template and after the line <?php echo description; ?> paste the form content you just copied.
- Where the it says: <form action="<?php echo $action; ?>"... > just make action="" to tell the form to call itself
Step 2:
- Edit the form to your liking. This is going to require some knowledge of how to format an HTML form, but the vast majority of what you will likely need is right there.
- Once you've added your input, textarea, select, checkbox, radio, etc. etc. options take note of the various PHP variable names. You should see something similar to:
Code: Select all
<?php echo $error_name; ?>
Step 3:
- Open the Information Controller file and declare an array named 'error' at the top. This is very important because you will get some errors when trying to submit the form without this.
Code: Select all
class ControllerInformationInformation extends Controller {
private $error = array(); // <-- add this line right here!
public function index() {
.....
Code: Select all
public function index() {
$this->language->load('information/information');
$this->load->model('catalog/information');
/* Begin adding custom content here */
/**
* In the form data you copied over from the Contact Template you will
* have noticed that there were little bits of code that looked like:
* <?php echo $entry_name; ?>
*
* These variables need to be defined here, and then we'll set them later
* in the Information Language file. Just go ahead and set one of the below
* for each of them that appear in your form.
*/
$this->data['text_name'] = $this->language->get('text_name');
/**
* Now as for sending the mail, you'll want to add the following. I have some changes
* in here from what you will see in the Contact Controller file because I didn't just want to
* send the 'comments' field as the body of my message.
*/
if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
$mail = new Mail();
$mail->protocol = $this->config->get('config_mail_protocol');
$mail->parameter = $this->config->get('config_mail_parameter');
$mail->hostname = $this->config->get('config_smtp_host');
$mail->username = $this->config->get('config_smtp_username');
$mail->password = $this->config->get('config_smtp_password');
$mail->port = $this->config->get('config_smtp_port');
$mail->timeout = $this->config->get('config_smtp_timeout');
$mail->setTo($this->config->get('config_email'));
$mail->setFrom($this->request->post['email']);
$mail->setSender($this->request->post['name']);
/**
* Here I set some custom content for the body of the e-mail. You can change this
* or remove it, etc. Seemed to work well for me to get more than just the 'comments'
* field in the email body.
*/
$email_body = 'Name: ' . $this->request->post['name'] . "\n\r";
$email_body .= 'Company: ' . $this->request->post['company'] . "\n\r";
$email_body .= 'Phone: ' . $this->request->post['phone'] . "\n\r";
$email_body .= 'Email: ' . $this->request->post['email'] . "\n\r";
$email_body .= 'Comments: ' . $this->request->post['enquiry'] . "\n\r";
$mail->setSubject(sprintf("Outfitters Request Form", $this->request->post['name']));
$mail->setText(strip_tags(html_entity_decode($email_body, ENT_QUOTES, 'UTF-8')));
$mail->send();
$this->redirect($this->url->link('information/contact/success'));
}
/**
* You will need one of these for every required element in your form.
* So if you have a form with input elements 'name', 'phone', 'email' and
* all are required, then do the following once for each of those input fields.
*/
if (isset($this->error['name'])) {
$this->data['error_name'] = $this->error['name'];
} else {
$this->data['error_name'] = '';
}
// and you will want this at the end of your error declarations
if (isset($this->error['captcha'])) {
$this->data['error_captcha'] = $this->error['captcha'];
} else {
$this->data['error_captcha'] = '';
}
/**
* You will need one of these for every element in your form because
* if a user fails to fill out the form correctly you don't want them to have
* to type everything out again.
*/
if (isset($this->request->post['name'])) {
$this->data['name'] = $this->request->post['name'];
} else {
$this->data['name'] = '';
}
// and again, you don't want to forget your CAPTCHA variable
if (isset($this->request->post['captcha'])) {
$this->data['captcha'] = $this->request->post['captcha'];
} else {
$this->data['captcha'] = '';
}
Second, we added a bunch of variable declarations and a mail function to the Information Controller. These are necessary because if you don't declare these variables in here OpenCart is going to get all freaky on you when you reload the page.
Well then. Let's carry on.
Step 3:
Still in the Information Controller file you will want to scroll down to the very bottom, and directly before the last curly bracket } you will want to carriage-return a few times and make yourself some space for the following.
Code: Select all
/**
* Here was get the CAPTCHA working correctly so that you
* reduce your spam getting chances. No changes necessary
* in the captcha() function. Just copy and paste.
*/
public function captcha() {
$this->load->library('captcha');
$captcha = new Captcha();
$this->session->data['captcha'] = $captcha->getCode();
$captcha->showImage();
}
/**
* This function you will notice was called up above when we tried to
* send an e-mail. If the following doesn't evaluate to TRUE then you
* are not going to be able to send an e-mail.
*/
private function validate() {
/**
* Here is where you need to set up the validation that will keep your
* form from submitting until everything required is filled in correctly.
*
* This is where that very first declaration of private $error = array();
* becomes necessary. These errors will get assigned to that array above,
* and if these exist will be output on the Information View page below each
* input element that wasn't filled in correctly. You can easily move these
* error elements around on the form by moving the <?php echo $error_name; ?>
* lines. (or whatever the error is you are targeting: email, phone, etc.)
*/
if ((utf8_strlen($this->request->post['name']) < 3) || (utf8_strlen($this->request->post['name']) > 32)) {
$this->error['name'] = $this->language->get('error_name');
}
if (!preg_match('/^[^\@]+@.*\.[a-z]{2,6}$/i', $this->request->post['email'])) {
$this->error['email'] = $this->language->get('error_email');
}
if ((utf8_strlen($this->request->post['phone']) < 7) || (utf8_strlen($this->request->post['phone']) > 3000)) {
$this->error['phone'] = $this->language->get('error_phone');
}
if ((utf8_strlen($this->request->post['enquiry']) < 10) || (utf8_strlen($this->request->post['enquiry']) > 3000) && $this->request->get['information_id'] == 10)) {
$this->error['enquiry'] = $this->language->get('error_enquiry');
}
/**
* I left this following one in because this is a useful example of how you
* can create separate forms on more than one Information Page.
* Essentially what I'm asking OpenCart to do is tell me if we are on a
* specific Information Page that has a form, and if so, execute the
* following code.
*
* In this case, I had two different forms on different Information Pages
* and if I didn't wrap certain elements in this tag it would cause some
* serious issues if I tried to submit one form that didn't have required
* elements from the other!
*
* But if you aren't concerned about having multiple forms, just get rid of
* that first if ($this->request->get['information_id'] == 9) { part.
*/
if ($this->request->get['information_id'] == 9) {
if ((utf8_strlen($this->request->post['product']) < 3)) {
$this->error['product'] = $this->language->get('error_product');
}
if ((utf8_strlen($this->request->post['prod_description']) < 3)) {
$this->error['prod_description'] = $this->language->get('error_prod_description');
}
}
if (!isset($this->session->data['captcha']) || ($this->session->data['captcha'] != $this->request->post['captcha'])) {
$this->error['captcha'] = $this->language->get('error_captcha');
}
/**
* This just tells the page if the form was submitted correctly.
*/
if (!$this->error) {
return true;
} else {
return false;
}
}
Step 4:
Open the Information Language file and add the following. Please read the comments in the code section as a straight copy/paste of this probably won't work for your individual needs.
Code: Select all
/**
* Define each of your various errors here. These are going to be loaded in
* as the default errors for your form. If you remember toward the beginning
* of the Information Controller file we declared a few items such as:
* $this->data['error_name'] = $this->error['name']
* Well this is where it is getting that information from.
*/
// Errors
$_['error_name'] = 'Name must be between 3 and 32 characters!';
$_['error_email'] = 'E-Mail Address does not appear to be valid!';
$_['error_enquiry'] = 'Enquiry must be between 10 and 3000 characters!';
$_['error_captcha'] = 'Verification code does not match the image!';
$_['error_phone'] = 'Phone number must be at least 7 characters!';
$_['error_quant'] = 'Please select at least 1 item of interest and a quantity!';
$_['error_prod_description'] = 'Please provide a description of your product!';
$_['error_product'] = 'Please provide a name for your product!';
/**
* And as I had mentioned before, we now need to set the language for
* some of these other form variables such as $entry_name
*
* Just edit the below line and create as many as you need. Just remember
* to rename the 'entry_name' to whatever the variable name is your calling.
*/
$_['entry_name'] = 'First Name:';
...
If not, well then please let me know and I'll try and answer your questions.
Also, rather than messing around with the information template file, could we just add the <form></form> data into the information page via admin? (ie. in the hmtl box when you're setting up an new info page).
I heart cmd-f, cmd-c, cmd-v, cmd-z + vQmod.
My favourite page...
v1.5.4.1
Seems that on line 328 you've got an extra curly bracket closing out the index() function early. Just delete that and see if it helps. The line you want to look for is:
Code: Select all
$this->redirect($this->url->link('information/contact/success'));
I've updated my post from earlier because I realize I had included an extra curly bracket which would certainly cause this exact havoc on your system.
As for adding the <form> element directly in the WYSIWYG editor, it will html_encode all that stuff and not function. Rather it would print out all your HTML as text on the screen. It might be possible to modify the editor itself so that it would accept direct HTML into the database... if you want that. However, I'm not very well versed with the CKEditor used for formatting text and can't say for certain how easy this task would be.
I'm fairly certain adding the CAPTCHA to the registration form would be no different than above. You would need to add:
Code: Select all
<br />
<b><?php echo $entry_captcha; ?></b><br />
<input type="text" name="captcha" value="<?php echo $captcha; ?>" />
<br />
<img src="index.php?route=information/contact/captcha" alt="" />
<?php if ($error_captcha) { ?>
<span class="error"><?php echo $error_captcha; ?></span>
<?php } ?>
Code: Select all
public function captcha() {
$this->load->library('captcha');
$captcha = new Captcha();
$this->session->data['captcha'] = $captcha->getCode();
$captcha->showImage();
}
All you would have to do after that is follow the directions in the tutorial above about declaring your CAPTCHA variable, CAPTCHA error variable, and set the language in the Register Language file. Everything should fall in place after that.
I heart cmd-f, cmd-c, cmd-v, cmd-z + vQmod.
My favourite page...
v1.5.4.1
Okay. I placed your file into my OpenCart test site and now I see what happened. You were missing a couple of proper opening and closing tags that were throwing your errors. Around line 524 you are missing a closing parentheses ) in your validate() function when you are checking for 'enquiry'.
Around line 273 you are missing an if() opening tag. You've got all the rest of the stuff in there } else { ... } which is what is throwing that T_ELSE error in your browser.
Anyhow, I'm feeling generous today so I've made the fixes and uploaded your file. Be informed that I changed the filename from 'Information-Controller-FORM' to 'Information'.
Attachments
One question though, if I'm putting the <form></form> into information.tpl and only want the form to show up on one information page, how do we accomplish this? I don't want the form to show on every info page. I saw something about:
Code: Select all
if ($this->request->get['information_id'] == 9) {
Also, when I'm defining min/max number of characters, if I want the postcode to be exactly 4 characters, is it ok to do it like this:
Code: Select all
if ((utf8_strlen($this->request->post['postcode']) < 4) || (utf8_strlen($this->request->post['postcode']) > 4)) {
$this->error['postcode'] = $this->language->get('error_postcode');
}
Lastly, my <form> from contact looks like this:
Code: Select all
<form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="contact">
I heart cmd-f, cmd-c, cmd-v, cmd-z + vQmod.
My favourite page...
v1.5.4.1
We'll start with the <form> question. If you examine your Page Source once the Information Page has loaded, you'll see that you are probably getting an error of some sort about an undefined variable in the action=" ". I'll update my post up top to reflect this, but will explain it here.
As for the conditional statement, you would need to add a similar line to your Information Template file. You will need to wrap your <form></form> area (and any additional HTML you don't want showing if displaying a different Information Page) with this conditional. So it would look something similar to this:
Code: Select all
<?php if ($information_id == 10) { ?>
<form>
<!-- your form HTML here -->
</form>
<?php } // endif ?>
So using this method you can serve up custom information for any specific Information Page you want. In my case I have two different forms that appear on two different Information Pages, and both forms exist in the Information Template file but are restricted from showing because I use a conditional tag.
Be forewarned that if you intend to add additional forms (or anything that requires function calls in the Information Controller) you are likely to get an error if you don't wrap that stuff in conditional statements. So in your Information Controller you might have something similar to this:
Code: Select all
if ($this->request->get['information_id'] == 9) {
// ... your page specific functions here
}
if ($this->request->get['information_id'] == 10) {
// ... your page specific functions here
}
If you need to figure out the ID tag for a specific Information Page (and it isn't in your address bar because you have SEO URLs turned on) then you need to access it from your Administration area. You can find it in the address bar once you choose to edit the Information Page you are interested in.
As for wanting a specific string length, it is much more efficient to state it as such:
Code: Select all
if ((utf8_strlen($this->request->post['postcode']) != 4)){
// execute code here
}
This way you are just checking to see if it is exactly four characters long, and you save having to execute a repetitive action.
Code: Select all
<?php if ($information_id == 29) { ?>
<form>
<!-- your form HTML here -->
</form>
<?php } // endif ?>
Also, I did a test submission and when I clicked on "Continue" (ie. submit), it redirected me to information/information which doesn't exist. I would say it has something to do with this code:
Code: Select all
$this->data['action'] = $this->url->link('information/information');
Here's the important part of the tpl file:
Code: Select all
<?php echo $description; ?>
<?php if ($information_id == 29) { ?>
<form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="contact">
<div class="content">
<b><?php echo $text_name; ?></b><br />
<input type="text" name="name" value="<?php echo $name; ?>" />
<br />
<?php if ($error_name) { ?>
<span class="error"><?php echo $error_name; ?></span>
<?php } ?>
<br />
<b><?php echo $text_company; ?></b><br />
<input type="text" name="company" value="<?php echo $company; ?>" />
<br />
<?php if ($error_company) { ?>
<span class="error"><?php echo $error_company; ?></span>
<?php } ?>
<br />
<b><?php echo $text_street_address; ?></b><br />
<input type="text" name="street_address" value="<?php echo $street_address; ?>" />
<br />
<?php if ($error_street_address) { ?>
<span class="error"><?php echo $error_street_address; ?></span>
<?php } ?>
<br />
<b><?php echo $text_street_address_2; ?></b><br />
<input type="text" name="street_address_2" value="<?php echo $street_address_2; ?>" />
<br />
<?php if ($error_street_address_2) { ?>
<span class="error"><?php echo $error_street_address_2; ?></span>
<?php } ?>
<br />
<b><?php echo $text_suburb; ?></b><br />
<input type="text" name="phone" value="<?php echo $suburb; ?>" />
<br />
<?php if ($error_suburb) { ?>
<span class="error"><?php echo $error_suburb; ?></span>
<?php } ?>
<br />
<b><?php echo $text_state; ?></b><br />
<input type="text" name="phone" value="<?php echo $state; ?>" />
<br />
<?php if ($error_state) { ?>
<span class="error"><?php echo $error_state; ?></span>
<?php } ?>
<br />
<b><?php echo $text_postcode; ?></b><br />
<input type="text" name="phone" value="<?php echo $postcode; ?>" />
<br />
<?php if ($error_postcode) { ?>
<span class="error"><?php echo $error_postcode; ?></span>
<?php } ?>
<br />
<b><?php echo $text_phone; ?></b><br />
<input type="text" name="phone" value="<?php echo $phone; ?>" />
<br />
<?php if ($error_phone) { ?>
<span class="error"><?php echo $error_phone; ?></span>
<?php } ?>
<br />
<b><?php echo $text_mobile; ?></b><br />
<input type="text" name="mobile" value="<?php echo $mobile; ?>" />
<br />
<?php if ($error_mobile) { ?>
<span class="error"><?php echo $error_mobile; ?></span>
<?php } ?>
<br />
<b><?php echo $text_email; ?></b><br />
<input type="text" name="email" value="<?php echo $email; ?>" />
<br />
<?php if ($error_email) { ?>
<span class="error"><?php echo $error_email; ?></span>
<?php } ?>
<br />
<b><?php echo $text_website; ?></b><br />
<input type="text" name="website" value="<?php echo $website; ?>" />
<br />
<?php if ($error_website) { ?>
<span class="error"><?php echo $error_website; ?></span>
<?php } ?>
<br />
<b><?php echo $text_enquiry; ?></b><br />
<textarea name="enquiry" cols="40" rows="10" style="width: 97%;"><?php echo $enquiry; ?></textarea>
<br />
<?php if ($error_enquiry) { ?>
<span class="error"><?php echo $error_enquiry; ?></span>
<?php } ?>
<br />
<b><?php echo $text_captcha; ?></b><br />
<input type="text" name="captcha" value="<?php echo $captcha; ?>" />
<br />
<img src="index.php?route=information/contact/captcha" alt="" />
<?php if ($error_captcha) { ?>
<span class="error"><?php echo $error_captcha; ?></span>
<?php } ?>
</div>
<div class="buttons">
<div class="right"><a onclick="$('#contact').submit();" class="button"><span><?php echo $button_continue; ?></span></a></div>
</div>
</form>
<?php } ?>
<div class="buttons">
<div class="right"><a href="<?php echo $continue; ?>" class="button"><span><?php echo $button_continue; ?></span></a></div>
</div>
<?php echo $content_bottom; ?></div>
<?php echo $footer; ?>
I heart cmd-f, cmd-c, cmd-v, cmd-z + vQmod.
My favourite page...
v1.5.4.1
Code: Select all
Undefined variable: information_id in catalog/view/theme/themeglobal/template/information/information.tpl on line 39
I heart cmd-f, cmd-c, cmd-v, cmd-z + vQmod.
My favourite page...
v1.5.4.1
Before I get to any of the rest of this stuff, let me ask you to make an adjustment to your Information Controller file. Do this, test the form and see if everything works. I was realizing that your $error_name, etc. variables weren't triggering when incorrectly filled out. Find the line that says this:
Code: Select all
if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
// ... your Mail() code
}
Code: Select all
$this->data['text_enquiry'] = $this->language->get('text_enquiry');
$this->data['text_captcha'] = $this->language->get('text_captcha');
if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
// ... your Mail() code
}
Another way to do your conditional tag in the Information Template (and would also get rid of your undefined variable error) is to replace if ($information_id == 29) with this:
Code: Select all
<?php if ($this->request->get['information_id'] == 29) { ?>
Code: Select all
<form action="" method="post" enctype="multipart/form-data" id="contact">
Took a bit, but we got there in the end!! Thank you Eyechild!
I was getting a bit frisky with copy and paste, thanks for picking that up.Also, while looking through your form markup I noticed that many of your input fields share the same name="phone". Might want to catch that before it causes problems.
Now, I can live without it, but BobDougan did ask about the customer being able to upload a file with the form...
Thanks again!
I heart cmd-f, cmd-c, cmd-v, cmd-z + vQmod.
My favourite page...
v1.5.4.1
Users browsing this forum: No registered users and 119 guests