¿Cómo mostrar el formulario de registro de usuarios en el front-end del sitio web?

24 feb 2011, 16:07:30
Vistas: 175K
Votos: 37

¿Cómo puedo mostrar el formulario de registro de usuarios de WordPress (el formulario que aparece en la página "www.mywebsite.com/wp-register.php") en el front-end de mi blog?

He personalizado el formulario de registro. Pero no sé cómo llamar a ese formulario en la página del front-end. Cualquier ayuda será realmente valiosa.

Gracias de antemano. :)

3
Comentarios

La mejor solución que encontré es el plugin Theme My Login.

wyrfel wyrfel
24 feb 2011 16:37:44

Este artículo proporciona un gran tutorial sobre cómo crear tus propios formularios de registro/inicio de sesión/recuperación de contraseña en el frontend. O si estás buscando un plugin, he usado estos antes y puedo recomendarlos: - Ajax Login/Register - Login With Ajax

Bainternet Bainternet
24 feb 2011 17:02:00

Cristian de Cosmolabs ha publicado un excelente tutorial con archivos fuente que te dan la capacidad de construir plantillas de Perfil de Usuario, Inicio de Sesión y Registro en el frontend.

Philip Philip
24 feb 2011 19:58:41
Todas las respuestas a la pregunta 6
2
43

El proceso involucra 2 pasos:

  1. mostrar el formulario en el frontend
  2. guardar los datos al enviar

Hay 3 enfoques diferentes que se me ocurren para mostrar el frontend:

  • usar el formulario de registro incorporado, editando estilos, etc. para hacerlo más "parecido al frontend"
  • usar una página/entrada de WordPress, y mostrar el formulario usando un shortcode
  • usar una plantilla dedicada no conectada a ninguna página/entrada, pero llamada por una URL específica

Para esta respuesta usaré el último. Las razones son:

  • usar el formulario de registro incorporado puede ser una buena idea, pero personalizaciones profundas pueden ser muy difíciles usando el formulario incorporado, y si también se quieren personalizar los campos del formulario, el dolor aumenta
  • usar una página de WordPress en combinación con un shortcode no es tan confiable, y también creo que los shortcodes no deberían usarse para funcionalidad, solo para formato y similares

1: Construir la URL

Todos sabemos que el formulario de registro predeterminado de un sitio WordPress es a menudo un objetivo para spammers. Usar una URL personalizada ayuda a resolver este problema. Además, también quiero usar una URL variable, es decir, la URL del formulario de registro no debería ser siempre la misma, esto hace la vida más difícil a los spammers. El truco se hace usando un nonce en la URL:

/**
* Generar URL de registro dinámica
*/
function custom_registration_url() {
  $nonce = urlencode( wp_create_nonce( 'registration_url' ) );
  return home_url( $nonce );
}

/**
* Generar enlace de registro dinámico
*/
function custom_registration_link() {
  $format = '<a href="%s">%s</a>';
  printf(
    $format,
    custom_registration_url(), __( 'Registrarse', 'custom_reg_form' )
  );
}

Usando estas funciones es fácil mostrar en las plantillas un enlace al formulario de registro incluso si es dinámico.

2: Reconocer la URL, primer esbozo de la clase Custom_Reg\Custom_Reg

Ahora necesitamos reconocer la URL. Para el propósito comenzaré a escribir una clase, que se completará más adelante en la respuesta:

<?php
// no guardar, solo un esbozo
namespace Custom_Reg;

class Custom_Reg {

  function checkUrl() {
    $url_part = $this->getUrl();
    $nonce = urlencode( wp_create_nonce( 'registration_url' ) );
    if ( ( $url_part === $nonce ) ) {
      // no hacer nada si el registro no está permitido o el usuario está conectado
      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];
    }
  }

}

La función mira la primera parte de la URL después de home_url(), y si coincide con nuestro nonce devuelve TRUE. Esta función se usará para verificar nuestra solicitud y realizar las acciones necesarias para mostrar nuestro formulario.

3: La clase Custom_Reg\Form

