Создание контактной формы без плагина

1 апр. 2018 г., 15:08:29
Просмотры: 17.2K
Голосов: 3

Я новичок в разработке для WordPress и устал бороться с Contact Form 7, чтобы стилизовать его так, как мне нужно. Возможно ли и не считается ли "плохой практикой" разместить HTML-форму на странице контактов и отправлять данные на PHP-страницу, которая обрабатывает отправку формы? Или так просто не делают?

2
Комментарии

Вы пробовали расширение Smart Grid-layout, которое позволяет создавать сложные макеты форм с помощью сеточного интерфейса? Возможно, оно поможет вам смириться с CF7

Aurovrata Aurovrata
1 апр. 2018 г. 19:07:52

К любой форме, которую вы кодите вручную, я бы добавил скрытое поле для проверки, что отправка действительно произошла с формы, а также CSS (и ARIA) скрытое поле, которое должно оставаться пустым в качестве "обратного теста на заполнение"

Cedon Cedon
2 апр. 2018 г. 01:45:41
Все ответы на вопрос 3
6

Это моя очень простая реализация контактной формы:

class WPSE_299521_Form {

    /**
     * Конструктор класса
     */
    public function __construct() {

        $this->define_hooks();
    }

    public function controller() {

        if( isset( $_POST['submit'] ) ) { // Кнопка отправки

            $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 );

            // Отправка письма и редирект на страницу "Спасибо"
        }
    }

    /**
     * Отображение формы
     */
    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 );

        // Пустой массив по умолчанию
        $accessories = ( $accessories === null ) ? array() : $accessories;

        $output = '';

        $output .= '<form method="post">';
        $output .= '    <p>';
        $output .= '        ' . $this->display_text( 'full_name', 'Имя', $full_name );
        $output .= '    </p>';
        $output .= '    <p>';
        $output .= '        ' . $this->display_text( 'email', 'Email', $email );
        $output .= '    </p>';
        $output .= '    <p>';
        $output .= '        ' . $this->display_radios( 'color', 'Цвет', $this->get_available_colors(), $color );
        $output .= '    </p>';
        $output .= '    <p>';
        $output .= '        ' . $this->display_checkboxes( 'accessories', 'Аксессуары', $this->get_available_accessories(), $accessories );
        $output .= '    </p>';
        $output .= '    <p>';
        $output .= '        ' . $this->display_textarea( 'comments', 'Комментарии', $comments );
        $output .= '    </p>';
        $output .= '    <p>';
        $output .= '        <input type="submit" name="submit" value="Отправить" />';
        $output .= '    </p>';
        $output .= '</form>';

        return $output;
    }

    /**
     * Отображение текстового поля
     */
    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;
    }

    /**
     * Отображение поля textarea
     */
    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;
    }

    /**
     * Отображение радио-кнопок
     */
    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;
    }

    /**
     * Отображение одной радио-кнопки
     */
    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;
    }

    /**
     * Отображение чекбоксов
     */
    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;
    }

    /**
     * Отображение одного чекбокса
     */
    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;
    }

    /**
     * Получение доступных цветов
     */
    private function get_available_colors() {

        return array(
            'red' => 'Красный',
            'blue' => 'Синий',
            'green' => 'Зеленый',
        );
    }

    /**
     * Получение доступных аксессуаров
     */
    private function get_available_accessories() {

        return array(
            'case' => 'Чехол',
            'tempered_glass' => 'Закаленное стекло',
            'headphones' => 'Наушники',
        );
    }

    /**
     * Определение хуков плагина
     */
    private function define_hooks() {

        /**
         * Добавление действия для отправки письма
         */
        add_action( 'wp', array( $this, 'controller' ) );

        /**
         * Добавление шорткода для отображения формы
         */
        add_shortcode( 'contact', array( $this, 'display_form' ) );
    }
}

new WPSE_299521_Form();

После вставки кода вы можете использовать шорткод [contact] для его отображения.

1 апр. 2018 г. 21:15:03
Комментарии

Куда бы вы поместили этот код?

user8463989 user8463989
2 апр. 2018 г. 09:38:14

Вероятно, я бы создал простой плагин.

kierzniak kierzniak
2 апр. 2018 г. 09:48:46

@user8463989 - это можно добавить в файл functions.php вашей дочерней темы... вы ведь работаете с дочерней темой, верно?

HPWD HPWD
11 февр. 2019 г. 22:36:21

Странно, но после того как я нашел этот ответ, у меня появилась возможность использовать этот код в качестве отправной точки. Очень хорошо.

HPWD HPWD
15 февр. 2019 г. 16:21:00

Хорошая реализация. Где я могу управлять действием формы, то есть куда отправляется форма?

MontyHall MontyHall
4 сент. 2019 г. 10:02:04

Есть метод controller, подключенный к действию wp. Этот метод будет выполняться при каждом запросе, но, как видно из условия, остальная часть метода будет обработана только если в POST-запросе есть данные submit, которые соответствуют нашей кнопке отправки.

kierzniak kierzniak
4 сент. 2019 г. 10:20:34
Показать остальные 1 комментариев
3

Все плагины для форм ужасны, просто потому что формы обычно очень сложно правильно запрограммировать, особенно когда администратор сайта должен иметь возможность их проектировать.

Нет ничего плохого в том, чтобы написать форму самостоятельно, просто вам, вероятно, придётся воссоздавать то, что другие уже усовершенствовали или, по крайней мере, заложили хорошую основу (форматирование писем, хранение в базе данных и, вероятно, многое другое).

Так что всё действительно зависит от ваших конкретных требований. Если гибкость не требуется, и отправки email достаточно, то написать свою форму должно быть проще, чем "бороться" с плагинами.

1 апр. 2018 г. 16:22:54
Комментарии

Моя самая большая проблема — это попытки стилизовать чекбоксы и радио-кнопки с помощью Contact Form 7 или любого другого плагина для контактных форм. Это медленно убивает меня, поэтому я подумал просто использовать HTML-форму и PHP для отправки данных.

user8463989 user8463989
1 апр. 2018 г. 16:34:56

@user8463989, возможно, стоит попробовать другой плагин. На мой взгляд, CF7 слишком базовый, но я никогда им не пользовался, так что, может быть, просто недостаточно знаком с ним, чтобы критиковать. У всех плагинов есть свои особенности, ни один не идеален.

Mark Kaplun Mark Kaplun
1 апр. 2018 г. 16:46:20

Я пробовал несколько, и все они работают, но проблема остаётся. CSS ломается. Возможно, это из-за того, что я пытаюсь преобразовать HTML-форму для WordPress, не знаю.

user8463989 user8463989
1 апр. 2018 г. 21:09:57
0

Поскольку вы не выполняете CRUD-операции с базой данных, я не вижу причин не делать так. Я уже делал подобное, используя шаблон страницы для обработки формы и указывая в атрибуте action контактной формы ссылку на него: action="<?php echo home_url( 'slug-shablona-dlya-obrabotki-formy' ); ?>".

Альтернативный вариант — использовать саму запись пользовательского типа для обработки, например: action="<?php echo get_the_permalink();?>" (для работы get_the_permalink() страница должна быть одиночной записью, проверяемой через is_single() || is_singular()).

1 апр. 2018 г. 16:21:04