Как отобразить форму регистрации пользователей на фронтенде сайта?

24 февр. 2011 г., 16:07:30
Просмотры: 175K
Голосов: 37

Как отобразить форму регистрации пользователей WordPress (форму, которая появляется на странице "www.mywebsite.com/wp-register.php") во фронтенде моего блога?

Я настроил форму регистрации. Но не знаю, как вызвать эту форму на странице фронтенда. Любая помощь будет действительно очень полезна.

Заранее спасибо. :)

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

Лучшее решение, которое я нашел — это плагин Theme My Login.

wyrfel wyrfel
24 февр. 2011 г. 16:37:44

В этой статье представлено отличное руководство по созданию собственных форм регистрации, входа и восстановления пароля на фронтенде. Если же вы ищете плагин, то я использовал и могу порекомендовать следующие: - Ajax Login/Register - Login With Ajax

Bainternet Bainternet
24 февр. 2011 г. 17:02:00

Кристиан из Cosmolabs опубликовал отличный урок с исходными файлами, которые позволяют создать шаблоны профиля пользователя, входа и регистрации на фронтенде.

Philip Philip
24 февр. 2011 г. 19:58:41
Все ответы на вопрос 6
2
43

Процесс включает 2 шага:

  1. отображение формы на фронтенде
  2. сохранение данных при отправке

Есть 3 различных подхода, которые приходят на ум для отображения формы:

  • использовать встроенную форму регистрации, редактируя стили и т.д., чтобы сделать её более "фронтенд-ориентированной"
  • использовать страницу/запись WordPress и отображать форму через шорткод
  • использовать отдельный шаблон, не связанный ни с какой страницей/записью, но вызываемый по определённому URL

В этом ответе я использую последний вариант. Причины:

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

1: Создание URL

Все мы знаем, что стандартная форма регистрации WordPress часто становится целью спамеров. Использование кастомного URL помогает решить эту проблему. Кроме того, я хочу использовать переменный URL, т.е. URL формы регистрации не должен всегда быть одинаковым, что усложнит жизнь спамерам. Это достигается с помощью nonce в URL:

/**
* Генерация динамического URL регистрации
*/
function custom_registration_url() {
  $nonce = urlencode( wp_create_nonce( 'registration_url' ) );
  return home_url( $nonce );
}

/**
* Генерация динамической ссылки регистрации
*/
function custom_registration_link() {
  $format = '<a href="%s">%s</a>';
  printf(
    $format,
    custom_registration_url(), __( 'Зарегистрироваться', 'custom_reg_form' )
  );
}

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

2: Распознавание URL, первый набросок класса Custom_Reg\Custom_Reg

Теперь нам нужно распознать URL. Для этого я начну писать класс, который будет завершён позже в ответе:

<?php
// не сохранять, только набросок
namespace Custom_Reg;

class Custom_Reg {

  function checkUrl() {
    $url_part = $this->getUrl();
    $nonce = urlencode( wp_create_nonce( 'registration_url' ) );
    if ( ( $url_part === $nonce ) ) {
      // ничего не делать, если регистрация не разрешена или пользователь авторизован
      if ( is_user_logged_in() || ! get_option('users_can_register') ) {
        wp_safe_redirect( home_url() );
        exit();
      }
      return TRUE;
    }
  }

  protected function getUrl() {
    $home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' );
    $relative = trim(str_replace($home_path, '', esc_url(add_query_arg(array()))), '/');
    $parts = explode( '/', $relative );
    if ( ! empty( $parts ) && ! isset( $parts[1] ) ) {
      return $parts[0];
    }
  }

}

Функция проверяет первую часть URL после home_url(), и если она совпадает с нашим nonce, возвращает TRUE. Эта функция будет использоваться для проверки нашего запроса и выполнения необходимых действий для отображения формы.

3: Класс Custom_Reg\Form

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

<?php 
// файл: Form.php
namespace Custom_Reg;

class Form {

  protected $fields;

  protected $verb = 'POST';

  protected $template;

  protected $form;

  public function __construct() {
    $this->fields = new \ArrayIterator();
  }

