HAProxy: proxy para mejorar el rendimiento

HAProxy es un proxy gratuito, con balanceo de carga y que soporta decenas de miles de peticiones. Además de tener un gran rendimiento, permite tener un control de concurrencia, esencial cuando tenemos demasiadas peticiones que nuestro sistema no puede soportar, y en vez de saturar el sistema y dar un mal servicio a todo el mundo, podemos limitar el número de peticiones para que al menos una parte de los usuarios sí reciban el servicio adecuado.

HAProxy

Vía / SaaS Interrupted

|

BigDump: facilita recuperar dumps de MySQL grandes

A veces es un lío enorme recuperar BDs obtenidos de dumps cuando el fichero es enorme, sobre todo si usamos phpMyAdmin (y no tenemos acceso a él). Por ello este script nos puede venir muy bien para recuperar backups anteriores, ya que recupera de poco en poco y se auto-reinicia él mismo.

BigDump

Plupload: sube varios ficheros fácilmente

Plupload es un script creado por los autores de TinyMCE. Permite subir ficheros usandoHTML5 Gears, Silverlight, Flash, Yahoo! BrowserPlus o formularios normales, además permite subida progresiva, redimensionado de imágenes y chunked uploads.

Está dividido en dos partes: Core API y una cola de subida jQuery, lo cual permite que creamos nuestra propia implementación. Además en Firefox 3.5+ se puede usar drag&drop y el redimensionado de images también es exclusivo de FF.

Plupload

Vía / WebAppers

Opiniones sobre HipHop de Facebook

He estado leyendo bastantes opiniones sobre HipHop de Facebook e iba a hacer un listado pero me he encontrado con el trabajo ya hecho en PHPDeveloper.org:

Community News: Responses to the Facebook HipHop Announcement

Mostrar las páginas vistas y las visitas de Google Analytics al estilo Feedburner

Me ha gustado el ejemplo para mostrar en tu web las visitas y las páginas vistas de tu web como muestra Feedburner los suscritores que tienes en el feed. Para mostrarlo haremos uso de la librería GAPI, la cual accede a los datos que ofrece Google Analytics:

<?php
define('ga_email','yourGoogleEmail');
define('ga_password','yourGooglePass');
define('ga_profile_id','yourProfileID');

require 'gapi.class.php';
$ga = new gapi(ga_email,ga_password);
$ga->requestReportData(ga_profile_id,array('browser','browserVersion'),array('pageviews'));
?>

El resto será darle estilo a los datos obtenidos.

FeedCount-Like Google Analytics Counter

Vía / Script & Style

|

Facebook crea HipHop para PHP

Después de muchos rumores ya se ha conocido que Facebook ha creado una aplicación que transforma PHP en código C++, no es un compilador en sí, sino una especie de traductor de código que compila. Los resultados en Facebook son asombrosos, hasta un 50% menos de CPU, lo cual reduce el número de servidores que necesitan.

HipHop for PHP

Tutorial sobre Facebook Connect

Facebook Connect es una API de FB que nos permite usar nuestra cuenta de FB en otras webs. A mi personalmente, la ayuda que ofrece FB no me apasiona demasiado, y cuando quieres realizar algo con Facebook Connect te tienes que pelear bastante con cosas que haces mal o que te faltan por hacer. Por ello, creo que este tutorial es bastante interesante para aquellos que quieren desarrollar algo con FB Connect y no saben por dónde empezar.

El tutorial nos mostrará los siguientes puntos:

  1. Crear una aplicación en Facebook
  2. Copiar en tu sitio el fichero xd_receiver.htm
  3. Descargar la API PHP de FB en tu web
  4. Modificar tu tabla de usuarios
  5. Crear una página para loguearse con FB Connect
  6. Enlazar a fbclogin.php desde tu login
  7. Otros puntos a seguir

Facebook Connect Tutorial

Vía / PHPDeveloper.org

|

Laboratorio: leer cualquier tipo de imágen en PHP de forma sencilla

Uno de los problemas con los que nos solemos encontrar es leer imágenes en PHP mediante la librería GD sin estar seguros de que tipo de fichero es: JPEG, GIF o PNG. Normalmente solemos mirar la extensión y según sea, abrir el fichero con alguno de los métodos que ofrece GD. Pero hay una solución más sencilla: leer el fichero en un string y crear la imagen usando ese script:

$img_content = file_get_contents($image);
$im = imagecreatefromstring($img_content);
// Para saber el tipo de imagen por si lo necesitamos
$imgtype = exif_imagetype($image);

