Crear un formulario de contacto sin plugin
Soy nuevo en el desarrollo de WordPress y estoy cansado de luchar con Contact Form 7 para darle el estilo que quiero. ¿Es posible y no se considera "mala práctica" poner un formulario HTML en mi página de contacto y que envíe los datos a una página PHP que maneje el envío? ¿O simplemente no se hace eso?

Esta es mi implementación muy simple de un formulario de contacto:
class WPSE_299521_Form {
/**
* Constructor de la clase
*/
public function __construct() {
$this->define_hooks();
}
public function controller() {
if( isset( $_POST['submit'] ) ) { // Botón de envío
$full_name = filter_input( INPUT_POST, 'full_name', FILTER_SANITIZE_STRING );
$email = filter_input( INPUT_POST, 'email', FILTER_SANITIZE_STRING | FILTER_SANITIZE_EMAIL );
$color = filter_input( INPUT_POST, 'color', FILTER_SANITIZE_STRING );
$accessories = filter_input( INPUT_POST, 'accessories', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
$comments = filter_input( INPUT_POST, 'comments', FILTER_SANITIZE_STRING );
// Enviar un correo y redirigir al usuario a la página de "Gracias"
}
}
/**
* Mostrar formulario
*/
public function display_form() {
$full_name = filter_input( INPUT_POST, 'full_name', FILTER_SANITIZE_STRING );
$email = filter_input( INPUT_POST, 'email', FILTER_SANITIZE_STRING | FILTER_SANITIZE_EMAIL );
$color = filter_input( INPUT_POST, 'color', FILTER_SANITIZE_STRING );
$accessories = filter_input( INPUT_POST, 'accessories', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
$comments = filter_input( INPUT_POST, 'comments', FILTER_SANITIZE_STRING );
// Array vacío por defecto
$accessories = ( $accessories === null ) ? array() : $accessories;
$output = '';
$output .= '<form method="post">';
$output .= ' <p>';
$output .= ' ' . $this->display_text( 'full_name', 'Nombre', $full_name );
$output .= ' </p>';
$output .= ' <p>';
$output .= ' ' . $this->display_text( 'email', 'Correo electrónico', $email );
$output .= ' </p>';
$output .= ' <p>';
$output .= ' ' . $this->display_radios( 'color', 'Color', $this->get_available_colors(), $color );
$output .= ' </p>';
$output .= ' <p>';
$output .= ' ' . $this->display_checkboxes( 'accessories', 'Accesorios', $this->get_available_accessories(), $accessories );
$output .= ' </p>';
$output .= ' <p>';
$output .= ' ' . $this->display_textarea( 'comments', 'Comentarios', $comments );
$output .= ' </p>';
$output .= ' <p>';
$output .= ' <input type="submit" name="submit" value="Enviar" />';
$output .= ' </p>';
$output .= '</form>';
return $output;
}
/**
* Mostrar campo de texto
*/
private function display_text( $name, $label, $value = '' ) {
$output = '';
$output .= '<label>' . esc_html__( $label, 'wpse_299521' ) . '</label>';
$output .= '<input type="text" name="' . esc_attr( $name ) . '" value="' . esc_attr( $value ) . '">';
return $output;
}
/**
* Mostrar campo de área de texto
*/
private function display_textarea( $name, $label, $value = '' ) {
$output = '';
$output .= '<label> ' . esc_html__( $label, 'wpse_299521' ) . '</label>';
$output .= '<textarea name="' . esc_attr( $name ) . '" >' . esc_html( $value ) . '</textarea>';
return $output;
}
/**
* Mostrar campo de radios
*/
private function display_radios( $name, $label, $options, $value = null ) {
$output = '';
$output .= '<label>' . esc_html__( $label, 'wpse_299521' ) . '</label>';
foreach ( $options as $option_value => $option_label ):
$output .= $this->display_radio( $name, $option_label, $option_value, $value );
endforeach;
return $output;
}
/**
* Mostrar campo de radio individual
*/
private function display_radio( $name, $label, $option_value, $value = null ) {
$output = '';
$checked = ( $option_value === $value ) ? ' checked' : '';
$output .= '<label>';
$output .= ' <input type="radio" name="' . esc_attr( $name ) . '" value="' . esc_attr( $option_value ) . '"' . esc_attr( $checked ) . '>';
$output .= ' ' . esc_html__( $label, 'wpse_299521' );
$output .= '</label>';
return $output;
}
/**
* Mostrar campo de checkboxes
*/
private function display_checkboxes( $name, $label, $options, $values = array() ) {
$output = '';
$name .= '[]';
$output .= '<label>' . esc_html__( $label, 'wpse_299521' ) . '</label>';
foreach ( $options as $option_value => $option_label ):
$output .= $this->display_checkbox( $name, $option_label, $option_value, $values );
endforeach;
return $output;
}
/**
* Mostrar checkbox individual
*/
private function display_checkbox( $name, $label, $available_value, $values = array() ) {
$output = '';
$checked = ( in_array($available_value, $values) ) ? ' checked' : '';
$output .= '<label>';
$output .= ' <input type="checkbox" name="' . esc_attr( $name ) . '" value="' . esc_attr( $available_value ) . '"' . esc_attr( $checked ) . '>';
$output .= ' ' . esc_html__( $label, 'wpse_299521' );
$output .= '</label>';
return $output;
}
/**
* Obtener colores disponibles
*/
private function get_available_colors() {
return array(
'red' => 'Rojo',
'blue' => 'Azul',
'green' => 'Verde',
);
}
/**
* Obtener accesorios disponibles
*/
private function get_available_accessories() {
return array(
'case' => 'Funda',
'tempered_glass' => 'Vidrio templado',
'headphones' => 'Auriculares',
);
}
/**
* Definir hooks relacionados con el plugin
*/
private function define_hooks() {
/**
* Añadir acción para enviar correo
*/
add_action( 'wp', array( $this, 'controller' ) );
/**
* Añadir shortcode para mostrar el formulario
*/
add_shortcode( 'contact', array( $this, 'display_form' ) );
}
}
new WPSE_299521_Form();
Después de pegar el código puedes usar el shortcode [contact]
para mostrarlo.

@user8463989 - esto podría ir en tu archivo functions.php en tu tema hijo... estás trabajando con un tema hijo, ¿verdad?

Curiosamente, después de encontrar esta respuesta, surgió una oportunidad para usar este código como punto de partida. Muy bueno.

Buena implementación. ¿Dónde controlo la acción del formulario, es decir, a dónde se envía el formulario?

Todos los plugins de formularios son horribles, es solo que los formularios suelen ser muy complejos de codificar correctamente, especialmente cuando el administrador del sitio debe poder diseñarlos.
No hay nada malo en codificar un formulario tú mismo, es solo que probablemente necesitarás recrear cosas que otras personas ya han perfeccionado, o al menos tienen buenas bases (formateo de correos electrónicos, almacenamiento en la base de datos y probablemente más).
Así que realmente depende de tus requisitos específicos, si no se requiere flexibilidad y enviar correos electrónicos es suficiente, debería ser más fácil escribir el tuyo propio que "luchar" con los plugins.

Mi mayor problema en realidad es intentar dar estilo a casillas de verificación (checkboxes) y botones de radio usando Contact Form 7 o cualquier otro plugin de formularios. Me está matando lentamente, por eso pensé en simplemente usar un formulario HTML y luego PHP para enviar el formulario.

@user8463989, tal vez deberías usar un plugin diferente. CF7 en mi opinión es demasiado básico, aunque nunca lo he usado así que quizás no estoy lo suficientemente familiarizado para criticarlo. Todos tienen sus peculiaridades, ninguno es perfecto de verdad.

Como no estás realizando operaciones CRUD en la base de datos, no veo por qué no. Yo lo he hecho antes usando una plantilla de página para el procesamiento de formularios y apuntando el atributo action
del formulario de contacto <form ...>
hacia ella: action="<?php echo home_url( 'slug-de-mi-plantilla-de-procesamiento-de-formulario' ); ?>"
.
Alternativamente, puedes usar la publicación individual del tipo de contenido para procesarlo, es decir: action="<?php echo get_the_permalink();?>"
(necesita ser una página is_single() || is_singular()
para usar get_the_permalink()
).
