Flash Player 9 y algunos detalles mas.
Como algunos sabrán el Flash player 8.5 que se encuentra en estado beta, ahora se llamara Flash player 9. Con esto Adobe se evitara conflictos ya que la próxima versión de Flash (Blaze) estará basada en el mismo player.
Además este player tiene muchos cambios que lo diferencian bastante con sus antecesores y por eso es mejor diferenciarlo bien de sus predecesor (8) y darle un numero unico (9). Aquí algunos detalles:
Primero quería mencionar que ahora el player tiene dos virtual machines. Una sirve para correr todas las versiones anteriores, desde la version 1 a la version 8. La otra sirve para correr las versiones 9 en adelante. Esto fue implementado así por que ahora la nueva versión de ActioScript tiene un nuevo bytecode que se diferencia bastante de las anteriores.
También se le agrego un verificador de bytecode que analiza los bytes a medida van bajando y verifica que el bytecode no tenga errores y que sea legitimo. Esto ayuda a resolver los problemas con anticipación.
Esta nueva virtual machine también posee un nuevo garbage collector (recolector de basura) mucho mas inteligente que va limpiando la memoria que no se usa mas en nuestra aplicación.
También existe el JIT (just un time compilation) que lo que hace es transformar las instrucciones que están el en bytecode del archivo swf a código nativo de la maquina. Permitiendo que el código se ejecute mucho mas rápido ya que es nativo en el procesador, el proceso es similar a lo que hace java con su virtual machine.
Otra cosa interesante del nuevo player es que hay una versión para los desarrolladores que es el debug player y que permite ver los errores en la aplicación a medida que van pasando, en tiempo real (runtime exceptions). Esto es increíble ya que facilita mucho la programación.
Por el lado de las librerías de código, ahora tenemos dos librerías muy importantes incomparadas directamente en el player.
Una es el Focus manager. Y la otra es el motor de Eventos (EventDispatcher) que también ahora es parte del player. Gracias a esto todos los objetos que se muestran en la pantalla (ósea que están el la diplayList) poseen los métodos necesarios para trabajar con los eventos debido a que heredan de la clase EventDispatcher.
Bueno para terminar les digo que todo estos beneficios los tenemos si hacemos código en ActionScript 3.0. También prometo que el próximo post no va ser tan freak :)
setCredentials con Base de Datos
Autentificación de usuarios con FlashRemoting y setCredentials
Uso de herencia en AMFPHP en conexiones a bases de datos
Ya con esta información en nuestra mente, procedamos. En primer lugar, veamos nuestra clase Config.php la cual nos ayuda a tener mejor organizadas nuestras conexiones a MySQL :
class Config {
//-------------------------
//Configuraciones MySQL
var $dbhost = "localhost";
var $dbname = "noticias";
var $dbuser = "root";
var $dbpass = "";
//-------------------------
function Config ($db) {
if(basename($_SERVER['PHP_SELF']) == "Config.php") exit; //Esta línea es para evitar que accedan al archivo de manera pública.
$this->conn = $this->connect($db);
}
function connect ($db) {
if(!$conn = @mysql_pconnect($this->dbhost, $this->dbuser, $this->dbpass)) {
return false;
}
if (!@mysql_select_db ($db, $conn)) {
return false;
}
return $conn;
}
function log ($log) {
$file = implode("", file("log.txt"));
$open = fopen ("log.txt", "w+");
$file .= date ("\l\o\g :::: d/m/Y h:m:s ----> ", time()).$log."\n";
fwrite ($open, $file);
fclose ($open);
}
function _authenticate ($user, $pass) {
$user = addslashes($user); //escapamos las comillas para evitar un MySQL inyection...es por seguridad.
$pass = addslashes($pass);
$query = "SELECT `roles` FROM `users` WHERE `user` LIKE '".$user."' AND `password` LIKE '".$pass."';";
$result = mysql_query ($query, $this->conn);
if ($data = mysql_fetch_assoc($result)) {
return $data['roles'];
} else {
return false;
}
}
}
Todo lo anterior, ya está explicado en uno de los links (a excepción del nuevo _authentificate que hemos creado), así que no es necesario repetir . Por otro lado, veamos nuestro servicio seguro :
include_once("Config.php");
class News extends Config {
function News {
parent::__construct($this->dbname);//Esta linea llama al constructor de la clase.
$this->methodTable = array (
"getNews" => array (
"description" => "Devuelve el listado de noticias",
"access" => "remote",
"roles" => "admin",
"arguments" => array ()
)
);
}
function getNews () {
return "AsFusion es un blog mas en la blogosfera que intenta sobrevivir en este mundo cruel";
}
}
Como verán, está mi clase News la cual hereda los métodos y propiedades de mi clase Config. Entre lo heredado, está obviamente mi método _authenticate el cual me validará a mi usuario en una supuesta tabla como esta :
| user | password | roles |
| daniel | asfusion | admin |
| nahuel | coldfusion | admin |
Básicamente mi método _authenticate me validará el usuario haciendo una consulta a la base de datos, y devolverá el rol de nuestro usuario seleccionado. Si este rol concuerda con lo especificado dentro de nuestro methodTable, se validará correctamente el usuario. No es díficil esto de combinar setCredentials con MySQL....solo se trata de aplicar un poco de lógica si es que antes hemos combinado FlashRemoting con Base de Datos. Este seria el código de Actionscript :
import mx.remoting.Service;
import mx.services.Log;
import mx.rpc.RelayResponder;
import mx.rpc.FaultEvent;
import mx.rpc.ResultEvent;
import mx.remoting.PendingCall;
var sSecured:Service = new Service ("http://localhost/gateway.php", null,"News",null,null);
sSecured.connection.setCredentials ("daniel", "asfusion");
function welcomeResult (rs:ResultEvent) {
trace (rs.result);
}
function welcomeFault (fl:FaultEvent) {
trace("Su usuario no esta validado");
trace("Hubo un problema: "+fl.fault.faultstring);
trace("El código del error es: "+fl.fault.faultcode);
trace("Detalles: "+fl.fault.detail);
}
var pcWelcome:PendingCall = sSecured.welcome ();
pcWelcome.responder = new RelayResponder (this, "welcomeResult", "welcomeFault");
Algo a destacar, es que también si queremos agregarle un poco más de seguridad a nuestra aplicación, podemos encriptar el password en la base de datos usando md5. Entonces nuestra validacioón quedaría así :
function _authenticate ($user, $pass) {
$user = addslashes($user); //escapamos las comillas para evitar un MySQL inyection...es por seguridad.
$pass = md5($pass); //Encriptamos el password previamente.
$query = "SELECT `roles` FROM `users` WHERE `user` LIKE '".$user."' AND `password` LIKE '".$pass."';";
$result = mysql_query ($query, $this->conn);
if ($data = mysql_fetch_assoc($result)) {
return $data['roles'];
} else {
return false;
}
}
Espero haber aclarado un poco más este tema, y que esto sea de gran ayuda a cualquiera que desee enfocarse plenamente a FlashRemoting.
Saludos¡
Un error en el articulo anterior con el método log() de la clase Config.
function log ($log) {
$file = implode("", file("log.txt"));
$open = fopen ("log.txt", "w+");
$file .= date ("\l\o\g :::: d/m/Y h:i:s ----> ", time()).$log."\n";
fwrite ($open, $file);
fclose ($open);
}
Saludos!
Uso de herencia en AMFPHP en conexiones a bases de datos.
Básicamente este es el codigo que suelo usar para mi clase Config que esta dentro de un archivo llamado Config.php.
<?PHP
class Config {
//-------------------------
//Configuraciones MySQL
var $dbhost = "localhost";
var $dbname = "facturacion";
var $dbuser = "root";
var $dbpass = "";
//-------------------------
function Config ($db) {
if(basename($_SERVER['PHP_SELF']) == "Config.php") exit; //Esta línea es para evitar que accedan al archivo de manera pública.
$this->conn = $this->connect($db);
}
function connect ($db) {
if(!$conn = @mysql_pconnect($this->dbhost, $this->dbuser, $this->dbpass)) {
return false;
}
if (!@mysql_select_db ($db, $conn)) {
return false;
}
return $conn;
}
function log ($log) {
$file = readfile("log.txt");
$open = fopen ("log.txt", "w+");
$file .= date ("\l\o\g :::: d/m/Y h:m:s ----> ", time()).$log."\n";
fwrite ($open, $file);
fclose ($open);
}
}
?>
Si se leen detenidamente el código, creo unas propiedades al inicio de Config donde estan mis configuraciones de la base de datos. Dentro de la función constructora hago la conexión ademas de agregar una pequeña línea de seguridad. Ahí mismo verán que requiero como argumento el nombre de la base de datos y guardo el id de la conexión, aún a pesar de que la defino previamente como propiedad. Esto es porque en ocasiones en un projecto grande hacemos conexiones a mas de una base de datos. Esto me da la posibilidad de que en un servicio diferente sobreescriba la propiedad $dbname y todo siga funcionando correctamente. Mas adelante ustedes verán la función de connect (no tiene mucha ciencia si ya saben combinar PHP con MySQL) y otra llamada log la cual me ha llegado a resultar ser muy útil a la hora del debugeo del lado de AMFPHP. Muchos sabrán que cuando usamos remoting tenemos al NetConection Debugger para depurar la aplicación del lado de Flash....pero no tenemos nada del lado del servidor, por eso creo esa función que me permite llevar un cierto registro. Ahora en nuestro servicio hijo hacemos lo siguiente :
<?PHP
include_once ("Config.php");
class Billing extends Config {
function Billing () {
parent::__construct($this->dbname);//Esta linea llama al constructor de la clase.
$this->methodTable = array (
"getClients" => array (
"description" => "Get the client list from db.",
"access" => "remote",
"arguments" => array ()
)
);
}
//Metodos
/*-----------------------------------*/
function getClients () {
$query = "SELECT `client` AS label, `id` AS data, `address`, `rfc` FROM `clients` ORDER BY `client`;";
$this->log($query);//Uso el método heredado log para hacer debugeos
return mysql_query($query, $this->conn);
}
}
?>
Lo primero que hacemos primero es incluir el archivo Config.php y después establecemos la herencia con la palabra reservada extends. Además, si ven dentro de la función constructora de Billing hay una línea como esta :
parent::__construct($this->dbname);
Esta línea lo que hace es llamar a la funcion constructora de la superclase donde establecemos la conexion de la base de datos creandonos automáticamente la propiedad $conn que es muy importante para que si en un mismo servicio usamos dos bases de datos, podamos crear una conexion temporal en algún método (por eso dejo que la función connect heredable dentro de Config). También verán que dentro de getClients uso el método log que definí en la superclase Config. No es necesario usar ese método ahí, pero sirve para ilustrar el uso que se le puede dar.
En fin, este es todo el tutorial...la idea es proveer una solución mas elegante a las conexiones de bases de datos en remoting...por ahí he visto otras maneras usando constantes definidas en un archivo config.php pero nunca he han gustados. Espero que les sirva a algunos. Saludos!
Cristalab Online 2
El Sábado, 26 de Noviembre será la próxima conferencia de Cristalab (gratis y para todo el mundo). La cual incluirá varios temas interesantes como:
- Chats con soporte de webcam sin servidores, en Flash 8
- Creación de componentes en Flash 8
- Proyectos corporativos de alto nivel con herramientas Open Source en Flash
- Creando sitios web con CSS, XHTML y aproximación a paginas semánticas
- Instalación y primera aplicación en Flash creada en un entorno 100% libre, FAMES
- Bases de datos en Flash 8 con Flash Remoting 2
- Presentación de nuevos proyectos de Cristalab. Y Esto es Cristalab
- Aplicaciones para Internet con Flex Builder 2 y Actionscript 3
Gracias a Freddie y a toda la gente del Clab por organizar este tipo de eventos, y gracias ademas por invitarme ;). Ahí estaré presentando la conferencia de Flex y ActionScript 3
Para mas info visiten Cristalab Online 2, y espero verlos por ahí