  public function create() {
    do_action( 'custom_reg_form_create', $this );
    $form = $this->open();
    $it =  $this->getFields();
    $it->rewind();
    while( $it->valid() ) {
      $field = $it->current();
      if ( ! $field instanceof FieldInterface ) {
        throw new \DomainException( "Некорректное поле" );
      }
      $form .= $field->create() . PHP_EOL;
      $it->next();
    }
    do_action( 'custom_reg_form_after_fields', $this );
    $form .= $this->close();
    $this->form = $form;
    add_action( 'custom_registration_form', array( $this, 'output' ), 0 );
  }

  public function output() {
    unset( $GLOBALS['wp_filters']['custom_registration_form'] );
    if ( ! empty( $this->form ) ) {
      echo $this->form;
    }
  }

  public function getTemplate() {
    return $this->template;
  }

  public function setTemplate( $template ) {
    if ( ! is_string( $template ) ) {
      throw new \InvalidArgumentException( "Некорректный шаблон" );
    }
    $this->template = $template;
  }

  public function addField( FieldInterface $field ) {
    $hook = 'custom_reg_form_create';
    if ( did_action( $hook ) && current_filter() !== $hook ) {
      throw new \BadMethodCallException( "Добавляйте поля до вызова {$hook}" );
    }
    $this->getFields()->append( $field );
  }

  public function getFields() {
    return $this->fields;
  }

  public function getVerb() {
    return $this->verb;
  }

  public function setVerb( $verb ) {
    if ( ! is_string( $verb) ) {
     throw new \InvalidArgumentException( "Некорректный метод" );
    }
    $verb = strtoupper($verb);
    if ( in_array($verb, array( 'GET', 'POST' ) ) ) $this->verb = $verb;
  }

  protected function open() {
    $out = sprintf( '<form id="custom_reg_form" method="%s">', $this->verb ) . PHP_EOL;
    $nonce = '<input type="hidden" name="_n" value="%s" />';
    $out .= sprintf( $nonce,  wp_create_nonce( 'custom_reg_form_nonce' ) ) . PHP_EOL;
    $identity = '<input type="hidden" name="custom_reg_form" value="%s" />';
    $out .= sprintf( $identity,  __CLASS__ ) . PHP_EOL;
    return $out;
  }

  protected function close() {
    $submit =  __('Зарегистрироваться', 'custom_reg_form');
    $out = sprintf( '<input type="submit" value="%s" />', $submit );
    $out .= '</form>';
    return $out;
  }

}

Класс генерирует разметку формы, перебирая все добавленные поля и вызывая метод create для каждого из них. Каждое поле должно быть экземпляром Custom_Reg\FieldInterface. Добавляется скрытое поле для проверки nonce. По умолчанию метод формы - 'POST', но его можно изменить на 'GET' с помощью метода setVerb. После создания разметка сохраняется в свойстве объекта $form, которое выводится методом output(), подключённым к хуку 'custom_registration_form': в шаблоне формы достаточно вызвать do_action( 'custom_registration_form' ) для вывода формы.

4: Шаблон по умолчанию

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

<?php
// файл: default_form_template.php
get_header();

global $custom_reg_form_done, $custom_reg_form_error;

if ( isset( $custom_reg_form_done ) && $custom_reg_form_done ) {
  echo '<p class="success">';
  _e(
    'Спасибо, ваша регистрация отправлена, проверьте вашу электронную почту.',
    'custom_reg_form'
  );
  echo '</p>';
} else {
  if ( $custom_reg_form_error ) {
    echo '<p class="error">' . $custom_reg_form_error  . '</p>';
  }
  do_action( 'custom_registration_form' );
}

get_footer();

5: Интерфейс Custom_Reg\FieldInterface

Каждое поле должно быть объектом, реализующим следующий интерфейс:

<?php 
// файл: FieldInterface.php
namespace Custom_Reg;

interface FieldInterface {

  /**
   * Возвращает ID поля, используемый для имени значения запроса и параметра 'name'
   * HTML-поля ввода
   */
  public function getId();

  /**
   * Возвращает константу фильтра, которая должна использоваться с
   * filter_input для получения значения из запроса
   */
  public function getFilter();

  /**
   * Возвращает true, если переданное значение должно быть принято, false если нет
   */
  public function isValid( $value = NULL );

