Icono del sitio Tursos

Como Hacer un Formulario de Contacto III: Validar y Enviar con PHP

Actualización: Acabo de publicar un tutorial para usuarios avanzados de como hacer un formulario de contacto similar a este, capaz de enviar mensaje sin recargar la pagina usando AJAX, todo en un solo tutorial.


En este tutorial veremos como validar nuestro formulario del lado del servidor con PHP, ademas hacer que se envie el mensaje a una dirección de correo electrónico que le definamos.

Antes de empezar

Importante: en este tutorial vamos a trabajar con el metodo de envio POST, si no conoces este tema te recomendaria que le eches un ojo a este tutorial antes de seguir.

Ya que vamos a trabajar con PHP, es necesario que tengas instalado en tu sistema un servidor local que soporte PHP.

Luego tenemos que cambiar la extension del archivo index.html a index.php:

Te recomendaria tambien que desactives el Javascript del explorador en el que estes probando el formulario, para que te puedas asegurar que la validación del lado del servidor esta funcionando.

Validación

Lo primero es abrir un par de etiquetas PHP arriba del todo, dentro de estas hacemos un if para cuando el boton de envio es presionado, en el formulario definimos los atributos method y action.

<?php
    if(isset($_POST['boton'])){
         //aqui va nuestro codigo
    }
?>
<html>
    <head>
        <title>Contacto</title>
        <link rel='stylesheet' href='estilos.css'>
        <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js'></script>
        <script src='funciones.js'></script>
    </head>
    <body>
        <form class='contacto' method='POST' action=''>
            <div><label>Tu Nombre:</label><input type='text' class='nombre' value=''></div>
            <div><label>Tu Email:</label><input type='text' class='email' value=''></div>
            <div><label>Asunto:</label><input type='text' class='asunto' value=''></div>
            <div><label>Mensaje:</label><textarea rows='6' class='mensaje'></textarea></div>
            <div><input type='submit' value='Envia Mensaje' class='boton'></div>
        </form>
    </body>
</html>

Tenemos que definir tambien los atributos name a cada campo del formulario(incluyendo al boton de envio) para poder identificarlos con PHP:

<form class='contacto' method='POST' action=''>
    <div><label>Tu Nombre:</label><input name='nombre' type='text' class='nombre' value=''></div>
    <div><label>Tu Email:</label><input name='email' type='text' class='email' value=''></div>
    <div><label>Asunto:</label><input name='asunto' type='text' class='asunto' value=''></div>
    <div><label>Mensaje:</label><textarea name='mensaje' rows='6' class='mensaje'></textarea></div>
    <div><input name='boton' type='submit' value='Envia Mensaje' class='boton'></div>
</form>

Teniendo ya todos los atributos necesarios declarados, regresamos al codigo PHP de mas arriba y hacemos una serie de comparaciones similar a cuando lo validamos del lado del cliente.

        <?php
			if(isset($_POST['boton'])){
				$errors = array(); // declaramos un array para almacenar los errores
				if($_POST['nombre'] == ''){
					$errors[1] = '<span class="error">Ingrese su nombre</span>';
				}else if($_POST['email'] == '' or !preg_match("/^[a-zA-Z0-9_\.\-]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+$/",$_POST['email'])){
					$errors[2] = '<span class="error">Ingrese un email correcto</span>';
				}else if($_POST['asunto'] == ''){
					$errors[3] = '<span class="error">Ingrese un asunto</span>';
				}else if($_POST['mensaje'] == ''){
					$errors[4] = '<span class="error">Ingrese un mensaje</span>';
				}else{
					//si todo esta ok envia email
				}
			}
	    ?>

Nota que en cada valor del array $errors le estamos declarando en el valor el mismo error que usamos en el anterior tutorial, así para reciclar las mismas clases y no volver a escribirlas.

Ahora tenemos que ubicar los errores en donde deberían aparecer si la prueba de validación no pasa:

        <form class='contacto' method='POST' action=''>
            <div><label>Tu Nombre:</label><input name='nombre' type='text' class='nombre' value=''>
            <?php echo $errors[1]; ?></div>
            <div><label>Tu Email:</label><input name='email' type='text' class='email' value=''>
            <?php echo $errors[2]; ?></div>
            <div><label>Asunto:</label><input name='asunto' type='text' class='asunto' value=''>
            <?php echo $errors[3]; ?></div>
            <div><label>Mensaje:</label><textarea name='mensaje' rows='6' class='mensaje'></textarea>
            <?php echo $errors[4]; ?></div>
            <div><input name='boton' type='submit' value='Envia Mensaje' class='boton'></div>
        </form>

Si probamos esto, podemos comprobar que esta validando pero que no esta guardando lo que rellenamos en los campos de textos cuando se muestra el error.

Por ejemplo si llenamos el primer campo pero no el segundo, se mostrara el error del segundo pero se eliminara lo que llenamos en el primero:

Para arreglar esto vamos a hacer que en el atributo value de cada uno de los campos del formulario se almacene lo que el usuario escribió, entonces el formulario quedaria asi:

        <form class='contacto' method='POST' action=''>
            <div><label>Tu Nombre:</label><input type='text' class='nombre' value='<?php echo $_POST['nombre']; ?>'>
			<?php echo $errors[1]; ?></div>
            <div><label>Tu Email:</label><input type='text' class='email' value='<?php echo $_POST['email']; ?>'>
			<?php echo $errors[2]; ?></div>
            <div><label>Asunto:</label><input type='text' class='asunto' value='<?php echo $_POST['asunto']; ?>'>
			<?php echo $errors[3]; ?></div>
            <div><label>Mensaje:</label><textarea rows='6' class='mensaje'><?php echo $_POST['mensaje']; ?></textarea>
			<?php echo $errors[4]; ?></div>
            <div><input type='submit' value='Envia Mensaje' class='boton'></div>
        </form>