Ahora escribiré una clase, que será responsable de generar el marcado del formulario. También la usaré para almacenar en una propiedad la ruta del archivo de plantilla que debería usarse para mostrar el formulario.

<?php 
// archivo: 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( "Campo inválido" );
      }
      $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( "Plantilla inválida" );
    }
    $this->template = $template;
  }

  public function addField( FieldInterface $field ) {
    $hook = 'custom_reg_form_create';
    if ( did_action( $hook ) && current_filter() !== $hook ) {
      throw new \BadMethodCallException( "Agrega campos antes de que se dispare {$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( "Verbo inválido" );
    }
    $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 =  __('Registrarse', 'custom_reg_form');
    $out = sprintf( '<input type="submit" value="%s" />', $submit );
    $out .= '</form>';
    return $out;
  }

}

La clase genera el marcado del formulario recorriendo todos los campos agregados llamando al método create en cada uno de ellos. Cada campo debe ser una instancia de Custom_Reg\FieldInterface. Se agrega un campo oculto adicional para la verificación del nonce. El método del formulario es 'POST' por defecto, pero se puede establecer en 'GET' usando el método setVerb. Una vez creado, el marcado se guarda dentro de la propiedad del objeto $form que se muestra mediante el método output(), enganchado en el gancho 'custom_registration_form': en la plantilla del formulario, simplemente llamar a do_action( 'custom_registration_form' ) mostrará el formulario.

4: La plantilla predeterminada

Como dije, la plantilla para el formulario se puede anular fácilmente, sin embargo, necesitamos una plantilla básica como respaldo. Escribiré aquí una plantilla muy rudimentaria, más una prueba de concepto que una plantilla real.

<?php
// archivo: 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(
    'Gracias, tu registro fue enviado, revisa tu correo electrónico.',
    '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: La interfaz Custom_Reg\FieldInterface

Cada campo debe ser un objeto que implemente la siguiente interfaz

<?php 
// archivo: FieldInterface.php
namespace Custom_Reg;

interface FieldInterface {

  /**
   * Devuelve el id del campo, usado para nombrar el valor de la solicitud y para el parámetro 'name' de
   * el campo de entrada html
   */
  public function getId();

  /**
   * Devuelve la constante de filtro que debe usarse con
   * filter_input para obtener el valor de la solicitud
   */
  public function getFilter();

  /**
   * Devuelve true si el valor usado pasado como argumento debe ser aceptado, false si no
   */
  public function isValid( $value = NULL );

  /**
   * Devuelve true si el campo es obligatorio, false si no
   */
  public function isRequired();

  /**
   * Devuelve el marcado de entrada del campo. El parámetro 'name' debe mostrarse 
   * de acuerdo a getId()
   */
  public function create( $value = '');
}

Creo que los comentarios explican lo que deben hacer las clases que implementan esta interfaz.

6: Agregar algunos campos

Ahora necesitamos algunos campos. Podemos crear un archivo llamado 'fields.php' donde definamos las clases de los campos:

<?php
// archivo: 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 __( 'Nombre completo', 'custom_reg_form' );
  }

}

class Login extends BaseField {

  protected $required = TRUE;

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

  public function getLabel() {
    return __( 'Nombre de usuario', 'custom_reg_form' );
  }
}

class Email extends BaseField {

  protected $type = 'email';

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