  /**
   * Возвращает true, если поле обязательно, false если нет
   */
  public function isRequired();

  /**
   * Возвращает разметку поля ввода. Параметр 'name' должен выводиться
   * в соответствии с getId()
   */
  public function create( $value = '');
}

Я думаю, что комментарии объясняют, что должны делать классы, реализующие этот интерфейс.

6: Добавление полей

Теперь нам нужны некоторые поля. Мы можем создать файл 'fields.php', где определим классы полей:

<?php
// файл: fields.php
namespace Custom_Reg;

abstract class BaseField implements FieldInterface {

  protected function getType() {
    return isset( $this->type ) ? $this->type : 'text';
  }

  protected function getClass() {
    $type = $this->getType();
    if ( ! empty($type) ) return "{$type}-field";
  }

  public function getFilter() {
    return FILTER_SANITIZE_STRING;
  }

  public function isRequired() {
    return isset( $this->required ) ? $this->required : FALSE;
  }

  public function isValid( $value = NULL ) {
    if ( $this->isRequired() ) {
      return $value != '';
    }
    return TRUE;
  }

  public function create( $value = '' ) {
    $label = '<p><label>' . $this->getLabel() . '</label>';
    $format = '<input type="%s" name="%s" value="%s" class="%s"%s /></p>';
    $required = $this->isRequired() ? ' required' : '';
    return $label . sprintf(
      $format,
      $this->getType(), $this->getId(), $value, $this->getClass(), $required
    );
  }

  abstract function getLabel();
}


class FullName extends BaseField {

  protected $required = TRUE;

  public function getID() {
    return 'fullname';
  }

  public function getLabel() {
    return __( 'Полное имя', 'custom_reg_form' );
  }

}

class Login extends BaseField {

  protected $required = TRUE;

  public function getID() {
    return 'login';
  }

  public function getLabel() {
    return __( 'Имя пользователя', 'custom_reg_form' );
  }
}

class Email extends BaseField {

  protected $type = 'email';

  public function getID() {
    return 'email';
  }

  public function getLabel() {
    return __( 'Email', 'custom_reg_form' );
  }

  public function isValid( $value = NULL ) {
    return ! empty( $value ) && filter_var( $value, FILTER_VALIDATE_EMAIL );
  }
}

class Country extends BaseField {

  protected $required = FALSE;

  public function getID() {
    return 'country';
  }

  public function getLabel() {
    return __( 'Страна', 'custom_reg_form' );
  }
}

Я использовал базовый класс для определения реализации интерфейса по умолчанию, однако можно добавлять очень кастомизированные поля, непосредственно реализуя интерфейс или расширяя базовый класс и переопределяя некоторые методы.

На этом этапе у нас есть всё для отображения формы, теперь нам нужно что-то для валидации и сохранения полей.

7: Класс Custom_Reg\Saver

<?php
// файл: Saver.php
namespace Custom_Reg;

class Saver {

  protected $fields;

  protected $user = array( 'user_login' => NULL, 'user_email' => NULL );

  protected $meta = array();

  protected $error;

  public function setFields( \ArrayIterator $fields ) {
    $this->fields = $fields;
  }

  /**
  * Валидация всех полей
  */
  public function validate() {
    // если регистрация не разрешена, возвращаем false
    if ( ! get_option('users_can_register') ) return FALSE;
    // если поля не заданы, возвращаем FALSE
    if ( ! $this->getFields() instanceof \ArrayIterator ) return FALSE;
    // сначала проверяем nonce
    $nonce = $this->getValue( '_n' );
    if ( $nonce !== wp_create_nonce( 'custom_reg_form_nonce' ) ) return FALSE;
    // затем проверяем все поля
    $it =  $this->getFields();
    while( $it->valid() ) {
      $field = $it->current();
      $key = $field->getID();
      if ( ! $field instanceof FieldInterface ) {
        throw new \DomainException( "Некорректное поле" );
      }
      $value = $this->getValue( $key, $field->getFilter() );
      if ( $field->isRequired() && empty($value) ) {
        $this->error = sprintf( __('%s обязательно', 'custom_reg_form' ), $key );
        return FALSE;
      }
      if ( ! $field->isValid( $value ) ) {
        $this->error = sprintf( __('%s некорректен', 'custom_reg_form' ), $key );
        return FALSE;
      }
      if ( in_array( "user_{$key}", array_keys($this->user) ) ) {
        $this->user["user_{$key}"] = $value;
      } else {
        $this->meta[$key] = $value;
      }
      $it->next();
    }
    return TRUE;
  }

