Archive: cakePhp

multilenguaje en cakephp (Internationalization & Localization)

 

cakePhp, Emprendedor

La primera parte que es internacionalización, es muy importante tenerla prevista antes de empezar un proyecto en cakephp, lo que hago en cualquier proyecto por muy grande o pequeño que sea es dejarlo preparado.

Es fácil dejarlo listo para traducir, en vez de poner los textos sin más, hacelo de la siguiente manera.

__('texto para traducir', true);

Ya lo tenemos preparado por si nos piden multilenguaje en un futuro. Ahora si lo necesitamos hacer, el siguiente paso es crear los archivos con tantos idiomas se requiera, por ejemplo de ingles y español.

Crearíamos las siguientes carpetas y archivos dentro de la carpeta locale:
eng/LC_MESSAGES/default.po
esp/LC_MESSAGES/default.po

Ahora viene la parte que mas me ha costado, y más divertida, pasar el script que coge todos los textos traducibles, y crea archivos con las palabras a traducir . El script lo lanzo desde eclipse, os dejo un pantallazo de la configuración para lanzar el script.

Crea varios archivos, solo hay que abrir estos archivos, copiar lo que hay y pegarlo dento de los archivos que hemos creado default.po
Para editar los archivos .po os recomiendo el editor poedit, desde aquí ya se traduce con facilidad.

Ya tenemos una parte muy importante, podríamos cambiar de idioma copiando lo siguiente en app_controller.php

Configure::write('Config.language', 'esp');

o

Configure::write('Config.language', 'eng');

Ahora entramos en la segunda parte Localización.
Hay muchas maneras de hacerlo, os voy a presentar una sencilla, cuando estoy en la página en inglés tener el link para pasarla a castellano y viceversa.

En config/route.php copiar el siguiente código, para reconocer el idioma:

Router::connect('/:language/:controller/:action/*',
                       array(),
                       array('language' => '[a-z]{3}'));

En app_controller.php necesitamos definir el idioma predefinido, llamar a los componenetes cookie y session, ver y guardar en cookie el idioma que queremos.

$lang='esp';
Configure::write('Config.language', $lang);

class AppController extends Controller {

	var $helpers = array('Html', 'Form', 'Ajax','Javascript','Bonzzay');
	var $components = array('Session', 'Cookie'); 

	function beforeFilter() {
	    $this->_setLanguage();
	} 

	function _setLanguage() {

	    if ($this->Cookie->read('lang') && !$this->Session->check('Config.language')) {
	        $this->Session->write('Config.language', $this->Cookie->read('lang'));
	    }
	    else if (isset($this->params['language']) && ($this->params['language']
	             !=  $this->Session->read('Config.language'))) {     

	        $this->Session->write('Config.language', $this->params['language']);
	        $this->Cookie->write('lang', $this->params['language'], false, '20 days');
	    }
	}

}

Lo último que nos falta hacer es poner el link para cambiar el idioma, pero debemos saber en que idiomas estamos para saber que link poner, asi que primero vamos al controlador o en el mismo app_controller y ponemos el siguiente código, que recoge, que tenemos como lenguaje definido en cookie y lo envia a vista.

function beforeRender() {
		$idioma = $this->Cookie->read('lang');
		$this->set('idioma',$idioma);
	}

Recojo en vista el idioma definido y según el idioma definido tengo un link u otro.

$this->languageswitch($idioma);
function languageswitch($idioma){
		$content ="";
		if($idioma == 'esp'){
			$content .= $this->Html->link(__("English",true), array('language'=>'eng'));
		}else if($idioma == 'eng'){
			$content .= $this->Html->link(__("English",true), array('language'=>'esp'));
		}else{
			$content .= $this->Html->link(__("English",true), array('language'=>'eng'));
		}
		return $content;
	}

Bueno esto ya estaría, espero haberme explicado bien, se que son muchas cosas, muchos conceptos, pero leyendo antes el cookbook de cakephp, ayuda entender mejor como funciona.

Formulario Ajax en Cakephp

 

cakePhp

Algo que a veces queremos hacer, es al tener un formulario, ver los datos enviados desde el formulario si refrescar la página.
Un ejemplo de como hacerlo añadiendo un album, con un campo nombre.

Hay dos cosas a tener en cuenta, el envio del formulario es ajax, pero tambien el div donde cargaremos los resultados es ajax.

$content .= $this->Ajax->div('calendars');
foreach ($calendars as $calendar){
$content .=$interestDestination["InterestDestination"]["name"];
}
$content .=  $this->Ajax->divEnd('calendars');

$content .= $this->Ajax->form('/calendars', 'post', array('update' => 'calendars'));
$content .= $this->Form->input('name', array('label' => 'Agregar Nuevo Grupo:', 'error' => __('Nombre no valido', true)));
$content .= $this->Form->submit('Añadir',array('escape'=>false));
$content .= $this->Form->end();

return $content

Podemos ver que el update del form tiene el mismo nombre que le div Ajax, está observación es importante ya que el formulaior hace la llamada a este div, y esté div es el que se refrescará sin tener que refrescar toda la página.

En el controlador deberemos tener en cuenta, el añadir var $helpers = array(‘Ajax’);