  public function getLabel() {
    return __( 'Correo electrónico', '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 __( 'País', 'custom_reg_form' );
  }
}

He usado una clase base para definir la implementación predeterminada de la interfaz, sin embargo, se pueden agregar campos muy personalizados implementando directamente la interfaz o extendiendo la clase base y sobrescribiendo algunos métodos.

En este punto tenemos todo para mostrar el formulario, ahora necesitamos algo para validar y guardar los campos.

7: La clase Custom_Reg\Saver

<?php
// archivo: 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;
  }

  /**
  * validar todos los campos
  */
  public function validate() {
    // si el registro no está permitido, devuelve false
    if ( ! get_option('users_can_register') ) return FALSE;
    // si no se establecen campos, devuelve FALSE
    if ( ! $this->getFields() instanceof \ArrayIterator ) return FALSE;
    // primero verificar nonce
    $nonce = $this->getValue( '_n' );
    if ( $nonce !== wp_create_nonce( 'custom_reg_form_nonce' ) ) return FALSE;
    // luego verificar todos los campos
    $it =  $this->getFields();
    while( $it->valid() ) {
      $field = $it->current();
      $key = $field->getID();
      if ( ! $field instanceof FieldInterface ) {
        throw new \DomainException( "Campo inválido" );
      }
      $value = $this->getValue( $key, $field->getFilter() );
      if ( $field->isRequired() && empty($value) ) {
        $this->error = sprintf( __('%s es obligatorio', 'custom_reg_form' ), $key );
        return FALSE;
      }
      if ( ! $field->isValid( $value ) ) {
        $this->error = sprintf( __('%s no es válido', '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;
  }

  /**
  * Guardar el usuario usando register_new_user que maneja la verificación de nombre de usuario y correo electrónico
  * y también envía correo electrónico al nuevo usuario
  * además guarda todos los demás datos personalizados en los metadatos del usuario
  *
  * @see register_new_user()
  */
  public function save() {
    // si el registro no está permitido, devuelve false
    if ( ! get_option('users_can_register') ) return FALSE;
    // verificar campos obligatorios
    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( "Valor inválido" );
    }
    $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;
  }

}

Esa clase tiene 2 métodos principales, uno (validate) que recorre los campos, los valida y guarda los datos correctos en un array, el segundo (save) guarda todos los datos en la base de datos y envía la contraseña por correo electrónico al nuevo usuario.

8: Usando las clases definidas: terminando la clase Custom_Reg

Ahora podemos trabajar nuevamente en la clase Custom_Reg, agregando los métodos que "unen" los objetos definidos y los hacen funcionar

<?php 
// archivo 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;
  }

  /**
   * Verificar si la URL para reconocer es la de la página del formulario de registro
   */
  function checkUrl() {
    $url_part = $this->getUrl();
    $nonce = urlencode( wp_create_nonce( 'registration_url' ) );
    if ( ( $url_part === $nonce ) ) {
      // no hacer nada si el registro no está permitido o el usuario está conectado
      if ( is_user_logged_in() || ! get_option('users_can_register') ) {
        wp_safe_redirect( home_url() );
        exit();
      }
      return TRUE;
    }
  }

  /**
   * Inicializar el formulario, si se envía, validar y guardar, si no, solo mostrarlo
   */
  function init() {
    if ( $this->checkUrl() !== TRUE ) return;
    do_action( 'custom_reg_form_init', $this->form );
    if ( $this->isSubmitted() ) {
      $this->save();
    }
    // no es necesario crear el formulario si ya se guardó
    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 ) { // ¿validar?
      if ( $this->saver->save() ) { // ¿guardado?
        global $custom_reg_form_done;
        $custom_reg_form_done = TRUE;
      } else { // error al guardar
        $err =  $this->saver->getErrorMessage(); 
        $custom_reg_form_error = $err ? : __( 'Error al guardar.', 'custom_reg_form' );
      }
    } else { // error de validación
       $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];
    }
  }

}

El constructor de la clase acepta una instancia de Form y una de Saver.

El método init() (usando checkUrl()) mira la primera parte de la URL después de home_url(), y si coincide con el nonce correcto, verifica si el formulario ya fue enviado, si es así, usando el objeto Saver, valida y guarda los datos del usuario, de lo contrario solo imprime el formulario.

El método init() también dispara el gancho de acción 'custom_reg_form_init' pasando la instancia del formulario como argumento: este gancho debe usarse para agregar campos, configurar la plantilla personalizada y también para personalizar el método del formulario.

9: Uniendo todo

Ahora necesitamos escribir el archivo principal del plugin, donde podemos

  • requerir todos los archivos
  • cargar el dominio de texto
  • iniciar todo el proceso instanciando la clase Custom_Reg y llamando al método init() en ella usando un gancho razonablemente temprano
  • usar 'custom_reg_form_init' para agregar los campos a la clase del formulario