  /**
  * Сохранение пользователя с помощью register_new_user, который обрабатывает проверку имени пользователя и email
  * а также отправляет письмо новому пользователю
  * дополнительно сохраняет все другие кастомные данные в метаданных пользователя
  *
  * @see register_new_user()
  */
  public function save() {
    // если регистрация не разрешена, возвращаем false
    if ( ! get_option('users_can_register') ) return FALSE;
    // проверяем обязательные поля
    if ( ! isset($this->user['user_login']) || ! isset($this->user['user_email']) ) {
      return false;
    }
    $user = register_new_user( $this->user['user_login'], $this->user['user_email'] );
    if ( is_numeric($user) ) {
      if ( ! update_user_meta( $user, 'custom_data', $this->meta ) ) {
        wp_delete_user($user);
        return FALSE;
      }
      return TRUE;
    } elseif ( is_wp_error( $user ) ) {
      $this->error = $user->get_error_message();
    }
    return FALSE;
  }

  public function getValue( $var, $filter = FILTER_SANITIZE_STRING ) {
    if ( ! is_string($var) ) {
      throw new \InvalidArgumentException( "Некорректное значение" );
    }
    $method = strtoupper( filter_input( INPUT_SERVER, 'REQUEST_METHOD' ) );
    $type = $method === 'GET' ? INPUT_GET : INPUT_POST;
    $val = filter_input( $type, $var, $filter );
    return $val;
  }

  public function getFields() {
    return $this->fields;
  }

  public function getErrorMessage() {
    return $this->error;
  }

}

Этот класс имеет 2 основных метода: один (validate), который перебирает поля, валидирует их и сохраняет корректные данные в массив, и второй (save), который сохраняет все данные в базу данных и отправляет пароль новому пользователю по email.

8: Использование определённых классов: завершение класса Custom_Reg

Теперь мы можем продолжить работу над классом Custom_Reg, добавив методы, которые "связывают" определённые объекты и заставляют их работать.

<?php 
// файл Custom_Reg.php
namespace Custom_Reg;

class Custom_Reg {

  protected $form;

  protected $saver;

  function __construct( Form $form, Saver $saver ) {
    $this->form = $form;
    $this->saver = $saver;
  }

  /**
   * Проверяет, является ли URL для страницы формы регистрации
   */
  function checkUrl() {
    $url_part = $this->getUrl();
    $nonce = urlencode( wp_create_nonce( 'registration_url' ) );
    if ( ( $url_part === $nonce ) ) {
      // ничего не делать, если регистрация не разрешена или пользователь авторизован
      if ( is_user_logged_in() || ! get_option('users_can_register') ) {
        wp_safe_redirect( home_url() );
        exit();
      }
      return TRUE;
    }
  }

  /**
   * Инициализирует форму, если отправлена - валидирует и сохраняет, если нет - просто отображает
   */
  function init() {
    if ( $this->checkUrl() !== TRUE ) return;
    do_action( 'custom_reg_form_init', $this->form );
    if ( $this->isSubmitted() ) {
      $this->save();
    }
    // не нужно создавать форму, если уже сохранено
    if ( ! isset( $custom_reg_form_done ) || ! $custom_reg_form_done ) {
      $this->form->create();
    }
    load_template( $this->getTemplate() );
    exit();
  }

  protected function save() {
    global $custom_reg_form_error;
    $this->saver->setFields( $this->form->getFields() );
    if ( $this->saver->validate() === TRUE ) { // валидация?
      if ( $this->saver->save() ) { // сохранено?
        global $custom_reg_form_done;
        $custom_reg_form_done = TRUE;
      } else { // ошибка сохранения
        $err =  $this->saver->getErrorMessage(); 
        $custom_reg_form_error = $err ? : __( 'Ошибка при сохранении.', 'custom_reg_form' );
      }
    } else { // ошибка валидации
       $custom_reg_form_error = $this->saver->getErrorMessage();
    }
  }

