Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Validate with HTML_QuickForm, send with PHPmailer 1

Status
Not open for further replies.

ChrisRChamberlain

Programmer
Mar 23, 2000
3,392
GB
Hi all

Newbie type question - is it possible to validate a form using HTML_QuickForm and then send the relevant data via SMTP using PHPmailer?

TIA

FAQ184-2483​
Chris [pc2]
PDFcommander.com
motrac.co.uk
 
yup.

example follows (wholly untested !)

Code:
<?php

class myForm{
	
	public $fields = array('surName', 'firstName', 'id');
	
	public function __construct(){
		$this->url = $_SERVER['PHP_SELF'];
		$this->primary = 'id';
		$this->tableName = 'mytable';
	}
	
	public function load($data){
		if (is_object($array)){
			$array = get_object_vars($array);
		}
		foreach($this->fields as $field){
			if (isset($array[$field])){
				$this->$field = $array[$field];
			}
		}
	}
	
	public function send($to){
		require_once('../class.phpmailer.php');
		$mail             = new PHPMailer();
		$this->form->freeze();
		$body             = <<<HTML
A new form was submitted today.  <br/>
details of the form were: <br/>
HTML
		. $this->form->toHTML();
				
		$mail->AddReplyTo($this->from, $this->fromName);
		$mail->SetFrom($this->fromEmail, $this->fromName);
		$mail->AddAddress($to, '');
		$mail->Subject    = "Just received a new form submission";
		$mail->AltBody    = "To view the message, please use an HTML compatible email viewer!"; // optional, comment out and test
		$mail->MsgHTML($body);
		
		if(!$mail->Send()) {
		echo "Mailer Error: " . $mail->ErrorInfo;
		} else {
		echo "Message sent!";
		}
	}
	
	public function enquote($data){
		if(is_array($data)){
			array_walk(array($this, 'enquote'), $data);
		}
		return "'" . mysql_real_escape_string($data). "'";
	}
	
	public function loadFromID($id){
		$sql = "select * from $this->tableName where $this->primary=%d";
		$result = mysql_query(sprintf($sql, $id));
		if($result){
			$this->load(mysql_fetch_assoc($result));
		}
	}
	
	public function constructForm(){
		$form = new aacForm('client', 'post', '', '', '', TRUE);
		$form->setAttribute('action', $this->url);	//we need to do this otherwise the forms class will strip the url before the query string
		$form->addElement('header','','Fill in your details');
		$form->addElement('text', 'surName', 'SurName:', array('class'=>'regular-text'));
		$form->addElement('text','firstName', 'First Name:', array('class'=>'regular-text'));
		$form->addElement('hidden', $this->primary);
		$form->addElement('hidden', 'action');
		$form->addRule('surName', 'You must provide a surname', 'required', '', 'client' );
		$form->addRule('firstName', 'You must provide a first name', 'required', '', 'client' );
		$this->form = $form;
		$this->aacAction = 'saveFormData';
		$this->form->setDefaults(get_object_vars($this)); //load info
	}
	
	public function saveNew(){
		$args = $this->compact();
		$args = $this->enquote($args);
		$fields =  implode (',', array_keys($args));
		$values = implode (',', array_values($args));
		$sql = "insert into $this-tableName ($fields) values ($values)"; 
		$r = mysql_query($sql);
		if ($r) {
			$this->{$this->primary} = $wpdb->insert_id;
			return true;
		} else {
			die(mysql_error());
		}
	}
	
	public function compact(){
		foreach($this->fields as $val){
			if (is_array($this->$val)){
				$array[$val] = serialize($this->$val);
			} else {
				$array[$val]=$this->$val;
			}
		}	
		return $array;
	}
	
	/**
	 * private helper method to update an existing record
	 * @return 
	 */
	public function update(){
		
		$args= $this->compact();
		update($args[$this->primary]);
		$set = array();
		foreach ($args as $f->$a){
			$set [] = "$f=".$this->enquote($a);
		}
		$values = implode (',', $set) ;
		$sql = "Update $this->tableName set $values where {$this->primary} = {$this->{$this->primary}}";
		$r = @mysql_query($sql);
		return ($r > 0) ? true : false;
	}
	
	public function save(){
		if (empty($this->{$this->primary})){
			$this->saveNew();
		} else{
			$this->update();
		}
	}
	
	public function validates(){
		if (empty($this->form)){
			$this->constructForm();
		}
		return $this->form->validate();
	}
	public function showForm(){
		if (empty($this->form)){
			$this->constructForm();
		}
		$this->form->display();
	}
}

$action = empty($_REQUEST['action']) ? '' : $_REQUEST['action'];
switch ($action){
	case 'saveFormData':
		$i = new myForm();
		if (isset($_REQUEST[$i->primary])){
			$i->loadfromid($_REQUEST[$i->primary]);
		}
		if ($i->validates){
			$i->save();
			$i->send();
		} else {
			$i->showForm();
		}
	break;
	default:
		$i = new myForm();
		$i->showForm();
}
?>
 
oh. i see that you asked for it to be sent via smtp rather than mail(). answer is still yes. just change the send method() to use the phpmailer smtp class and provide the relevant host, username, password variables to phpmailer.

i also note that i did not provide properties for the from, fromEmail and fromName. bit sloppy. from = fromEmail. so just add this to the __construct() method

Code:
$this->from = $this->fromEmail = 'me@example.com';
$this->fromName = 'John Smith';
 
jpadie

Thanks for your reply.

Added relevant host, username, password variables to phpmailer and there is an error
Code:
Fatal error: Only variables can be passed by reference in /var/[URL unfurl="true"]www/www.mysite.com/testit5.php[/URL] on line 70
line 70 code being
Code:
array_walk(array($this,'enquote'), $data);

