cakePHP: Aplicaciones 'bipolares' usando "beforeRender()"

viernes, 2 de marzo de 2007

Hoy me siento orgulloso de mi mismo, por fin tengo algo que escribir aquí.

Llevo unos días trabajando con PHP para un proyecto de la facultad, y después de trabajar con .net para aplicaciones web volver a un lenguaje de script se me antojaba un poco difícil. Al menos con he encontrado un framework sencillo de utilizar y aunque le faltan muchas características por implementar hay que tener en cuenta que esta todavía en desarrollo. Acaban de sacar la versión 1.2alfa. Este framework es cakePHP, mas info aquí, aquí y aquí.

Buscando información para documentarme he encontrado este blog coderbattery con algunos posts interesantes. No me considero un entendido en cakePHP, mas bien un aprendiz, pero me aventuro a mejorar una de las soluciones que proponen para ‘aplicaciones web bipolares’. El problema esta muy bien explicado en post y por lo tanto os remito a el [Aplicaciones “bipolares” con CakePHP].

La solución propuesta pasa por modificar appController. Incluyendo el siguiente código que modifica el layout por defecto dependiendo del dominio desde el que estamos accediendo:


class AppController extends Controller {
/* Constructor que determina el dominio
y en base a eso usa el layout correspondiente */
function __construct() {
parent::__construct();

// Determinar layout por defecto
if(ereg('dominio1',$_SERVER['SERVER_NAME'])) {
// Estamos en el primer dominio
$this->layout = 'dominio1_layout';
} else {
// Estamos en el segundo dominio
$this->layout = 'dominio2_layout';
}
}
...
}

Pero se presenta el problema que en aquellos controladores que no utilicen el layout por defecto hemos de incluir el siguiente código:

class LoginController extends AppController {
// Constructor para evitar el layout default
function __construct() {
parent::__construct();

if(ereg('dominio1',$_SERVER['SERVER_NAME'])) {
$this->layout = 'dominio1_login';
} else {
$this->layout = 'dominio2_login';
}
}
...
}


Esto provoca la repetición de código complicando las cosas si decidimos cambiar de dominio o incluir alguno mas pues nos veremos obligados a modificar bastantes ficheros si nuestra aplicación es compleja. Buscando un poco he encontrado la función beforeRender() de la clase Controller que se ejecuta justo antes de aplicar la el layout. Por lo tanto mi propuesta es incluir el siguiente código en el AppController:


class AppController extends Controller {
/* Determina el dominio y en base a eso usa el layout correspondiente */
function beforeRender(){
// Determinar layout por defecto
if(ereg('localhost',$_SERVER['SERVER_NAME'])) {
// Estamos en el primer dominio
$this->layout = 'dominio1_'.$this->layout;
} else {
// Estamos en el segundo dominio
$this->layout = 'dominio2_'.$this->layout;
}
}
...
}


Con esto nos ahorramos tener que incluir el código en cada controlador que no utilice el layout por defecto. Por supuesto también tiene inconvenientes y es que tendremos que crear, al menos en mi caso, los layout ‘dominio1_ajax.thtml’ y ‘dominio2_ajax.thtml’ y es probable que también alguno mas.

3 comentarios:

Unknown dijo...

Hola guadonpost,

Interesante aproximación la tuya, pero no sé si será porque dormí poco o que, pero no veo que tu propuesta de solución ahorre el problema de modificar cada controlador que no use el layout por defecto. Por qué? porque de todas formas lo que hace tu solución es establecer el layout por defecto para ambos dominios, tal como lo hace mi constructor, pero de paso anula la capacidad de LoginController de utilizar un layout distinto al default pues beforeRender se ejecuta después del constructor, lo que implica que lo estará obligando a usar el layout establecido en beforeRender de AppController. Por lo tanto, para mostrar un layout distinto al default en LoginController, de todas formas tendrías que crear un método beforeRender dentro de LoginController, y dentro de cualquier otro controlador que no use el layout por defecto, indicando que layout utilizar dependiendo del dominio.

Tal vez te faltó un paso?

Gracias por tu comentario! :)

Guadonpost dijo...

Hola Ramon:

No falta ningún paso, el truco esta en la línea $this -> layout = 'dominio1_'.$this -> layout;

Al ejecutarse la función, no sustituye el layout por defecto, sino que antepone el prefijo ‘dominio1_’ (o ‘dominio2_’ según el caso) al layout que hallamos definido.

Por lo tanto los layout resultantes serian:
‘dominio1_default’ -> si no modificamos el layout,
‘dominio1_login’ -> si en el controlador cambiamos el layout por ‘login’

‘dominio1_loQueMeDeLaGana’ -> si en el controlador tenemos la línea $this->layout = ‘loQueMeDeLaGana’

‘dominio1_ajax’ -> si llamamos al método mediante ajax

Cuidado con este ultimo pues tendremos que crear el archivo ‘dominio1_ajax.thtml’ con y solo con: "echo $ content_for_layout"

Espero que quede claro, y gracias por tu contestación/comentario ;)

Unknown dijo...

Ahora si lo capté!!! Que solución más elegante!

Ademas la instrucción para dominio1_ajax.thtml es muy importante. Es bueno destacarlo.

Gracias por tu aporte guadonpost :)