Y también en la función en este caso “calendars” que ejecutamos desde nuestro formulario, deberemos hacer un render a la página donde se encuentra el mismo formulario.
Por ejemplo si nuestro formulario está en nuestro index $this->render(‘index’, ‘ajax’);

Helpers cakephp

 

cakePhp

Una de las cosas que utilizo en mis vistas en cakephp son los helpers.

¿Para que sirve?
Lo que hago yo es hacer un helper de una tématica ( ejemplo album de imagenes), asi lo tengo más organizado.

Mi controlador llama a mi vista, y la vista llama a una función el helper pasando las variables necesarias de la siguiente manera.


echo $imageHelper->viewImageComponent($image,$albums);

para que me funcione esta manera de hacerlo necesito tener creado mi helper en views/helpers/image_helper.php
y debemos también decir que vamos a usar este helper, esto lo hacemos en /app_controller.php
añadir lo siguiente, o modificarla.


class AppController extends Controller {
	var $helpers = array('Html', 'Form', 'ImageHelper');	
}

De esta manera si mi proyecto es grande, puedo estar modificando mis vistas desde un solo archivo, y tenelo más organizado.

Test Unitarios en Cakephp

 

cakePhp

Podreís ver que muchos de mis Posts son sobre cakephp, pero es sobre lo que estoy trabajando ahora mismo.

En este caso me gustaría Explicar como hacer un test unitario en un módelo y su importancia.
A mi me ayuda mucho. No se siempre, si mi modelo está bien hecho, también me ayuda a pensar en todas las funciones que necesito para ese modelo, en diferentes casos que puedo tener de respuesta, y no dar palos de ciego cuando algo no funciona.
Aunque al principio pueda parecer una perdida de tiempo hacer test unitarios, cuando la complegidad se mayor más los necesitaremos, y nos daremos cuenta de que nuestro rendimiento mejora.

Lo primero que deberemos hacer, es crear un fixture, vamos a poner un ejemplo simple, un modelo User con los campos id, name, email.

En el directorio tests/fixtures creamos el archivo user_fixtures.php
En este fichero siempre tendremos que tener la extructura de nuestra tabla, y datos con los que luego haremos nuestros tests.

ejemplo user_fixtures.php

class UserFixture extends CakeTestFixture {
	var $name = 'User';
	var $table = 'users';
	var $fields = array(
		'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 20, 'key' => 'primary'),
		'name' => array('type'=>'string', 'null' => false, 'default' => NULL, 'length' => 100),
		'email' => array('type'=>'string', 'null' => false, 'default' => NULL),
		'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
	);
	var $records = array(
		array(
		'id'  => 1,
		'name'  => 'usuario1',
		'email'  => 'usuario1@email.com'),
	var $records = array(
		array(
		'id'  => 2,
		'name'  => 'usuario2',
		'email'  => 'usuario2@email.com'),
	);
}

Una vez hecho el fixture, es momento de pensar en nuestros en un caso de test unitario, el primero que se me ocurre es buscar usuarios por su id.
Creamos en el directorio tests/models el archivo user.test.php, importante siempre en cake el nombre de los arhivos.
Ejemplo user.test.php

App::import('Model', 'user');

class UserTestCase extends CakeTestCase {
	var $user = null;
	var $fixtures = array('app.user');

	function startTest() {
		$this-=>User =& ClassRegistry::init('User');
	}
        function testuserInstance() {
		$this-=>assertTrue(is_a($this-=>User, 'User'));
	}
        function testfindUserId(){
	        // buscamos en el modelo user en la función findUserId la id 1.
		$friendid=$this-=>User-=>findUserId(1);
                // comparamos si el usuario el name de la busqueda, con usuario1, que debería ser true.
		$this-=>assertEqual($friendid['User']['name'],'usuario1');
	}
}

Ya tenemos Hecho un test unitario para el modelo User, ahora mismo esto nos dará Error, debemos crear la funcion findUserId() en el modelos user, aún así nos dará error, hay que hacer que esta función nuestro return sea el usuario 1 que es lo que estamos buscando.
Por cierto para poder hacer test en Cakephp debemos tener el debug del core.php a 2.

Componente cakePhp generador de Contraseña aleatorio.

 

cakePhp

Es un componente muy sencillo, pero útil para el típico “he olvidado mi contraseña” en un sistema de usuarios.

Implementación en cake

- en”controller/components” en tu proyecto de cakePhp, añadir un archivo “password.php”.

 class PasswordComponent extends Object {

/**
 * Password generator function
 *
 */
    function generatePassword ($length = 8)
    {
        // inicializa variables
        $password = "";
        $i = 0;
        $possible = "0123456789bcdfghjkmnpqrstvwxyz"; 

        // agrega random
        while ($i < $length) {

            $char = substr($possible, mt_rand(0, strlen($possible)-1), 1);

            if (!strstr($password, $char)) {
                $password .= $char;
                $i++;
            }
        }
        return $password;
    }
}

- En el controlador que vayamos a usar este componente deberemos añadir:
var $components = array(‘Password’);

- Llamaremos a la función:
$this->Password->generatePassword();

- Si guardamos la función en una variable $newpassword, tendremos la nueva password aleatoria.