En caso del textarea que no tiene atributo value va dentro de las etiquetas.

Envio

Ya con la validación del lado del servidor funcionando procederemos a hacer el envio del mensaje a una dirección de correo electrónico mediante la función mail() de PHP.

En el código PHP de arriba dentro del else (por la linea 14) que define si todas las pruebas de validación fueron pasadas ponemos lo que sera el envio:

			}else{			
				$dest = "tu@email.com; //Email de destino
				$nombre = $_POST['nombre'];
				$email = $_POST['email'];
				$asunto = $_POST['asunto']; //Asunto
				$cuerpo = $_POST['mensaje']; //Cuerpo del mensaje
				//Cabeceras del correo para que no llegue a spam
				$headers = "From: $nombre <$email>\r\n"; //Quien envia?
				$headers .= "X-Mailer: PHP5\n";
				$headers .= 'MIME-Version: 1.0' . "\n";
				$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; //

				if(mail($dest,$asunto,$cuerpo,$headers)){ // esta es una comparacion para ver si envio el mail o no (\r\n = salto de linea)
					$result = '<div class="result_ok">Email enviado correctamente</div>';	
             // si el envio fue exitoso reseteamos lo que el usuario escribio:
					$_POST['nombre'] = '';
					$_POST['email'] = '';
					$_POST['asunto'] = '';
					$_POST['mensaje'] = '';
				}else{
					$result = '<div class="result_fail">Hubo un error al enviar el mensaje</div>';
				}
			}

Si no logras entender muy bien esta parte del código te recomiendo que leas este tutorial donde se habla especificamente de la función mail de PHP.

La variable $result que he remarcado es para definir el mensaje que se le mostrara al usuario si el mensaje se envio correctamente o no, sin embargo tenemos que ubicar esta variable dentro del formulario para que se muestre:

			<?php echo $result; ?>
		</form>

Ten en cuenta que si intentas enviar el formulario no te va a funcionar si estas probandolo en tu servidor local a menos que tengas instalado un SMTP en tu sistema, lo ideal seria subirlo a un hosting y probarlo desde allí.

Si deseas puedes estilizar un poco el mensaje de error final($result) en la hoja de estilos:

.result_fail{
    background: none repeat scroll 0 0 #BC1010;
    border-radius: 20px 20px 20px 20px;
    color: white;
    font-weight: bold;
    padding: 10px 20px;
    text-align: center;
}
.result_ok{
    background: none repeat scroll 0 0 #1EA700;
    border-radius: 20px 20px 20px 20px;
    color: white;
    font-weight: bold;
    padding: 10px 20px;
    text-align: center;
}

Código final: index.php

<?php
    if(isset($_POST['boton'])){
        if($_POST['nombre'] == ''){
            $errors[1] = '<span class="error">Ingrese su nombre</span>';
        }else if($_POST['email'] == '' or !preg_match("/^[a-zA-Z0-9_\.\-]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+$/",$_POST['email'])){
            $errors[2] = '<span class="error">Ingrese un email correcto</span>';
        }else if($_POST['asunto'] == ''){
            $errors[3] = '<span class="error">Ingrese un asunto</span>';
        }else if($_POST['mensaje'] == ''){
            $errors[4] = '<span class="error">Ingrese un mensaje</span>';
        }else{
            $dest = "tu@email.com"; //Email de destino
            $nombre = $_POST['nombre'];
            $email = $_POST['email'];
            $asunto = $_POST['asunto']; //Asunto
            $cuerpo = $_POST['mensaje']; //Cuerpo del mensaje
            //Cabeceras del correo
            $headers = "From: $nombre <$email>\r\n"; //Quien envia?
            $headers .= "X-Mailer: PHP5\n";
            $headers .= 'MIME-Version: 1.0' . "\n";
            $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; //

            if(mail($dest,$asunto,$cuerpo,$headers)){
                $result = '<div class="result_ok">Email enviado correctamente </div>';
                // si el envio fue exitoso reseteamos lo que el usuario escribio:
                $_POST['nombre'] = '';
                $_POST['email'] = '';
                $_POST['asunto'] = '';
                $_POST['mensaje'] = '';
            }else{
                $result = '<div class="result_fail">Hubo un error al enviar el mensaje </div>';
            }
        }
    }
?>
<html>
    <head>
        <title>Contacto</title>
        <link rel='stylesheet' href='estilos.css'>
        <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js'></script>
        <script src='funciones.js'></script>
    </head>
    <body>
        <form class='contacto' method='POST' action=''>
            <div><label>Tu Nombre:</label><input type='text' class='nombre' name='nombre' value='<?php echo $_POST['nombre']; ?>'><?php echo $errors[1] ?></div>
            <div><label>Tu Email:</label><input type='text' class='email' name='email' value='<?php echo $_POST['email']; ?>'><?php echo $errors[2] ?></div>
            <div><label>Asunto:</label><input type='text' class='asunto' name='asunto' value='<?php echo $_POST['asunto']; ?>'><?php echo $errors[3] ?></div>
            <div><label>Mensaje:</label><textarea rows='6' class='mensaje' name='mensaje'><?php echo $_POST['mensaje']; ?></textarea><?php echo $errors[4] ?></div>
            <div><input type='submit' value='Envia Mensaje' class='boton' name='boton'></div>
            <?php echo $result; ?>
        </form>
    </body>
</html>

Actualización:

Debido a los comentarios que escribieron, decidi continuar el tutorial añadiendo una parte mas, en esta veremos como almancenar los valores ingresados por el usuario a una base de datos MySQL usando PHP.

Como hacer un formulario de contacto IV: Almacenar en base de datos MySQL con PHP