En el grupo de Symfony2 hay una gran cantidad de preguntas entre las que, de vez en cuando, podemos encontrar un buen hilo donde se trata un tema interesante. Entre tanta “paja” (preguntas fáciles de responder solamente leyendo la documentación) es posible que pasemos por alto alguna de estas buenas preguntas junto a sus respuestas.
Voy a intentar recopilar este tipo de hilos y traducirlos al castellano, siempre dejando el enlace al hilo original del grupo de Symfony2 por si hay alguna nueva respuesta.
Para empezar, podemos encontrar como utilizar Sphinx haciendo uso de la api como un servicio en Symfony2.
1) Nos descargamos la api de Sphinx de la página oficial http://sphinxsearch.com/, colocándolo en la carpeta vendor/sphinx-client. Debemos renombrar la clase a SphinxClient.
2) Lo añadimos en el autoload.php
$loader->registerPrefixes(array( // ... 'Sphinx' => __DIR__.'/../vendor/sphinx-client', ));
3) Añadimos Sphinx como servicio de Symfony2 en el fichero config.yml
services: search: class: SphinxClient calls: - [setArrayResult, [true]] - [setLimits, [0, 20, 1000]]
4) Por último, podemos hacer uso del servicio desde el controlador de esta forma:
$search = $this->get('search'); $results = $search->Query($search_terms, 'myindex');
Evidentemente deberemos leer la documentación de Sphinx para instarlo y configurarlo correctamente. La página oficial es bastante completa en ese sentido.
Hilo original: doctrine2 and sphinx
Etiquetas: autoload, controlador, doctrine2, servicio, sphinx, Symfony2
Por programador inquieto englobamos a una persona proactiva, autodidacta, le gusta aprender cosas nuevas, capacidad de trabajo en equipo, apasionado de la programación y un largo etcétera. Vamos, alguien que cuando llega a casa investiga nuevos lenguajes de programación, desarrolla algún proyecto propio, seguramente tenga blog, compra y lee libros técnicos (aunque la temática no sea precisamente sobre programación), etc.
El opuesto a este programador es aquel que llega y sale del trabajo a su hora, no toca un ordenador si no es el del trabajo y únicamente programa en la tecnología utilizada en la empresa (y no le interesa aprender otra cosa). Este segundo tipo de programador tiene, en general, bastante más tiempo libre que el “inquieto”.
Para este post voy a suponer que los dos empleados son excelentes en sus puestos de trabajo en la empresa.
Después de describir a los dos tipos de programadores (opuestos, cada uno está en un extremo) pasamos a la siguiente pregunta, ¿qué tipo de programador me merece la pena ser? Esta pregunta me surge después de acudir al evento #desymfony en Castellón donde, en general, las empresas dicen tener dificultades para encontrar programadores (de los inquietos, está claro).
Me hubiera gustado preguntar (y no lo hice) cuantos de los presentes en ese momento (cerca de 200 programadores) habían aprendido Symfony (framework php sobre el que se centraba el evento) en sus empresas y cuantos en su tiempo libre fuera del horario laboral. Quizás esté equivocado, pero creo que la gran mayoría lo habrá aprendido en su tiempo libre.
Y ahora viene la pregunta del título del post: ¿Cuánto merece ganar este programador? Hubiese sido muy atrevido preguntar el sueldo de los asistentes. Quizás me vuelva a equivocar, pero creo que la gran mayoría andará en torno a los 1000 euros. Un mil eurista de los que están ahora tan de moda. Entonces, suponiendo que los asistentes al evento son de la clase de programadores inquietos, obtienen un salario de un trabajador “acomodado” después de “molestarse” en aprender Symfony (seguro que también otras muchas cosas) en su tiempo libre.
Entonces, ¿en que quedamos? ¿me merece la pena ser de los programadores inquietos? Te sentirás realizado, aprenderás cosas nuevas, harás algún proyecto por tu cuenta del que puede que te sientas orgulloso, optarás a numerosas ofertas de empleo (si quieres dejar el actual) casi sin problemas, etc.
¿O me merece la pena ser de los segundos programadores? Trabajarás sobre lo que sabes en tu horario laboral y después tendrás bastante tiempo libre (incluido el fin de semana). Te sentirás igualmente realizado por el trabajo bien hecho, puede que estés orgullos de alguno de los proyectos que has desarrollado en tu empresa, etc.
Está claro que es lo que quieren las empresas: trabajadores “inquietos” con sueldo de trabajador “acomodado”.
Si se juntan los dos tipos de programadores en una misma empresa, ¿quién acabará quemado antes? Ya lo digo yo: el programador inquieto. Por que no olvidemos que trabajamos para vivir (aunque, desgraciadamente para algunos, muchas veces sea al contrario) y si no ves recompensado tu trabajo, puedes acabar con la moral bastante baja y conectado a infojobs más de lo que quisieras.
Es como el ejemplo del niño que acababa el primero los deberes en clase porque tenía algo más de nivel que el resto de niños. El profesor, en lugar de recompensarle, lo que hacía era darle el mismo trato que a los demás alumnos y mandarle más deberes. Después de ocurrir esto en varias ocasiones, el niño decide no entregar los deberes antes que los demás. Recibe el mismo trato que el resto de la clase (como hasta ahora) pero sin tener que hacer el doble de deberes.
Y tú, ¿que tipo de programador eres?
Etiquetas: autodidacta, empleo, programador inquieto, programadores, tiempo libre
Nos vamos acercando inevitablemente al cambio de Symfony 1.x a Symfony2 y la conclusión que he sacado de mi asistencia al evento #desymfony es que cuanto antes nos pongamos con ello, mucho mejor. Symfony2 mejora a su predecesor en numerosos aspectos y se convertirá en el framework definitivo para el desarrollo de aplicaciones web en el futuro. Si quieres saber todas las nuevas características de esta versión, te recomiendo que visites la web oficial de Symfony2: http://symfony.com/.
En este primer post procederemos a su instalación. Personalmente, me gusta programar en local (en mi propio ordenador) y una vez haya acabado con el desarrollo o quiera probarlo en un entorno de producción, hacer el deploy a un servidor real. Por ello, primero voy a explicar como configurar un servidor web en nuestro ordenador y después procederemos con la instalación de Symfony2.
La instalación la voy a hacer en un entorno Linux con la distribución Ubuntu 11.04. Adaptar los comandos según nuestra distribución (o sistema operativo).
1) Primero instalamos Apache
# apt-get install apache2 apache2.2-common apache2-utils ssl-cert apache2-mpm-prefork
2) Instalamos y habilitamos el módulo para utilizar modrewrite
# apt-get install libapache2-mod-proxy-html
Para habilitar el modulo en apache, ejecutamos:
# a2enmod rewrite
3) Instalamos PHP5
# apt-get install php5 libapache2-mod-php5 php5-common php5-intl
4) Instalamos Mysql
# apt-get install mysql-server mysql-client php5-mysql
5) Por último instalamos phpmyadmin (opcional)
# apt-get install phpmyadmin
Con estos sencillos pasos ya tendremos un servidor web instalado en nuestro ordenador.
Ahora continuamos con la instalación de Symfony2. Mi IDE favorito para programar es Netbeans, por lo que es el que utilizaré en este ejemplo. Si no lo hemos cambiado, nuestro workspace (donde se encuentran los proyectos a los que podemos acceder desde Netbeans) lo encontraremos en la carpeta NetBeansProjects en nuestra carpeta Home.
Procedemos a crear una nueva carpeta con el nombre de nuestro proyecto en el workspace de Netbeans:
$ mkdir $HOME/NetBeansProjects/miproyectoEntramos en la carpeta que acabamos de crear:
$ cd $HOME/NetBeansProjects/miproyectoDescargamos Symfony2 (comprueba la última versión en http://symfony.com/download):
$ wget http://symfony.com/download?v=Symfony_Standard_Vendors_2.0.0-RC4.tgz
Y descomprimimos:
$ tar zxvf Symfony_Standard_Vendors_2.0.0-RC4.tgz
Borramos el archivo comprimido que hemos descargado:
$ rm Symfony_Standard_Vendors_2.0.0-RC4.tgz
Ya tenemos instalado un proyecto básico en Symfony2. Ahora vamos a configurar Apache para poder acceder desde nuestro navegador favorito.
Creamos un nuevo archivo donde irá la configuración de nuestra web:
# vi /etc/apache2/sites-available/miproyecto
Que contendrá el siguiente contenido (cambia “jonseg” por el nombre de tu carpeta Home):
<VirtualHost *:80> ServerAdmin email@email.com DocumentRoot /home/jonseg/NetBeansProjects/miproyecto/Symfony/web ServerName miproyecto.com ServerAlias *.miproyecto.com ErrorLog /var/log/apache2/miproyecto_error.log CustomLog /var/log/apache2/miproyecto_access.log common DirectoryIndex index.php <Directory "/home/jonseg/NetBeansProjects/miproyecto/Symfony/web"> Options Indexes FollowSymLinks Order Allow,Deny Allow from all AllowOverride all <IfModule mod_php5.c> php_admin_flag engine on php_admin_flag safe_mode off php_admin_value open_basedir none </ifModule> </Directory> </VirtualHost>
Creamos un enlace simbólico de este archivo en sites-enabled para indicar que es una web activa:
# ln -s /etc/apache2/sites-available/miproyecto /etc/apache2/sites-enabled/miproyecto
Para que se apliquen los cambios, reiniciamos el servidor Apache:
# /etc/init.d/apache2 restart
Por último, forzamos en el archivo /etc/hosts la ip de nuestra web, que en este caso será localhost o 127.0.0.1
# vim /etc/hosts
Y añadimos esta línea al final del fichero:
127.0.0.1 www.miproyecto.com miproyecto.com
Después de todo esto, ya podremos acceder a nuestro nuevo proyecto en Symfony2 desde el navegador escribiendo la url que hemos configurado.
Como primer paso, debemos comprobar si cumplimos con la configuración básica para que funcione nuestro proyecto. Lo haremos desde la siguiente url:
http://miproyecto.com/config.php
Como vemos, nos encontramos con dos problemas (podríamos tener más, deberemos resolverlos según sea necesario). En este caso el error es que las carpetas app/cache y app/logs no tienen los permisos necesarios.
Lo arreglaremos así:
chmod 777 $HOME/NetBeansProjects/miproyecto/Symfony/app/cache chmod 777 $HOME/NetBeansProjects/miproyecto/Symfony/app/logs
Una vez arreglados los problemas, ya podemos acceder a nuestro proyecto web con Symfony2 mediante esta url:
http://miproyecto.com/app_dev.php/
En próximos artículos nos iremos adentrando poco a poco en el desarrollo de Bundles, las plantillas con Twig, etc.
Cualquier duda, en los comentarios!
Etiquetas: localhost, netbeans, php, servidor, Symfony, Symfony2
Una de las dificultades que podemos encontrar al utilizar el ORM Doctrine (por ejemplo, en Symfony) es configurar las relaciones entre tablas en el schema.yml que define nuestra base de datos. A modo de ejemplo, voy a mostrar los tres tipos de relaciones que podemos querer configurar:
Un caso típico para este tipo de relación es el de un usuario y su perfil. Un usuario solamente tiene un perfil y un perfil solo puede pertenecer a un usuario.
User:
tableName: user
columns:
id:
type: integer(4)
primary: true
notnull: true
autoincrement: true
email:
type: string(255)
notnull: true
unique: true
password:
type: string(45)
Profile:
tableName: profile
columns:
user_id:
type: integer(4)
primary: true
notnull: true
autoincrement: false
nickname: string(255)
relations:
User:
class: User
local: user_id
foreign: id
foreignAlias: Profile
type: one
foreignType: oneCon esta relación, podremos acceder al perfil de un usuario así:
$user->Profile->nickname // obtenemos el nickname del perfil del usuario
Un ejemplo de este tipo de relación es el de los usuarios y sus números de teléfono. Un usuario puede tener varios números de teléfono pero un teléfono solo puede pertenecer a un usuario.
User:
tableName: user
columns:
id:
type: integer(4)
primary: true
notnull: true
autoincrement: true
email:
type: string(255)
notnull: true
unique: true
password:
type: string(45)
Telephone:
tableName: telephone
columns:
id:
type: integer(4)
primary: true
notnull: true
autoincrement: true
user_id:
type: integer(4)
notnull: true
number:
type: string(255)
relations:
User:
class: User
local: user_id
foreign: id
foreignAlias: Telephones
type: one
foreignType: manyPara acceder a los números de teléfono de un usuario, podemos hacer:
foreach($user->Telephones as $telephone){ echo $telephone->number; }
Para terminar, un caso típico de esta relación es la que podemos encontrar entre los artículos de un blog y sus etiquetas. Un artículo puede tener varias etiquetas y una etiqueta puede asignarse a varios artículos. En esta relación necesitaremos obligatoriamente una tercera tabla (article_tags) para poder relacionar la tabla articles y la tabla tags.
Article:
tableName: articles
columns:
id:
type: integer(4)
primary: true
notnull: true
autoincrement: true
title:
type: string(100)
notnull: true
Tag:
tableName: tags
columns:
id:
type: integer(4)
primary: true
notnull: true
autoincrement: true
name:
type: string(100)
notnull: true
relations:
Article:
foreignAlias: Tags
class: Article
refClass: ArticleTag
ArticleTag:
tableName: article_tags
columns:
article_id:
type: integer(4)
primary: true
tag_id:
type: integer(4)
primary: true
relations:
Article:
foreignAlias: ArticleTags
Tag:
foreignAlias: ArticleTagsPodremos obtener el nombre de todos los tags de un artículo de la siguiente manera:
foreach($article->ArticleTags as $article_tag){ echo $article_tag->Tag->name; }
¡Cualquier duda, en los comentarios!
Etiquetas: base de datos, doctrine, relaciones, Symfony
Existe un problema bastante frecuente cuando ejecutamos un task en Symfony 1.4, pareciéndonos el siguiente error:
“The default context does not exist”
El problema es que estás utilizando un método de un objeto que utiliza sfContext (para recuperar valores del archivo app.yml, por ejemplo). Parece ser que Symfony no crea una instancia de sfContext y nos devuelve este error.
La siguiente línea debería resolver el problema. La colocaremos en primer lugar dentro de la función execute:
sfContext::createInstance($this->configuration);
Por ejemplo:
1 2 3 4 5 | protected function execute ($arguments = array(), $options = array()) { sfContext::createInstance($this->configuration); // Aqui nuestro codigo } |
En el post anterior creamos un sistema de registro de usuarios básico para Symfony 1.4. Lo que vamos a hacer ahora es un sistema de login (y logout) para que el usuario pueda iniciar sesión en nuestra web.
Primero creamos el formulario de login, por lo que creamos un nuevo archivo:
/lib/form/LoginForm.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 | <?php class LoginForm extends BaseForm { public function configure() { parent::configure(); $this->setWidgets(array( 'email' => new sfWidgetFormInput(), 'password' => 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'=>'Escribe tu contraseña')), )); $this->widgetSchema->setNameFormat('login[%s]'); $this->widgetSchema->setFormFormatterName('list'); } } |
El formulario no tiene mayor misterior. Un input text para el email y un input password para la contraseña. Validamos que se hayan rellenado los dos campos.
Editamos las actions del módulo user que creamos en el post anterior para añadir el login.
/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 28 29 30 31 | <?php class userActions extends sfActions { public function executeLogin(sfWebRequest $request) { $this->form = new LoginForm(); if($request->isMethod("post")){ $this->form->bind($request->getParameter("login")); if($this->form->isValid()){ if(!$user = UserTable::login($this->form->getValue("email"), $this->form->getValue("password"))){ // No hemos conseguido loguear al usuario // Redirigimos de nuevo al login con un mensaje de error $this->getUser()->setFlash("error", "datos incorrectos"); $this->redirect("@user_login"); }else{ // Logueamos $this->getUser()->setAuthenticated(true); $this->getUser()->setAttribute("id",$user->id); // Comprobamos si tiene referer, si no, le llevamos a la homepage $url = $this->getUser()->getAttribute("referer",false)?:"@homepage"; $this->getUser()->setAttribute("referer", false); $this->redirect($url); } } } } |
Tenemos que comprobar si existe ese email junto con esa contraseña en nuestra base de datos. Si es así, logueamos al usuario y, si no, mostramos un mensaje de error.
La comprobación de si existe el usuario en la base de datos la hacemos en la linea 12, donde llamamos al método estático “login” del archivo UserTable.class.php del modelo.
/lib/model/doctrine/UserTable.class.php
1 2 3 4 5 6 7 8 9 10 11 | <?php class UserTable extends Doctrine_Table { public static function login($email,$password){ return Doctrine_Query::create() ->from('User u') ->where('u.email = ?', array($email)) ->andWhere('u.password = ?', array(md5($password))) // Podrimos usar otro algoritmo, en este caso utilizamos md5 ->fetchOne(); } } |
Y eso es todo, lo más sencillo para el final: la plantilla donde mostramos el formulario.
/apps/frontend/modules/user/templates/loginSuccess.php
1 2 3 4 5 6 7 | <?php if($sf_user->getFlash("error")): ?> <div class="error"><?php echo $sf_user->getFlash("error"); ?></div> <?php endif; ?> <form action="<?php echo url_for("@user_login"); ?>" method="post"> <?php echo $form; ?> <input type="submit" value="Entrar" /> </form> |
En este paso sería lógico desarrollar el logout para poder cerrar la sesión en la web. Para ello modificamos de nuevo la actions de nuestro módulo para añadir la nueva funcionalidad:
/apps/frontend/modules/user/actions/actions.class.php
1 2 3 4 5 6 7 8 9 | <?php class userActions extends sfActions { public function executeLogout(sfWebRequest $request){ $this->getUser()->setAuthenticated(false); $this->getUser()->getAttributeHolder()->clear(); $this->redirect("@homepage"); } } |
Para ejecutar el logout, solo debemos crear un enlace en nuestra web donde se llame a esta action. No necesitamos plantilla ya que después de logout siempre redirigiremos a la homepage.
<?php echo link_to("Cerrar sesión", '@user_logout'); ?>
Debemos añadir las siguientes rutas en el archivo routing.yml:
user_login:
url: /login
param: { module: user, action: login }
user_logout:
url: /logout
param: { module: user, action: logout }Cualquier duda en los comentarios!
Etiquetas: formularios, login, logout, registro, Symfony
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
Etiquetas: formularios, registro, Symfony
En este ejemplo, vamos a rellenar un spinner (un combo, select o como queráis llamarlo) con los datos que tenemos en un array.
Añadimos el spinner en la plantilla:
<Spinner android:id="@+id/spinner_animales" android:layout_width="wrap_content" android:layout_height="wrap_content" />
Creamos un archivo llamado arrays.xml en la carpeta /res/values/ de nuestro proyecto e insertamos el siguiente contenido:
<resources> <string-array name="animales"> <item>Elefante</item> <item>Tortuga</item> <item>Conejo</item> <item>Ratón</item> </string-array> </resources>
Por último, en la activity asignamos el array anterior al spinner mediante un ArrayAdapter:
Spinner spinner_animales = (Spinner) findViewById(R.id.spinner_animales); ArrayAdapter spinner_adapter = ArrayAdapter.createFromResource( this, R.array.animales , android.R.layout.simple_spinner_item); spinner_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner_animales.setAdapter(spinner_adapter);
Y eso es todo. Si ejecutamos el proyecto se mostrará el spinner con los elementos del array.
Etiquetas: Android, array, arrayadapter, spinner
Error tonto donde los haya relacionado con el sistema de control de versiones svn, pero que nos puede llevar un buen rato y algún que otro quebradero de cabeza dar con la solución.
Si intentamos hacer un commit de los cambios con la orden:
svn commit -m "plugins" ./proyecto/plugins
Nos mostrará el siguiente error:
svn: The log message is a pathname (was -F intended?); use '--force-log' to override
El “error” es que el mensaje que adjuntamos con el commit es igual al nombre de la carpeta que estamos subiendo. Lo arreglaremos cambiando el nombre del mensaje:
svn commit -m "cambios en plugins" ./proyecto/plugins
Etiquetas: svn
Cuando tenemos un servidor recién instalado, nos podemos encontrar con que algunos paquetes necesarios no están instalados en el sistema. Esto me ha ocurrido al intentar generar un nuevo proyecto con Symfony 1.4 en un servidor con OpenSuse 11.1.
Al intentar crear un nuevo proyecto con el comando:
php symfony generate:project miproyecto
La orden no se ejecutaba en su totalidad y me dejaba unos “bonitos” mensajes de error, relacionados con la función token_get_all():
PHP Notice: Use of undefined constant T_FINAL - assumed 'T_FINAL' in /var/symfony14/lib/util/sfClassManipulator.class.php on line 52 PHP Notice: Use of undefined constant T_ABSTRACT - assumed 'T_ABSTRACT' in /var/symfony14/lib/util/sfClassManipulator.class.php on line 52 PHP Notice: Use of undefined constant T_STATIC - assumed 'T_STATIC' in /var/symfony14/lib/util/sfClassManipulator.class.php on line 52 PHP Notice: Use of undefined constant T_PUBLIC - assumed 'T_PUBLIC' in /var/symfony14/lib/util/sfClassManipulator.class.php on line 52 PHP Notice: Use of undefined constant T_PROTECTED - assumed 'T_PROTECTED' in /var/symfony14/lib/util/sfClassManipulator.class.php on line 52 PHP Notice: Use of undefined constant T_PRIVATE - assumed 'T_PRIVATE' in /var/symfony14/lib/util/sfClassManipulator.class.php on line 52 PHP Notice: Use of undefined constant T_FUNCTION - assumed 'T_FUNCTION' in /var/symfony14/lib/util/sfClassManipulator.class.php on line 52 PHP Fatal error: Call to undefined function token_get_all() in /var/symfony14/lib/util/sfClassManipulator.class.php on line 117
Este problema con la función token_get_all() lo solucionaremos instalando la extensión para php “php5-tokenizer”:
zypper install php5-tokenizerMe he encontrado este error al generar un nuevo proyecto con Symfony pero nada tiene que ver con el framework. Quizás para cualquier otro proyecto donde no utilicemos Symfony no nos haga falta instalarlo y no lo echemos de menos. Visto lo visto, con Symfony es totalmente necesario tener esta extensión instalada.
Etiquetas: opensuse, php, php5-tokenizer, Symfony, zypper