  protected function isSubmitted() {
    $type = $this->form->getVerb() === 'GET' ? INPUT_GET : INPUT_POST;
    $sub = filter_input( $type, 'custom_reg_form', FILTER_SANITIZE_STRING );
    return ( ! empty( $sub ) && $sub === get_class( $this->form ) );
  }

  protected function getTemplate() {
    $base = $this->form->getTemplate() ? : FALSE;
    $template = FALSE;
    $default = dirname( __FILE__ ) . '/default_form_template.php';
    if ( ! empty( $base ) ) {
      $template = locate_template( $base );
    }
    return $template ? : $default;
  }

   protected function getUrl() {
    $home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' );
    $relative = trim( str_replace( $home_path, '', add_query_arg( array() ) ), '/' );
    $parts = explode( '/', $relative );
    if ( ! empty( $parts ) && ! isset( $parts[1] ) ) {
      return $parts[0];
    }
  }

}

Конструктор класса принимает экземпляр Form и Saver.

Метод init() (используя checkUrl()) проверяет первую часть URL после home_url(), и если она совпадает с правильным nonce, проверяет, была ли форма уже отправлена, и если да, использует объект Saver для валидации и сохранения данных пользователя, в противном случае просто выводит форму.

Метод init() также запускает хук действия 'custom_reg_form_init', передавая экземпляр формы в качестве аргумента: этот хук должен использоваться для добавления полей, настройки кастомного шаблона и также для кастомизации метода формы.

9: Собираем всё вместе

Теперь нам нужно написать основной файл плагина, где мы можем:

  • подключить все файлы
  • загрузить текстовый домен
  • запустить весь процесс, создав экземпляр класса Custom_Reg и вызвав метод init() на достаточно раннем хуке
  • использовать 'custom_reg_form_init' для добавления полей в класс формы

Итак:

<?php 
/**
 * Plugin Name: Кастомная форма регистрации
 * Description: Пример плагина для ответа на вопрос WPSE
 * Plugin URI: https://wordpress.stackexchange.com/questions/10309/
 * Author: G. M.
 * Author URI: https://wordpress.stackexchange.com/users/35541/g-m
 *
 */

if ( is_admin() ) return; // этот плагин только для фронтенда

load_plugin_textdomain(
  'custom_reg_form',
  FALSE,
  plugin_dir_path( __FILE__ ) . 'langs'
); 

require_once plugin_dir_path( __FILE__ ) . 'FieldInterface.php';
require_once plugin_dir_path( __FILE__ ) . 'fields.php';
require_once plugin_dir_path( __FILE__ ) . 'Form.php';
require_once plugin_dir_path( __FILE__ ) . 'Saver.php';
require_once plugin_dir_path( __FILE__ ) . 'CustomReg.php';

/**
* Генерация динамического URL регистрации
*/
function custom_registration_url() {
  $nonce = urlencode( wp_create_nonce( 'registration_url' ) );
  return home_url( $nonce );
}

/**
* Генерация динамической ссылки регистрации
*/
function custom_registration_link() {
  $format = '<a href="%s">%s</a>';
  printf(
    $format,
    custom_registration_url(), __( 'Зарегистрироваться', 'custom_reg_form' )
  );
}

/**
* Настройка, отображение и сохранение формы
*/
add_action( 'wp_loaded', function() {
  try {
    $form = new Custom_Reg\Form;
    $saver = new Custom_Reg\Saver;
    $custom_reg = new Custom_Reg\Custom_Reg( $form, $saver );
    $custom_reg->init();
  } catch ( Exception $e ) {
    if ( defined('WP_DEBUG') && WP_DEBUG ) {
      $msg = 'Исключение в ' . __FUNCTION__;
      $msg .= ', Тип: ' . get_class( $e ) . ', Сообщение: ';
      $msg .= $e->getMessage() ? : 'Неизвестная ошибка';
      error_log( $msg );
    }
    wp_safe_redirect( home_url() );
  }
}, 0 );

/**
* Добавление полей в форму
*/
add_action( 'custom_reg_form_init', function( $form ) {
  $classes = array(
    'Custom_Reg\FullName',
    'Custom_Reg\Login',
    'Custom_Reg\Email',
    'Custom_Reg\Country'
  );
  foreach ( $classes as $class ) {
    $form->addField( new $class );
  }
}, 1 );