Entonces:

<?php 
/**
 * Plugin Name: Formulario de registro personalizado
 * Description: Solo un ejemplo de plugin para responder una pregunta en 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; // este plugin es todo sobre el frontend

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';

/**
* Generar URL de registro dinámica
*/
function custom_registration_url() {
  $nonce = urlencode( wp_create_nonce( 'registration_url' ) );
  return home_url( $nonce );
}

/**
* Generar enlace de registro dinámico
*/
function custom_registration_link() {
  $format = '<a href="%s">%s</a>';
  printf(
    $format,
    custom_registration_url(), __( 'Registrarse', 'custom_reg_form' )
  );
}

/**
* Configurar, mostrar y guardar el formulario
*/
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 = 'Excepción en ' . __FUNCTION__;
      $msg .= ', Tipo: ' . get_class( $e ) . ', Mensaje: ';
      $msg .= $e->getMessage() ? : 'Error desconocido';
      error_log( $msg );
    }
    wp_safe_redirect( home_url() );
  }
}, 0 );

/**
* Agregar campos al formulario
*/
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: Tareas faltantes

Ahora todo está bastante hecho. Solo nos queda personalizar la plantilla, probablemente agregando un archivo de plantilla personalizado en nuestro tema.

Podemos agregar estilos y scripts específicos solo a la página de registro personalizado de esta manera

add_action( 'wp_enqueue_scripts', function() {
  // si no está en el formulario de registro personalizado, no hacer nada
  if ( did_action('custom_reg_form_init') ) {
    wp_enqueue_style( ... );
    wp_enqueue_script( ... );
  }
});

Usando ese método podemos encolar algunos scripts js para manejar la validación del lado del cliente, por ejemplo, este. El marcado necesario para que ese script funcione se puede manejar fácilmente editando la clase Custom_Reg\BaseField.

Si queremos personalizar el correo electrónico de registro, podemos usar métodos estándar y teniendo datos personalizados guardados en meta, podemos hacer uso de ellos en el correo electrónico.

La última tarea que probablemente queremos implementar es evitar solicitudes al formulario de registro predeterminado, tan fácil como:

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

Todos los archivos se pueden encontrar en un Gist aquí.

13 mar 2014 04:23:56
Comentarios

¡Vaya, esto es un rediseño completo de la funcionalidad de registro! Probablemente sea una buena solución si deseas anular completamente el proceso de registro incorporado. Creo que no usar el formulario de registro incorporado no es una buena idea porque perderás otras características principales como el formulario de contraseña perdida. Y luego, un usuario recién registrado necesitaría mostrar el formulario de inicio de sesión tradicional del backend para acceder.

Fabien Quatravaux Fabien Quatravaux
13 mar 2014 16:21:08

@FabienQuatravaux la contraseña perdida y el formulario de inicio de sesión se pueden usar como de costumbre (backend). Sí, el código está incompleto porque no se manejan el formulario de contraseña perdida y el de inicio de sesión, pero la pregunta del OP era solo sobre el formulario de registro y la respuesta ya era demasiado larga para agregar otras funcionalidades...

gmazzap gmazzap
13 mar 2014 16:45:12
2
17

TLDR; Coloca el siguiente formulario en tu tema, los atributos name e id son importantes:

<form action="<?php echo site_url('wp-login.php?action=register', 'login_post') ?>" method="post">
    <input type="text" name="user_login" value="Nombre de usuario" id="user_login" class="input" />
    <input type="text" name="user_email" value="Correo electrónico" id="user_email" class="input"  />
    <?php do_action('register_form'); ?>
    <input type="submit" value="Registrarse" id="register" />
</form>

Encontré un excelente artículo de Tutsplus sobre Cómo crear un formulario de registro elegante para WordPress desde cero. Dedica bastante tiempo al diseño del formulario, pero incluye la siguiente sección bastante simple sobre el código requerido en WordPress:

Paso 4. WordPress

No hay nada complicado aquí; solo necesitamos dos fragmentos de código de WordPress, ocultos dentro del archivo wp-login.php.

