Crear un formulario de contacto sin plugin

1 abr 2018, 15:08:29
Vistas: 17.2K
Votos: 3

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?

2
Comentarios

¿Has probado la extensión Smart Grid-layout que te permite crear diseños de formularios enriquecidos usando una interfaz de cuadrícula? Podría reconciliarte con CF7

Aurovrata Aurovrata
1 abr 2018 19:07:52

Algo que agregaría a cualquier formulario que codes manualmente es un campo oculto para verificar que el envío realmente provenga del formulario, y también un campo oculto con CSS (así como ARIA) que verifiques que esté vacío como una "prueba de tortura inversa"

Cedon Cedon
2 abr 2018 01:45:41
Todas las respuestas a la pregunta 3
6

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.

1 abr 2018 21:15:03
Comentarios

¿Dónde pondrías este código?

user8463989 user8463989
2 abr 2018 09:38:14

Probablemente crearía un plugin sencillo.

kierzniak kierzniak
2 abr 2018 09:48:46

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

HPWD HPWD
11 feb 2019 22:36:21

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

HPWD HPWD
15 feb 2019 16:21:00

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

MontyHall MontyHall
4 sept 2019 10:02:04

Existe un método controller enganchado a la acción wp. Este método se ejecutará en cada solicitud, pero como puedes ver en la condición, el resto del método solo procederá si hay datos submit en la solicitud POST, que es nuestro botón de envío.

kierzniak kierzniak
4 sept 2019 10:20:34
Mostrar los 1 comentarios restantes
3

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.

1 abr 2018 16:22:54
Comentarios

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 user8463989
1 abr 2018 16:34:56

@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.

Mark Kaplun Mark Kaplun
1 abr 2018 16:46:20

He probado varios que funcionan pero tengo el mismo problema. El CSS se rompe. Quizás porque estoy intentando convertir un formulario HTML a WordPress, no lo sé.

user8463989 user8463989
1 abr 2018 21:09:57
0

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()).

1 abr 2018 16:21:04