10: Оставшиеся задачи

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

Мы можем добавить специфичные стили и скрипты только для страницы кастомной регистрации таким образом:

add_action( 'wp_enqueue_scripts', function() {
  // если не на кастомной форме регистрации, ничего не делать
  if ( did_action('custom_reg_form_init') ) {
    wp_enqueue_style( ... );
    wp_enqueue_script( ... );
  }
});

Используя этот метод, мы можем подключить некоторые JS-скрипты для обработки валидации на стороне клиента, например, этот. Разметка, необходимая для работы этого скрипта, может быть легко обработана редактированием класса Custom_Reg\BaseField.

Если мы хотим кастомизировать письмо регистрации, мы можем использовать стандартный метод и, имея кастомные данные, сохранённые в мета, использовать их в письме.

Последняя задача, которую мы, вероятно, захотим реализовать, - это запрет запросов к стандартной форме регистрации, что легко сделать:

add_action( 'login_form_register', function() { exit(); } );

Все файлы можно найти в Gist здесь.

13 мар. 2014 г. 04:23:56
Комментарии

Вау, это полная переработка функционала регистрации! Вероятно, это хорошее решение, если вы хотите полностью переопределить встроенный процесс регистрации. Я считаю, что не использовать встроенную форму регистрации — не лучшая идея, потому что вы потеряете другие базовые возможности, такие как форма восстановления пароля. И тогда новому зарегистрированному пользователю придётся показывать традиционную форму входа в админку для авторизации.

Fabien Quatravaux Fabien Quatravaux
13 мар. 2014 г. 16:21:08

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

gmazzap gmazzap
13 мар. 2014 г. 16:45:12
2
17

Кратко: Поместите следующую форму в свою тему, атрибуты name и id важны:

<form action="<?php echo site_url('wp-login.php?action=register', 'login_post') ?>" method="post">
    <input type="text" name="user_login" value="Имя пользователя" id="user_login" class="input" />
    <input type="text" name="user_email" value="E-Mail" id="user_email" class="input"  />
    <?php do_action('register_form'); ?>
    <input type="submit" value="Зарегистрироваться" id="register" />
</form>

Я нашел отличную статью на Tutsplus о Создании красивой формы регистрации в WordPress с нуля. В ней много времени уделено стилизации формы, но есть довольно простой раздел о необходимом коде для WordPress:

Шаг 4. WordPress

Здесь нет ничего сложного; нам нужны только два сниппета из WordPress, скрытых в файле wp-login.php.

Первый сниппет:

<?php echo site_url('wp-login.php?action=register', 'login_post') ?>  

И второй:

<?php do_action('register_form'); ?>

Редактирование: Я добавил последнюю часть из статьи, объясняющую, куда вставлять эти сниппеты — это просто форма, поэтому её можно разместить в любом шаблоне страницы, сайдбаре или создать шорткод. Важный раздел — это form, который содержит указанные сниппеты и обязательные поля.

Финальный код должен выглядеть так:

<div style="display:none"> <!-- Регистрация -->
        <div id="register-form">
        <div class="title">
            <h1>Зарегистрируйте свой аккаунт</h1>
            <span>Присоединяйтесь к нам и наслаждайтесь!</span>
        </div>
            <form action="<?php echo site_url('wp-login.php?action=register', 'login_post') ?>" method="post">
            <input type="text" name="user_login" value="Имя пользователя" id="user_login" class="input" />
            <input type="text" name="user_email" value="E-Mail" id="user_email" class="input"  />
                <?php do_action('register_form'); ?>
                <input type="submit" value="Зарегистрироваться" id="register" />
            <hr />
            <p class="statement">Пароль будет отправлен вам по электронной почте.</p>


            </form>
        </div>
</div><!-- /Регистрация -->

Обратите внимание, что очень важно и необходимо, чтобы у текстового поля ввода был атрибут name и id со значением user_login; то же самое касается поля для email. Иначе форма не будет работать.

На этом всё!

30 янв. 2012 г. 12:35:09
Комментарии