El primer fragmento:

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

Y:

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

Edición: He añadido la parte final del artículo para explicar dónde colocar los fragmentos de código anteriores - es solo un formulario, así que puede ir en cualquier plantilla de página, barra lateral o convertirse en un shortcode. La sección importante es el form que contiene los fragmentos anteriores y los campos obligatorios necesarios.

El código final debería verse así:

<div style="display:none"> <!-- Registro -->
        <div id="register-form">
        <div class="title">
            <h1>Registra tu cuenta</h1>
            <spanRegístrate con nosotros y disfruta!</span>
        </div>
            <form action="<?php echo site_url('wp-login.php?action=register', 'login_post') ?>" method="post">
            <input type="text" name="user_login" value="Nombre de usuario" id="user_login" class="input" />
            <input type="text" name="user_email" value="Correo electrónico" id="user_email" class="input"  />
                <?php do_action('register_form'); ?>
                <input type="submit" value="Registrarse" id="register" />
            <hr />
            <p class="statement">Se te enviará una contraseña por correo electrónico.</p>

            </form>
        </div>
</div><!-- /Registro -->

Ten en cuenta que es realmente importante y necesario tener user_login como atributo name e id en tu campo de texto; lo mismo aplica para el campo de correo electrónico. De lo contrario, no funcionará.

¡Y con eso, hemos terminado!

30 ene 2012 12:35:09
Comentarios

¡Excelente solución! Simple y eficiente. Pero ¿dónde colocas esos fragmentos de código? ¿En una barra lateral? Este consejo parece funcionar solo con un formulario de registro AJAX.

Fabien Quatravaux Fabien Quatravaux
17 mar 2014 10:12:17

Gracias @FabienQuatravaux, he actualizado la respuesta para incluir la última sección del artículo. No debería ser necesario un formulario AJAX - es simplemente un formulario POST que se envía a la página wp-login.php?action=register

icc97 icc97
18 mar 2014 12:31:02
0

Este artículo proporciona un excelente tutorial sobre cómo crear tus propios formularios de registro, inicio de sesión y recuperación de contraseña en el frontend.

O si estás buscando un plugin, he utilizado estos antes y puedo recomendarlos:

24 feb 2011 17:02:00
0

Hace algún tiempo creé un sitio web que mostraba un formulario de registro personalizado en el front-end. Este sitio ya no está en línea, pero aquí hay algunas capturas de pantalla. formulario de inicio de sesión formulario de registro formulario de contraseña perdida

Estos son los pasos que seguí:

1) Activar la posibilidad de que todos los visitantes puedan solicitar una nueva cuenta mediante Configuración > General > Opción de Membresía. La página de registro ahora aparece en la URL /wp-login.php?action=register

2) Personalizar el formulario de registro para que coincida con el front-end de tu sitio. Esto es más complicado y depende del tema que estés utilizando.

Aquí hay un ejemplo con twentythirteen:

// incluir scripts y estilos del tema en la página de inicio de sesión/registro
add_action('login_enqueue_scripts', 'twentythirteen_scripts_styles');

// eliminar estilos de administración en la página de inicio de sesión/registro
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;
}

// mostrar cabecera y pie de página del front-end en la página de inicio de sesión/registro
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( 'Menú', 'twentythirteen' ); ?></h3>
                    <a class="screen-reader-text skip-link" href="#content" title="<?php esc_attr_e( 'Saltar al contenido', 'twentythirteen' ); ?>"><?php _e( 'Saltar al contenido', '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>
        // mover el formulario de inicio de sesión al área de contenido principal de la página
        jQuery('#main').append(jQuery('#login'));
    </script>
    <?php
}

Luego modifica la hoja de estilos del tema para que el formulario aparezca como desees.

3) Puedes modificar aún más el formulario ajustando los mensajes mostrados:

add_filter('login_message', 'user16975_login_message');
function user16975_login_message($message){
    if(strpos($message, 'register') !== false){
        $message = 'mensaje personalizado de registro';
    } else {
        $message = 'mensaje personalizado de inicio de sesión';
    }
    return $message;
}