FAQ184-2483​
Chris [pc2]
PDFcommander.com
motrac.co.uk
 
sorry. it should have been array_map(). not array_walk.

am still not sure it will work. that line is very lazy coding!

 
Error now
Code:
Fatal error: Class 'aacForm' not found in /var/[URL unfurl="true"]www/www.mysite.com/testit5.php[/URL] on line 84
line 84 being
Code:
$form = new aacForm('client', 'post', '', '', '', TRUE);

FAQ184-2483​
Chris [pc2]
PDFcommander.com
motrac.co.uk
 
i'm sorry again Chris. i dropped the code very quickly to get a response back to you asap. aacForm is a custom class i wrote to extend html quickform to use my own renderer. i have included it below but you might want to switch back to the standard quickform class instead.

my class uses the DHTML Rules Tableless PEAR extension to quickform. it is easily installable through PEAR and gives you (as you might expect) a form that is not based on a table layout and so is more customisable through css. It also degrades nicely.

Code:
<?php
require_once 'PEAR/HTML/QuickForm/DHTMLRulesTableless.php';
require_once 'PEAR/HTML/QuickForm/Renderer/Tableless.php';
/**
 * class for quickform
 */

class aacForm extends HTML_QuickForm_DHTMLRulesTableless{
	
	public function __construct($name, $method, $action, $target, $attributes, $trackSubmit ){
		parent::HTML_QuickForm_DHTMLRulesTableless($name, $method, $action, $target, $attributes, $trackSubmit);
		$renderer =& new HTML_QuickForm_Renderer_Tableless();
		$renderer->setElementTemplate(<<<HTML

			<div class="aacFormRow form-field">
				<div class="aacFormLabel">
					<label>
						{label}<!-- BEGIN required --><span class="required">*</span><!-- END required -->
					</label>
				</div>
				<div class="aacFormControl">
				{element}
				<br/>
				<!-- BEGIN error --><span class="error">{error}</span><br /><!-- END error -->
				</div>
			</div>

HTML
);
		$renderer->_headerTemplate = <<<HTML

		<legend class="aacFormLegend"><h2>{header}</h2></legend>
HTML;
		$renderer->setOpenHiddenFieldsetTemplate( <<<HTML

	<fieldset class="hidden{class}">
HTML
);
		$renderer->setCloseFieldsetTemplate(<<<HTML

	</fieldset>
HTML
);
		$renderer->_requiredNoteTemplate = <<<HTML

			<p>
				<label class="element">&nbsp;</label>{requiredNote}
			</p>
HTML;
		$this->renderer = $renderer;
		
	}
	
	public function publishForm(){
		$this->removeAttribute('name');
		$this->getValidationScript();
		
		getAACNonce();
		
		$buttons = <<<HTML

		<fieldset>
			<p class="submit">
				<input type="reset" value="Reset" class="button-secondary" /> &nbsp;
				<input type="submit" name="submit" id="aacSaveButton" value="Save" class="button-primary long"/>
				<input type="hidden" name="aacNonce" value="{$_SESSION['aacNonce']}" />
			</p>
		</fieldset>
HTML;
		$this->accept($this->renderer);
		$html =  $this->renderer->toHtml();
		return str_replace('</form>', $buttons . "</form>", $html);
	}
}

?>

and here is some very simple css to control the display

Code:
.aacFormRow{
	clear:left;
	overflow-y:hidden;
	margin:5px 0;
	width: 80%;
}
.aacFormControl{
	width:300px;
	float:left;
}
.aacFormControl .long{
	width: 50px;
}
.aacFormLabel{
	width:180px;
	float: left;
}
.aacFormLabel .required{
	color:#c6200d;
}

.aacFormLegend{
	padding-bottom: 10px; 
	padding-top: 10px; 
	color:#2a119f; 
	font-style:italic;
}
.aacFormControl textarea{
	height: 100px;
}
 
jpadie

Thanks for the additional code.

I integrated the class declaration into your previously posted code by pasting it, together with modified paths, before the main class declaration.

The form runs without error but displays two fields only together with relevant text.

Is this what is expected?



FAQ184-2483​
Chris [pc2]
PDFcommander.com
motrac.co.uk
 
yes, it is what is expected. if you look in the constructForm method there are only two editable form controls created: surName and firstName

obviously you will want to use your own form controls - the code was posted purely as a proof of concept to show you how things might be achieved.

when you submit the form, the form is validated and the data saved in the database table of your choice (see the tableName property and then emailed (using phpmailer) to the address of your choice as specified in the call to the send method
Code:
$i->send([red]add your address here[/red]);
;
[/code]
 
In the send($to) function, I assume
Code:
$mail = new PHPMailer();
$mail->IsSMTP();  // Telling the class to use SMTP
$mail->IsHTML(true);  // Telling the class to send as HTML		
$mail->SMTPAuth = true;	//	Enable SMTP authentication
$mail->SMTPSecure = "ssl";	//	Sets the prefix to the server

$mail->Host = "smtp.gmail.com"; // SMTP server
$mail->Port = 465;	//	Set the SMTP port
// other PHPmailer specific code here
etc precedes this code?
Code:
$this->form->freeze();
$body = <<<HTML
A new form was submitted today.  <br/>
details of the form were: <br/>
HTML
. $this->form->toHTML();




FAQ184-2483​
Chris [pc2]
PDFcommander.com
motrac.co.uk
 
oddly one of my posts did not get logged.

after your sendto question i posted something along the lines of the following:

the send($to) function is part of the switch statement at the end of my first post. therefore it calls the send method and passes an argument rather than being part of it.

your question indicates that you may not have a lot of experience in php. would it help if I more fully commented my code?

my apologies - i should have checked back to verify that the post had stuck.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top