Отличное решение! Простое и эффективное. Но куда вы вставляете эти фрагменты кода? В боковую панель? Похоже, этот совет работает только с AJAX-формой регистрации.

Fabien Quatravaux Fabien Quatravaux
17 мар. 2014 г. 10:12:17

Спасибо @FabienQuatravaux, я обновил ответ, включив последний раздел статьи. Вам не нужна AJAX-форма - достаточно обычной POST-формы, которая отправляет данные на страницу wp-login.php?action=register

icc97 icc97
18 мар. 2014 г. 12:31:02
0

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

Если же вы ищете плагин, то я ранее использовал эти и могу их рекомендовать:

24 февр. 2011 г. 17:02:00
0

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

Вот шаги, которые я выполнил:

1) Активируйте возможность для всех посетителей запрашивать новую учетную запись через Настройки > Общие > Опция "Членство". Страница регистрации теперь доступна по URL /wp-login.php?action=register

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

Вот пример с темой twentythirteen:

// подключаем скрипты и стили темы на странице входа/регистрации
add_action('login_enqueue_scripts', 'twentythirteen_scripts_styles');

// удаляем стили админки на странице входа/регистрации
add_filter( 'style_loader_tag', 'user16975_remove_admin_css', 10, 2);
function user16975_remove_admin_css($tag, $handle){
    if ( did_action('login_init')
    && ($handle == 'wp-admin' || $handle == 'buttons' || $handle == 'colors-fresh'))
        return "";

    else return $tag;
}

// отображаем шапку и подвал фронтенда на странице входа/регистрации
add_action('login_footer', 'user16975_integrate_login');
function user16975_integrate_login(){
    ?><div id="page" class="hfeed site">
        <header id="masthead" class="site-header" role="banner">
            <a class="home-link" href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
                <h1 class="site-title"><?php bloginfo( 'name' ); ?></h1>
                <h2 class="site-description"><?php bloginfo( 'description' ); ?></h2>
            </a>

            <div id="navbar" class="navbar">
                <nav id="site-navigation" class="navigation main-navigation" role="navigation">
                    <h3 class="menu-toggle"><?php _e( 'Меню', 'twentythirteen' ); ?></h3>
                    <a class="screen-reader-text skip-link" href="#content" title="<?php esc_attr_e( 'Перейти к содержимому', 'twentythirteen' ); ?>"><?php _e( 'Перейти к содержимому', 'twentythirteen' ); ?></a>
                    <?php wp_nav_menu( array( 'theme_location' => 'primary', 'menu_class' => 'nav-menu' ) ); ?>
                    <?php get_search_form(); ?>
                </nav><!-- #site-navigation -->
            </div><!-- #navbar -->
        </header><!-- #masthead -->

        <div id="main" class="site-main">
    <?php get_footer(); ?>
    <script>
        // перемещаем форму входа в основную область содержимого страницы
        jQuery('#main').append(jQuery('#login'));
    </script>
    <?php
}

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

3) Вы можете дополнительно изменить форму, настроив отображаемые сообщения:

add_filter('login_message', 'user16975_login_message');
function user16975_login_message($message){
    if(strpos($message, 'register') !== false){
        $message = 'настраиваемое сообщение регистрации';
    } else {
        $message = 'настраиваемое сообщение входа';
    }
    return $message;
}

add_action('login_form', 'user16975_login_message2');
function user16975_login_message2(){
    echo 'еще одно настраиваемое сообщение входа';
}

add_action('register_form', 'user16975_tweak_form');
function user16975_tweak_form(){
    echo 'еще одно настраиваемое сообщение регистрации';
}

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

add_filter('user_has_cap', 'user16975_refine_role', 10, 3);
function user16975_refine_role($allcaps, $cap, $args){
    global $pagenow;

    $user = wp_get_current_user();
    if($user->ID != 0 && $user->roles[0] == 'subscriber' && is_admin()){
        // запрещаем доступ к админке
        $allcaps['read'] = false;
    }

    return $allcaps;
}

add_action('admin_page_access_denied', 'user16975_redirect_dashbord');
function user16975_redirect_dashbord(){
    wp_redirect(home_url());
    die();
}

Шагов много, но результат того стоит!

12 мар. 2014 г. 02:03:32
0