add_action('login_form', 'user16975_login_message2');
function user16975_login_message2(){
    echo 'otro mensaje personalizado de inicio de sesión';
}

add_action('register_form', 'user16975_tweak_form');
function user16975_tweak_form(){
    echo 'otro mensaje personalizado de registro';
}

4) Si necesitas un formulario de registro en el front-end, probablemente no quieras que los usuarios registrados vean el backend cuando inicien sesión.

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()){
        // denegar acceso al backend de WordPress
        $allcaps['read'] = false;
    }

    return $allcaps;
}

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

Hay muchos pasos, ¡pero el resultado está aquí!

12 mar 2014 02:03:32
0

Mucho más fácil: usa una función de WordPress llamada wp_login_form() (página del Codex aquí).

Puedes crear tu propio plugin para usar un shortcode en una de tus páginas:

<?php
/*
Plugin Name: WP Login Form Shortcode
Description: Usa <code>[wp_login_form]</code> para mostrar el formulario de inicio de sesión de 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' => __( 'Nombre de usuario' ),
        'label_password' => __( 'Contraseña' ),
        'label_remember' => __( 'Recuérdame' ),
        'label_log_in'   => __( 'Iniciar sesión' ),
        '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 siempre es false
$atts['echo'] = false;

// convertir a valores booleanos reales
$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>';

}

Todo lo que tienes que hacer es dar estilo a tu formulario en el frontend.

26 ago 2014 10:35:37
5
-1

Si estás abierto al uso de plugins, he utilizado antes el complemento de Registro de Usuario para Gravity Forms y funcionó muy bien:

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

Edición: Me doy cuenta de que esta no es una solución muy detallada, pero hace exactamente lo que necesitas y es una buena solución.

Edición: Para ampliar más mi respuesta, el complemento de Registro de Usuario para Gravity Forms te permite asignar cualquier campo en un formulario creado con Gravity Forms a campos específicos del usuario. Por ejemplo, puedes crear un formulario con Nombre, Apellido, Correo electrónico, Sitio web, Contraseña. Al enviarlo, el complemento asignará esas entradas a los campos relevantes del usuario.

Otra gran ventaja es que puedes añadir usuarios registrados a una cola de aprobación. Sus cuentas de usuario solo se crearán una vez que un administrador las apruebe en el backend.

Si el enlace anterior deja de funcionar, simplemente busca en Google "User Registration add on for Gravity Forms"

18 mar 2014 16:20:22
Comentarios

¿Has leído las notas que @kaiser agregó a la pregunta (en negrita las mías): "Estamos buscando respuestas largas que brinden alguna explicación y contexto. No solo des una respuesta de una línea; explica por qué tu respuesta es correcta, idealmente con citas. Las respuestas que no incluyan explicaciones pueden ser eliminadas"

gmazzap gmazzap
18 mar 2014 16:32:17

Las he leído, pero sentí que el complemento aún vale la pena mencionarlo, ya que el OP no menciona la necesidad de codificarlo personalmente. Feliz de moverlo a un comentario si crees que es necesario

James Kemp James Kemp
18 mar 2014 16:39:14

No soy moderador, así que no puedo mover tu respuesta a un comentario. Solo puedo votar en contra, pero no lo he hecho porque creo que tu enlace contiene información útil, sin embargo, una respuesta que solo contiene un enlace no es útil, incluso porque ese enlace puede cambiar fácilmente y entonces tu respuesta lleva a un error 404. Intenta publicar aquí el código relevante y explica lo que hace ese código, entonces tu respuesta estaría bien, supongo.

gmazzap gmazzap
18 mar 2014 16:45:09

James, asigné la recompensa a una respuesta real que incluía código. Si quieres una recompensa adicional, por favor desmenuza el plugin y muéstranos exactamente lo que está haciendo. Gracias.

kaiser kaiser
19 mar 2014 00:17:37

Hola Kaiser, no busco la recompensa, solo quería compartir mi conocimiento sobre el plugin.

James Kemp James Kemp
19 mar 2014 11:13:34