Formulario de registro básico en Symfony 1.4

marzo 1, 2011

Es dificil no desarrollar una web sin tener registro de usuarios. Para Symfony 1.4 podemos encontrar gran cantidad de plugins que se encargan de esta función como pueden ser sfGuardPlugin (para Propel) y sfDoctrineGuardPlugin (para Doctrine). Estos plugins son muy completos y útiles, pudiéndolos usar en cualquiera de nuestros proyectos donde necesitemos las operaciones básicas con usuarios (registro, login, etc).

Para este post, la intención es crear un formulario de registro de usuarios sencillo desde cero para Symfony 1.4, sin la complejidad de un plugin ya que muchas veces tienen funcionalidades que no necesitaremos en nuestro proyecto.

Antes de empezar, evidentemente, crearemos un proyecto nuevo y generamos un modulo llamado «user».

Primero modificamos el archivo schema.yml, añadiendo una tabla user básica y sencilla.

/config/doctrine/schema.yml

1
2
3
4
5
6
7
8
9
User:
  tableName: user
  actAs:
    Timestampable: ~
  columns:
    email:
      type: string(255)
    password:
      type: string(45)

Indicamos que se comporte como Timestampable para que se creen automáticamente los campos created_at y updated_at. No nos olvidemos generar las consultas sql y ejecutarlas en nuestra base de datos.

En el segundo paso, vamos a crear el formulario para el registro del usuario. Creamos un archivo nuevo en /lib/form/ llamado RegisterForm.class.php

/lib/form/RegisterForm.class.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
class RegisterForm extends BaseForm
{
    public function configure()
    {
        parent::configure();
 
        $this->setWidgets(array(
	    'email'     => new sfWidgetFormInput(),
	    'password'  => new sfWidgetFormInputPassword(),
            'password2' => new sfWidgetFormInputPassword(),
	));
 
	$this->setValidators(array(
            'email'        => new sfValidatorEmail(array('required'=>true), array('required'=> "El email es obligatorio")),
            'password'  => new sfValidatorString(array('required'=>true), array('required'=> "La contraseña es obligatoria")),
            'password2' => new sfValidatorString(array('required'=>true), array('required'=> "La contraseña es obligatoria")),
	));
 
	$this->widgetSchema->setNameFormat('register[%s]');
        $this->widgetSchema->setFormFormatterName('list');
 
        $this->validatorSchema->setPostValidator(new sfValidatorAnd(array(
            new sfValidatorSchemaCompare('password2', sfValidatorSchemaCompare::EQUAL, 'password', array('throw_global_error' => true), array('invalid' => "Las dos contraseñas no coinciden")),
            new sfValidatorDoctrineUnique(array('model' => 'User', 'column' => array('email')), array('invalid'=> "Este email ya está en uso"))
        )));
    }
}

Los formularios pueden darnos muchos quebraderos de cabeza al principio ya que es algo dificil de entender a la primera, por lo que voy a explicarlo un poco más en detalle.

1
2
3
4
5
$this->setWidgets(array(
    'email'     => new sfWidgetFormInput(),
    'password'  => new sfWidgetFormInputPassword(),
    'password2' => new sfWidgetFormInputPassword(),
));

Indicamos que para el campo email queremos un input normal. Como se puede apreciar, le decimos que para los campos contraseña queremos un campo input password.

1
2
3
4
5
$this->setValidators(array(
    'email'        => new sfValidatorEmail(array('required'=>true), array('required'=> "El email es obligatorio")),
    'password'  => new sfValidatorString(array('required'=>true), array('required'=> "La contraseña es obligatoria")),
    'password2' => new sfValidatorString(array('required'=>true), array('required'=> "La contraseña es obligatoria")),
));

Ahora los validadores. El campo email, evidentemente, debe ser un email. El validador sfValidatorEmail se encarga de comprobar que sea un formato de email válido.
Los campos password son obligatorios y no pueden estar vacíos. Podríamos decirle que tienen que tener una longitud mínima y máxima con las opciones max_length y min_length.

1
2
3
4
$this->validatorSchema->setPostValidator(new sfValidatorAnd(array(
    new sfValidatorSchemaCompare('password2', sfValidatorSchemaCompare::EQUAL, 'password', array('throw_global_error' => true), array('invalid' => "Las dos contraseñas no coinciden")),
    new sfValidatorDoctrineUnique(array('model' => 'User', 'column' => array('email')), array('invalid'=> "Este email ya está en uso"))
)));

Vamos a añadir unos validadores un poco más complejos. En el primero, comprobamos que los dos campos de contraseña deben ser iguales. Para ello utilizamos el validador sfValidatorSchemaCompare. Es típico hacer esta comprobación en todos los formularios de registro de usuarios.
En el segundo caso, comprobamos que el email introducido por el usuario no esté ya introducido en la base de datos y, por tanto, en uso por otro usuario. Utilizamos el validador sfValidatorDoctrineUnique.

Ya tenemos el formulario preparado para su uso. Editamos el archivo actions.class.php de nuestro módulo «user» y añadimos la acción «Register»:

/apps/frontend/modules/user/actions/actions.class.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
class userActions extends sfActions
{
  public function executeRegister(sfWebRequest $request)
  {
 
    $this->redirectIf($this->getUser()->isAuthenticated(), "@homepage");
 
    $this->form = new RegisterForm();
 
    if($request->isMethod("post")){
 
       $this->form->bind($request->getParameter("register"));
       if($this->form->isValid()){
 
           $user = new User();
           $user->email = $this->form->getValue("email");
           $user->password = md5($this->form->getValue("password")); // podriamos utilizar otro sistema para encriptar la contraseña
           $user->save();
 
           $url = $this->getUser()->getAttribute("referer",false)?:"@homepage";
           $this->getUser()->setAttribute("referer",false);
           $this->redirect($url);
       }
    }
  }
}

En la línea 7 le indicamos que si el usuario ya está logueado le redirija a la homepage.

Hemos utilizado el algoritmo md5 para encriptar la contraseña antes de guardarla en la base de datos. Podríamos utilizar otro algoritmo como sha1 o uno propio. Es totalmente recomendable encriptar las contraseñas y no guardarlas en texto plano en nuestra base de datos por motivos de seguridad.

Por último, creamos la plantilla donde se mostrará el formulario de registro.

/apps/frontend/modules/user/templates/registerSuccess.php

1
2
3
4
<form action="<?php echo url_for("@user_register"); ?>" method="post">
  <?php echo $form; ?>
  <input type="submit" value="Registrarse" />
</form>

Debemos añadir la siguiente ruta en el archivo routing.yml:

user_register:
  url:   /register
  param: { module: user, action: register }

Y eso es todo, ya hemos creado un sistema muy básico de registro de usuarios en Symfony 1.4. A partir de aquí se puede expandir e incluir las funcionalidades que queramos.
En un próximo post, realizaremos el login y el logout.

Cualquier duda o si hay que explicar algo mejor, en los comentarios 🙂

Tags ; , ,

7 comentarios

    Manuel May 09, 2011

    Hola,

    Quiero darte las gracias porque estoy empezando con Symfony y este post me ha servido de mucha ayuda. Solo quería hacerte una pregunta: en la accion register cual es la utilidad de las ultimas 3 lineas en las que consultas si esta definido el atributo referer. Igual es una tonteria pero ahora mismo no me doy cuenta.

    Gracias por adelantado

    Responder
    Jon May 09, 2011

    Hola Manuel, muchas gracias, me alegro de que te haya sido de utilidad.

    Las 3 últimas líneas donde se comprueba si está definido el atributo referer es precisamente para eso, para comprobar si tenemos que redirigir a la url de la que venimos.

    Quizás en el registro no tenga mucho sentido pero, en en login, normalmente redirigimos a la página desde la que hemos hecho click en el enlace que nos lleva a la página de logueo para seguir navegando por donde estábamos.

    Un saludo.

    Responder
    Manuel May 10, 2011

    Perdona, igual no me he explicado bien. Lo que queria saber es si tu le asignas ese atributo a la sesion del usuario en algun lado o symfony ya por defecto lo hace y siempre le asigna el atributo referer. Pensaba que la sesion de usuario por defecto no tiene atributos definidos, sino es asi podrias decirme donde consultarlos? Yo lo que hice en el executeLogin tuyo es quitar las tres ultimas lineas y añadir «$this->redirect($request->getReferer());». Con esto me funciona, no se si será la mejor opción y si le ayudará a alguien.

    Gracias por adelantado y disculpa la ignorancia de un novato 🙂

    Responder
    Jon May 12, 2011

    Eso está perfecto Manuel.

    Puedes utilizar $request->getReferer() sin problemas.

    Un saludo.

    Responder
    Fran Ago 03, 2011

    el metodo save donde se encuentra implementado, gracias!

    Responder
    juan Sep 08, 2011

    muchas gracias por estos artículos acerca de la programación usando symfony, yo apenas estoy comenzando con este framework y hasta el momento me ha parecido muy interesante, solo tengo una duda respecto a esto de crear formularios, yo estoy utilizando propel como orm y por lo que pude ver tu utilizar doctrine así que mi pregunta es ¿Cual es el equivalente en propel a sfValidatorDoctrineUnique? es algo así como sfValidatorPropelUnique? o es algo completamente diferente? espero y me puedas responder pronto y gracias por tu esfuerzo me alegra que haya gente como tu dispuesta a compartir sus conocimientos

    Responder
    Jon Sep 08, 2011

    Hola Juan, como bien dices, si utilizas propel el validador que tienes que utilizar es sfValidatorPropelUnique. La forma de utilizarlo sería así:

    $this->validatorSchema->setPostValidator(
    new sfValidatorPropelUnique(array(‘model’ => ‘User’, ‘column’ => array(‘email’)), array(‘invalid’=> «Este email ya está en uso»))
    );

    Responder

Responde a Jon Cancelar la respuesta

Los comentarios son moderados y se utiliza rel="nofollow" para los enlaces.