Laboratorio: postear en WordPress mediante GTalk o Jabber (mejorado)

Hace tiempo hice un script para PHP que permitía postear en WordPress usando Jabber (por ejemplo GTalk). Ahora he mejorado un poco el script para que admita poner categorías (si no las hay, las crea) y subir imágenes mediante una URL (ajustándolo a un ancho máximo).

Existen distintas palabras claves para separar los distintos elementos del post dentro del texto que se envía: titulo, contenido, tags, categorias e image. Las distintas secciones se separan con ‘##’ para diferenciarlas unas de otras y se separarán por dos puntos ‘:’ formando pares clave:valor. Un ejemplo para escribir en el IM sería el siguiente:

titulo:Titulo del post##contenido:Lorem Ipsum... con todo el HTML que querramos##tags:etiqueta1, etiqueta2, etiqueta3##categorías:Categoria1,Categoria2#image:http://servidor.com/ruta/imagen.png

El código principal es el siguiente:

$e

";'), explode("\n", $contenido))); } if (isset($image)) { $img_content = file_get_contents($image); $im = imagecreatefromstring($img_content); $w = imagesx($im); $h = imagesy($im); $imgtype = exif_imagetype($image); if ($w > $max_width) { $image_p = imagecreatetruecolor($max_width, intval($h*$max_width/$w)); imagecopyresampled($image_p, $im, 0, 0, 0, 0, $max_width, intval($h*$max_width/$w), $w, $h); ob_start(); imagepng($image_p); $img_content = ob_get_contents(); ob_end_clean(); $imgtype = IMAGETYPE_PNG; $w = $max_width; $h = intval($h*$max_width/$w); } $imgname = "img".time().image_type_to_extension($imgtype); $f = new xmlrpcmsg('metaWeblog.newMediaObject', array(php_xmlrpc_encode($blog_usuario), php_xmlrpc_encode($blog_usuario), php_xmlrpc_encode($blog_contraseña), php_xmlrpc_encode(array('name'=>$imgname, 'bits'=>new xmlrpcval($img_content, 'base64')))) ); $c=new xmlrpc_client($blog_xmlrpc_path, $blog_url, $blog_puerto); $c->setDebug(0); $r=&$c->send($f); if(!$r->faultCode()) { $v=$r->value(); $datos = simplexml_load_string($v->serialize()); $url = $datos->xpath('//member/name[. ="url"]/following-sibling::*/string'); $contenido = ''.$contenido; } else { return "Error a la hora de subir la imagen: $image [".$r->faultString()."]"; } } //$contenido .= mb_convert_encoding($contenido, 'UTF-8'); $f = new xmlrpcmsg('wp.getUsersBlogs', array(php_xmlrpc_encode($blog_usuario), php_xmlrpc_encode($blog_contraseña)) ); $c=new xmlrpc_client($blog_xmlrpc_path, $blog_url, $blog_puerto); $c->setDebug(0); $r=&$c->send($f); if(!$r->faultCode()) { $v=$r->value(); $datos = simplexml_load_string($v->serialize()); $blogid = $datos->xpath('//member/name[. ="blogid"]/following-sibling::*/string'); $blogid = is_array($blogid) ? (string) $blogid[0] : (string) $blogid; $f = new xmlrpcmsg('metaWeblog.newPost', array(php_xmlrpc_encode($blogid), php_xmlrpc_encode($blog_usuario), php_xmlrpc_encode($blog_contraseña), php_xmlrpc_encode(array('title'=>$titulo, 'description'=>$contenido, 'mt_keywords'=>$tags)), php_xmlrpc_encode(1)) ); $c=new xmlrpc_client($blog_xmlrpc_path, $blog_url, $blog_puerto); $c->request_charset_encoding = 'UTF-8'; $c->setDebug(0); $r=&$c->send($f); if($r->faultCode()) { return "Ha habido un error al intentar crear un nuevo post [".$r->faultString()."]"; } else { $datos = simplexml_load_string($r->serialize()); $postid = $datos->xpath('//value/string'); $postid = is_array($postid) ? (string) $postid[0] : (string) $postid; $f = new xmlrpcmsg('metaWeblog.getPost', array(php_xmlrpc_encode($postid), php_xmlrpc_encode($blog_usuario), php_xmlrpc_encode($blog_contraseña)) ); $c=new xmlrpc_client($blog_xmlrpc_path, $blog_url, $blog_puerto); $c->setDebug(0); $r=&$c->send($f); if($r->faultCode()) { return "Ha habido un error al intentar recuperar información sobre el post insertado [".$r->faultString()."]"; } else { $datos = simplexml_load_string($r->serialize()); $permalink = $datos->xpath('//member/name[. ="permaLink"]/following-sibling::*/string'); $permalink = is_array($permalink) ? (string) $permalink[0] : (string) $permalink; $title = $datos->xpath('//member/name[. ="title"]/following-sibling::*/string'); $title = is_array($title) ? (string) $title[0] : (string) $title; if (isset($categorias)) { $f = new xmlrpcmsg('mt.getCategoryList', array(php_xmlrpc_encode($postid), php_xmlrpc_encode($blog_usuario), php_xmlrpc_encode($blog_contraseña)) ); $c=new xmlrpc_client($blog_xmlrpc_path, $blog_url, $blog_puerto); $c->setDebug(0); $r=&$c->send($f); if(!$r->faultCode()) { $datos = simplexml_load_string($r->serialize()); $catsblog = $datos->xpath('//struct'); foreach(explode(',', $categorias) as $cat) {$cats[$cat] = null;} foreach($catsblog as $cat) { foreach($cats as $_cat=>$val) { if (strtolower((string) $cat->member[1]->value->string) == strtolower($_cat)) { $cats[$_cat] = (string) $cat->member[0]->value->string; } } } foreach($cats as $cat=>$val) { if (!$val) { $f = new xmlrpcmsg('wp.newCategory', array(php_xmlrpc_encode($postid), php_xmlrpc_encode($blog_usuario), php_xmlrpc_encode($blog_contraseña), php_xmlrpc_encode(array('name'=>$cat, 'slug'=>str_replace(' ', '_', strtolower($cat)), 'parent_id'=>1, 'description'=>''))) ); $c=new xmlrpc_client($blog_xmlrpc_path, $blog_url, $blog_puerto); $c->setDebug(0); $r=&$c->send($f); if(!$r->faultCode()) { $datos = simplexml_load_string($r->serialize()); $catid = (string) $datos->xpath('//int'); $cats[$cat] = $catid; } else { return "Ha habido un error a la hora de crear la categoría $cat"; } } } foreach($cats as $val) { $catlist[] = array('categoryId'=>$val); } $f = new xmlrpcmsg('mt.setPostCategories', array(php_xmlrpc_encode($postid), php_xmlrpc_encode($blog_usuario), php_xmlrpc_encode($blog_contraseña), php_xmlrpc_encode($catlist)) ); $c=new xmlrpc_client($blog_xmlrpc_path, $blog_url, $blog_puerto); $c->setDebug(0); $r=&$c->send($f); if($r->faultCode()) { return "Hubo un error a la hora de modificar las categorías del post"; } } else { return "Ha habido un error al intentar recuperar las categorias del blog"; } } return "Se ha publicado '$title': $permalink"; } } } else { return "Ha habido un error al intentar recuperar información sobre el blog [".$r->faultString()."]"; } } //Use XMPPHP_Log::LEVEL_VERBOSE to get more logging for error reports //If this doesn't work, are you running 64-bit PHP with < 5.2.6? $conn = new XMPPHP_XMPPOld($jabber_host, $jabber_puerto, $jabber_usuario, $jabber_contraseña, 'xmpphp', $jabber_host, false, XMPPHP_Log::LEVEL_ERROR); $conn->autoSubscribe(); $conn->useEncryption(false); try { $conn->connect(); while(!$conn->isDisconnected()) { $payloads = $conn->processUntil(array('message', 'presence', 'end_stream', 'session_start')); foreach($payloads as $event) { $pl = $event[1]; switch($event[0]) { case 'message': if (trim($pl['body']) == '') break; $conn->message($pl['from'], $body=post($pl['body']), $type=$pl['type']); if($pl['body'] == 'quit') $conn->disconnect(); if($pl['body'] == 'break') $conn->send(""); break; case 'presence': // print "Presence: {$pl['from']} [{$pl['show']}] {$pl['status']}\n"; break; case 'session_start': //print "Empezamos\n"; $conn->getRoster(); $conn->presence($status="Asonesss jefeeeeeee!"); break; } } } } catch(XMPPHP_Exception $e) { echo 'ERROR:'; die($e->getMessage()); }

Podéis bajaros el código aquí.