viernes, 30 de septiembre de 2011

Asignando variables de sesión PHP desde jQuery (con KumbiaPHP)

En esta entrada muestro un pequeño ejemplo en el que asignamos una variable de sesión PHP "dentro" de una función Javascript. ¿Para qué queremos esto? Pues para lo mismo que normalmente queremos asignar una variable de sesión, sólo que si estamos, por ejemplo, manejando un evento con jQuery, no estamos en PHP, estamos en Javascript, así que no vale un $_SESSION['clave'] = valor.

La solución que planteo aquí es la de enviar un POST via Ajax que se encargue de hacer la asignación. Simple. Voy a hacer uso de KumbiaPHP, con el cual ya he mostrado códigos anteriormente, pero en definitiva, el procedimiento es realmente simple e independiente del framework que utilicemos (si utilizamos alguno).

En este ejemplo, tengo una tabla con algunos datos sobre unas hipotéticas transacciones que presento al usuario, incluyendo un enlace a otra página. Será una tabla con 3 columnas: 1) tipo de transacción 2) monto de transacción y 3) enlace. Muestro el código HTML de la vista, llamada test1.phtml:

<table border="0" width="100%" class="grid-table" id="transacciones-table">
<thead>
  <tr>
    <th class="table-header-repeat line-left minwidth-1">Transacción</th>
    <th class="table-header-repeat line-left minwidth-1">Monto</th>
    <th class="table-header-repeat line-left minwidth-1">Detalle</th>
  </tr>
</thead>
<tbody>
  <tr class="row-1">
    <td class="descripcion">Apertura</td>
    <td class="monto">850.00</td>
    <td><a href="test2" class="print_link" id="671">imprimir</a></td>
  </tr>
  <tr class="row-2">
    <td class="descripcion">Intereses</td>
    <td class="monto">150.00</td>
    <td><a href="test2" class="print_link" id="686">imprimir</a></td>
  </tr>
  <tr class="row-1">
    <td class="descripcion">Intereses</td>
    <td class="monto">150.00</td>
    <td><a href="test2" class="print_link" id="778">imprimir</a></td>
  </tr>
  <tr class="row-2">
    <td class="descripcion">Cancelación</td>
    <td class="monto">850.00</td>
    <td><a href="test2" class="print_link" id="990">imprimir</a></td>
  </tr>
</tbody>
</table>

Como vemos una simple tabla con datos. Obsérvese que el anchor tiene un id y que el resto de las columnas tienen una clase representativa del dato que contienen. Queremos que cuando el usuario presione el enlace, el navegador se vaya a la vista test2.phtml para, por ejemplo, imprimir una planilla en pdf. En este caso, podríamos enviarle el valor del id de la fila que queremos imprimir y hacer una nueva consulta a la base de datos para pedir el resto de los datos, o podemos enviar un GET a test2 con los datos, para no tener que consultar, o alguna otra cosa. Pero como queremos es utilizar variables de sesión, pues eso haremos: con jQuery, crearemos una función para manejar el evento click de los enlaces, de manera tal de que justo antes de ir a test2, asignemos las variables de sesión y podamos luego utilizarlas sin problema. Es sólo cuestión de agregar la función a la vista test1.phtml, que quedaría de la siguiente forma:

<script type="text/javascript">
  $(function() {
    $('.print_link').click(function() {
		var fixedurl = 'http://localhost/miapp/main/set_session_var';
		$.post( fixedurl,
		{ object_name: 'tmprow',
          id: $(this).attr('id'),
          monto: $(this).parent().parent().find('.monto').html()
		 },
			function(data){
			//donothing
		});

      return true;
    });
  });
</script>

<table border="0" width="100%" class="grid-table" id="transacciones-table">
<thead>
  <tr>
    <th class="table-header-repeat line-left minwidth-1">Transacción</th>
    <th class="table-header-repeat line-left minwidth-1">Monto</th>
    <th class="table-header-repeat line-left minwidth-1">Detalle</th>
  </tr>
</thead>
<tbody>
  <tr class="row-1">
    <td class="descripcion">Apertura</td>
    <td class="monto">850.00</td>
    <td><a href="test2" class="print_link" id="671">imprimir</a></td>
  </tr>
  <tr class="row-2">
    <td class="descripcion">Intereses</td>
    <td class="monto">150.00</td>
    <td><a href="test2" class="print_link" id="686">imprimir</a></td>
  </tr>
  <tr class="row-1">
    <td class="descripcion">Intereses</td>
    <td class="monto">150.00</td>
    <td><a href="test2" class="print_link" id="778">imprimir</a></td>
  </tr>
  <tr class="row-2">
    <td class="descripcion">Cancelación</td>
    <td class="monto">850.00</td>
    <td><a href="test2" class="print_link" id="990">imprimir</a></td>
  </tr>
</tbody>
</table>

Muy simple y autoexplicativo (sobre todo para el que sabe jQuery). Simplemente declaramos un handler para el evento click de los objetos de clase "print_link", que envíe un POST via Ajax a la url especificada, con 3 datos: id (el id de la columna), monto (el monto de la transacción que sería el dato de la segunda columna) y object_name (con el nombre que le queremos asignar a la variable de sesión, 'tmprow' en este caso). Lo que queda es ver el controlador:

<?php

class MainController extends AppController
{

public function index()
{
	View::template('admin');
}

public function set_session_var()
	{
		View::template(null);
		$tmpname = '_object';
		foreach($_POST as $clave => $valor)
		{
			if($clave == 'object_name')
			{
				$tmpname = $valor;
				unset($_POST[$clave]);
			}
		}
		$_SESSION[$tmpname] = $_POST;
	}

	public function test1()
	{
		View::template('admin');
	}
	
	public function test2()
	{
		View::template('admin');
	}
}
?>

Y eso es todo, lo que acabamos de hacer es PHP básico, que no hace falta comentar. Ya podemos utilizar en test2 las variables de sesión que asignamos. Por ejemplo:

<p>En esta vista se puede hacer cualquier cosa con la información
que se guardó en sesión en test1.</p>

<p>El id de la transacción es: <?php echo $_SESSION['tmprow']['id'] ?></p>
<p>El monto de la transacción es: <?php echo $_SESSION['tmprow']['monto'] ?></p>

<p>Recuerda que siempre debes limpiar las variables de sesión cuando
ya no las utilices.</p>
<?php unset($_SESSION['tmprow']); ?>

Nótese que la función set_session_var() es reutilizada. Es decir, desde cualquier controlador, podemos enviarle un POST Ajax, con algunos datos y ella asignará nuestras variables de sesión. Se trata de un código sencillo pero que puede resultar muy útil.

Actualización
En esta entrada he mejorado el código, cambiando el $.post() por un $.ajax() para que la enviada sea síncrona, y así garantizar que en test2, ya tengamos nuestras variables con seguridad.