Гораздо проще: используйте функцию WordPress под названием wp_login_form() (Страница в Codex здесь).

Вы можете создать собственный плагин, чтобы использовать шорткод на одной из ваших страниц:

<?php
/*
Plugin Name: WP Login Form Shortcode
Description: Используйте <code>[wp_login_form]</code> для отображения формы входа WordPress.
Version: 1.0
Author: WP-Buddy
Author URI: http://wp-buddy.com
License: GPLv2 or later
*/

add_action( 'init', 'wplfsc_add_shortcodes' );

function wplfsc_add_shortcodes() {
    add_shortcode( 'wp_login_form', 'wplfsc_shortcode' );
}

function wplfsc_shortcode( $atts, $content, $name ) {

$atts = shortcode_atts( array(
        'redirect'       => site_url( $_SERVER['REQUEST_URI'] ),
        'form_id'        => 'loginform',
        'label_username' => __( 'Имя пользователя' ),
        'label_password' => __( 'Пароль' ),
        'label_remember' => __( 'Запомнить меня' ),
        'label_log_in'   => __( 'Войти' ),
        'id_username'    => 'user_login',
        'id_password'    => 'user_pass',
        'id_remember'    => 'rememberme',
        'id_submit'      => 'wp-submit',
        'remember'       => false,
        'value_username' => NULL,
        'value_remember' => false
), $atts, $name );

// echo всегда false
$atts['echo'] = false;

// преобразуем в реальные булевы значения
$atts['remember']       = filter_var( $atts['remember'], FILTER_VALIDATE_BOOLEAN );
$atts['value_remember'] = filter_var( $atts['value_remember'], FILTER_VALIDATE_BOOLEAN );

return '<div class="cct-login-form">' . wp_login_form( $atts ) . '</div>';

}

Все, что вам осталось сделать — это стилизовать форму на фронтенде.

26 авг. 2014 г. 10:35:37
5
-1

Если вы открыты к использованию плагинов, я ранее использовал аддон User Registration для Gravity Forms, и он отлично работал:

http://www.gravityforms.com/add-ons/user-registration/

Примечание: понимаю, что это не очень детализированное решение, но оно делает именно то, что вам нужно, и является хорошим вариантом.

Дополнение: чтобы расширить мой ответ, аддон User Registration для Gravity Forms позволяет сопоставлять любые поля в форме, созданной с помощью Gravity Forms, с пользовательскими полями. Например, вы можете создать форму с полями Имя, Фамилия, Email, Веб-сайт, Пароль. При отправке формы аддон сопоставит эти поля с соответствующими полями пользователя.

Еще одно отличное преимущество — вы можете добавлять зарегистрированных пользователей в очередь на одобрение. Их учетные записи будут созданы только после утверждения администратором в админ-панели.

Если ссылка выше не работает, просто найдите в Google "User Registration add on for Gravity Forms".

18 мар. 2014 г. 16:20:22
Комментарии

Вы прочитали примечания, которые @kaiser добавил к вопросу (выделено мной): "Мы ищем развернутые ответы, которые содержат объяснения и контекст. Не ограничивайтесь односрочным ответом; объясните, почему ваш ответ верен, желательно со ссылками на источники. Ответы без объяснений могут быть удалены"

gmazzap gmazzap
18 мар. 2014 г. 16:32:17

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

James Kemp James Kemp
18 мар. 2014 г. 16:39:14

Я не модератор, поэтому не могу перенести ваш ответ в комментарии. Я могу только поставить минус, но я этого не сделал, так как считаю, что ваша ссылка содержит полезную информацию. Однако ответ, состоящий только из ссылки, бесполезен, тем более что ссылка может измениться, и тогда ваш ответ приведёт к 404 ошибке. Попробуйте привести здесь соответствующий код и объяснить, что он делает, тогда ваш ответ, на мой взгляд, будет в порядке.

gmazzap gmazzap
18 мар. 2014 г. 16:45:09

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

kaiser kaiser
19 мар. 2014 г. 00:17:37

Привет, Kaiser, я не гонюсь за наградой, просто хотел поделиться своими знаниями о плагине!

James Kemp James Kemp
19 мар. 2014 г. 11:13:34