oriolrius.cat

Des del 2000 compartiendo sobre…

Tag: programming

Generant RSS de les revisions de Subversion

Reading time: 2 – 2 minutes

rss.jpg

Quan treballes en un projecte on hi ha més d’una persona treballant contra un repositori de codi és molt bona idea poder-se sindicar via RSS a les noves revisions que es van publicant del codi i als comentaris associats a aquestes revisions. De fet, aconseguir això amb subversion no és gens difícil. Jo fins ara ho he fet amb el WebSVN (port del ViewCVS. A més gràcies al trac també podem obtenir aquests RSS i moltes més funcionalitats. Però tot això ja us ho he explicat. En alguns casos però ens pot interessar publicar aquests RSS sense haver de tenir programes orientats a altres funcionalitats sinó únicament aprofitar les extencions WebDAV/DAV_SVN per publicar els RSS. Això és el que ens expliquen a l’article HOWTO: Adding an RSS feed to a Subversion Server (local).

De fet, el que planteja aquest article és força senzill. Simplement usa un generador d’RSS a partir de les revisions de l’SVN, l’script esta fet en python i després li diem al subversion que després de cada commit que es fassi al repositori es genir un nou fitxer RSS. Així doncs el tema no té cap misteri però va bé tenir-ho en un howto per si mai fa falta.

Phalanger: the PHP Language Compiler for .NET Framework

Reading time: 2 – 2 minutes

dotNet.jpg

Ja coneixia aquesta solució però mai recordava el nom que tenia, de fet, encara no l’he pogut provar mai però pel que he vist a la web en principi qualsevol dels nostres codis fets en PHP hauria de poder-se compilar en bytecode perquè pogués correr en un servidor web ASP.NET.

Penseu el senzill que serà doncs, usar codi des de .NET que haguem fet amb PHP o alrevés, si ja disposem de classes implementades en C# O VB.NET les podrem usar tranquilament des de PHP.

Llàstima que no m’hagi posat mai ni en .NET ni mono ni res de res. A més dubto que ho fassi perquè no és la meva feina, però per alguns codis que tinc fets a la feina en PHP em seria una gran avantatge poder-los fer corre directament sobre infraestructures complemtament windows, així no hauria de portar els codis de PHP a llenguatges més complexos per tal de fer-los corre en servidors 2000 o 2003 amb ISS i .NET.

Per ampliar més informació us recomano la web de Phalanger és força completa i té molta documentació si algú proba mai el compilador que m’avisi ja que hi estic molt interessant però em suposaria molta feina provar-lo amb la infraestructura que tinc montada ara mateix. A més no tinc ni idea de .NET.

symfony: protegint els entorns de desenvolupament, integració i producció

Reading time: 7 – 12 minutes

A l’article symfony: entorns de desenvolupament, integració i producció es pot entendre el perquè de treballar amb aquests tres espais de noms (environment) així doncs el que es preten explicar és:

  • Impedir accés a les aplicacions en entorns de ‘dev’ i ‘int’ des de llocs no controlats. O sigui, que una IP d’internet no pugui executar myapp_dev.php o myapp_int.php però encanvi una IP de la xarxa del desenvolupador si que pugui.
  • Impedir accés a aplicacions de backend des de l’entorn de producció. Si hem desenvolupat alguna aplicació per tal de fer el manteniment de l’aplicació principal, una part d’administració o backend aquesta no sigui accessible des d’IPs no controlades.
  • Separar el fitxer de configuració config/cofnig.php per cada un dels entorns. Així podem definir constants o d’altres tasques de forma particular per cada un dels entorns.

Per tal d’aconseguir aquests objectius he creat el fitxer config/config.lib.php:

<?php
/**
 * Comproba si la IP amb la que s'accedeix a l'aplicació permet connectar en aquest environment
 *
 * @param string $env nom de l'environment
 * @param array $ips ips des de les que podem accedir a l'environment
 * @param string $clientip ip del client que vol accedir al recurs
 */
function envCorrecte ($env,$ips,$clientip)
	{
	if (SF_ENVIRONMENT==$env)
	{
		$acces=0;
			foreach($ips as $ip)
		{
			$ipclient=substr($clientip,0,strlen($ip));
				if ($ipclient==$ip)
			{
				$acces=1;
				}
		}
		if ($acces==0)
			{
			echo "You are not in '".$env."' environment! (".$ipclient."<>".$ip.")";
				exit;
		}
	}
}
/**
 * Comproba si l'aplicació amb la que s'accedeix al projecte és publica o no
 *
 * @param array $apps llista d'aplicacions no públiques
 * @param array $ips llista d'IP amb les que es pot accedir a les apps no públiques
 * @param string $clientip ip del client que vol accedir al recurs
 */
function appCorrecte ($apps,$ips,$clientip)
	{
	// solucionem problema de la clau '0'
    	$apps_aux[0]='';
		$apps = $apps_aux + $apps;
	//
	if (array_search(SF_APP,$apps)!=false)
		{
		$acces=0;
		foreach($ips as $ip)
			{
			$ADR=$HTTP_SERVER_VARS['REMOTE_ADDR'];
			$ipclient=substr($clientip,0,strlen($ip));
				if ($ipclient==$ip)
			{
				$acces=1;
				}
		}
		if ($acces==0)
		{
				echo "Keep away! ".SF_APP." is not a public application!";
			exit;
		}
		}
}
?>

Llavors des del fitxer config/config.php cal que cridem aquesta petita llibreria de funcions que he creat. La resta és més que lògica, aquí en teniu un exemple:

<?php
include("config.lib.php");
/**
 * Controlem accés als 'environments' de 'env' i 'int'
 */
$ip_dev=array("10.138.0.","192.168.");
$ip_int=array("10.138.0.","192.168.");
envCorrecte('env',$ip_env,$HTTP_SERVER_VARS['REMOTE_ADDR']);
envCorrecte('int',$ip_int,$HTTP_SERVER_VARS['REMOTE_ADDR']);
/**
 * Controlem accés a les 'apps' d'ús privat
 */
$ip_apps=array("10.138.0.","192.168.","w.x.y.z");
$apps=array('myapp_1','myapp_2','myapp_n');
appCorrecte($apps,$ip_apps,$HTTP_SERVER_VARS['REMOTE_ADDR']);
/**
 * Carreguem el fitxer de configuració propi de l'"environment".
 */
include("config.".SF_ENVIRONMENT.".php");
/**
 * Part comú en els 3 entorns
 */
?>

Com podeu veure el codi és molt senzill i la potència i el dinamisme, excepcionals.

Aquest codi també l’he publicat com un snippet a Access control to environment and applications and custom global config file for an environment.

symfony: entorns de desenvolupament, integració i producció

Reading time: 3 – 4 minutes

Al desenvolupar un projecte de software m’agrada treballar en 3 entorns. Mentre s’esta desenvolupant el projecte esta bé tenir un espai de variables (o entorn de noms) a l’aplicació que correspongui als ajustaments del servidor de desenvolupament (normalment una màquina pròpia), per exemple, els path, urls, dades de la bbdd, etc. tot això ha d’estar el màxim separat possible del codi per tal de poder crear les configuracions pels entorns d’integració i producció.

L’entorn d’integració és una màquina en l’entorn de desenvolupament del client, amb les característiques el més semblants possibles a l’entorn de producció. O sigui, les dades de configuració de l’espai de noms han d’apuntar a serveis si pot ser de la mateixa versió que l’entorn de producció. Així podem provar l’aplicació i millores de l’aplicació abans de passar-la a producció. Finalment hem de tenir l’entorn de noms per producció amb les dades de treball.

Per tal de suportar tot això symfony suporta en moltíssims fitxers de configuració la possibilitat de definir l’environment, en el cas que plantejo, ‘dev’, ‘int’ i ‘prod’. En el front controller de cada aplicació podem definir aquest entorn de noms així després s’accedirà a la part dels fitxers de configuració que pertoca.

Per exemple, si mirem el fixer config/databases.yml on symfony defineix els sistemes de BBDD que usa la nostre aplicació en cada un dels environments podriem tenir algo així:

dev:
  nombbdd:
    class:           sfPropelDatabase
    param:
      phptype:       mysql
      hostspec:      localhost
      database:      nombbdd
      username:      userbbdd
      password:      passbbdd
int:
  nombbdd:
    class:          sfPropelDatabase
    param:
      phptype:      oracle
      username:     nombbdd
      password:     nombbdd
      hostspec:     hostint
      database:     NULL
prod:
  nombbdd:
    class:          sfPropelDatabase
    param:
      phptype:      oracle
      username:     nombbdd
      password:     nombbdd
      hostspec:     hostprod
      database:     NULL

Al cridar el front controller és quan symfony diu amb quin environment treballarem, per exemple, per una aplicació anomenada myapp podriem tenir aquests tres front controllers un per cada entorn:

Entorn de desenvolupament web/myapp_dev.php:

<?php
define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'myapp');
define('SF_ENVIRONMENT', 'dev');
define('SF_DEBUG',       true);
#
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
#
sfContext::getInstance()->getController()->dispatch();
?>

Entorn de integració web/myapp_int.php:

<?php
define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'myapp');
define('SF_ENVIRONMENT', 'int');
define('SF_DEBUG',       true);
#
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
#
sfContext::getInstance()->getController()->dispatch();
?>

Entorn de producció web/myapp.php:

<?php
define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'myapp');
define('SF_ENVIRONMENT', 'prod');
define('SF_DEBUG',       false);
#
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
#
sfContext::getInstance()->getController()->dispatch();
?>

Com es pot veure, tan desenvolupament com integració ens mostraran informació de debug i producció amagarà els missatges d’error i reportarà sempre l’error “internal server error”. A més podem veure que tots tres entorns criden el mateix fitxer de configuració global config/config.php.

Si voleu més informació sobre aquest tema us recomano els següents enllaços de la documentació de symfony:

symfony: interficies amb tabs de forma molt senzilla

Reading time: 1 – 2 minutes

L’últim snippet que han pujat al repositori de symfony és un somni fet realitat. Sempre m’ha fet molta ràbia haver de montar-me un sistema de tabbing per una interficie web (UI web) i el que ens proposa aquest snippet és un helper que permet cridar una llibreria anomenada Tab Pane (llicència web 2.0) que a través de javascript modifica els objectes DOM de la pàgina web i ens permet treballar amb uns tabuladors molt ràpids. A més fins hi tot suporta diferents aspectes. Realment una forma molt còmode i senzilla de treballar amb interficies tabulades.

tabs.png

Doncs tornant a l’snippet de symfony podem cridar el helper i començar a usar el codi de forma ben senzilla, a la pròpia descripció en podeu veure un exemple. Doneu-hi un cop d’ull a Helper for Javascript Tabbed Panes. Com és obvi recordeu que aquest helper s’ha d’invocar des de la vista (template).

aptana: eina professional per programar UI Web

Reading time: 2 – 2 minutes

aptana esta disponible per Mac, Windows, Linux i fins hi tot com a plug-in per l’Eclipse. Així doncs es tracta d’una eina que ens ajudarà a programar. Com ja posava en el títol esta orientada a la creació d’interficies d’usuari via web. Ralment és per gent molt i molt professionals, abstenir-se principiants. Ja que li treurem realment el suc quan treballem amb JavaScript, AJAX, Yahoo UI, CSS, Dojo Javascript library, etc. De fet no em declaro ni usuari de l’eina ni segurament futur usuari de la mateixa, però això no treu que després de veure els screencast que té l’eina m’hagi caigut la baba i hagi sabut apreciar la gran feina que s’ha fet per crear una eina com aquesta.


screenshot_library_project_select.png

Per si tot això fos poc es tracta d’una eina OpenSource i com ja he dit multiplataforma. L’aspecte gràfic esta molt acurat i a més suporta força navegadors per comprobar que el codi que anem programant és compatible en tots ells. Com passa en tots els projectes vanguardistes també disposa d’un blog des d’on podeu anar seguint les millores que va tenint el programa, ja que ara mateix només hi ha disponible la versió beta.

symfony: cridant funcions i18n des de les actions

Reading time: 2 – 4 minutes

Una eina molt potent de symfony és la d’internacionalització (i18n), concretament la funció __() es converteix en una de les més usades i indispensables en la capa de vista de les nostres aplicacions. Ja que permet després de forma molt senzilla traduir la nostre aplicació a l’idioma que sigui. El problema és quan des de la part del model em de carregar informació a objectes que després seràn directament mostrats per la vista. Si volem que aquesta informació sigui fàcilment traudible malgrat trobar-se en el model i no pas en la capa de vista la cosa es complica una miqueta. De fet, fins avui no sabia com es feia i ho he descobert gràcies a un snippet publicat a la web de symfony.

Concretament symfony tracta la funció __() com el que ell anomena un helper que ens permeten dinamitzar i donar moltíssima potència als nostres templates. Si no sabeu el que són els helpers us recomano que repasseu la documentació de symfony concretmanet View chapter. De fet, symfony té molts tipus de helpers: url, javascript, form, i18n, etc. fins hi tot podem programar els nostres propis helpers.

Així doncs el que comentaré serà com usar els helpers de tipus i18n des del model, però la resta de helpers també es poden invocar de la mateixa manera.

Primer cal pensar en incloure des del model el codi on es declaren les funcions del helper:

include_once('symfony/helper/I18NHelper.php');

Per invocar la funció __(), hem de fer:

sfConfig::get('sf_i18n_instance')->__($text, $args, 'messages');

El que no sé és si les eines de traducció que es dediquen a extreure els missatges de les funcions __() són capaces de recorre també els fitxers d’accions definits al model o només passen pels templates. Tot i que no deu ser molt difícil dir-los que també mirin els fitxers del model.

Aprofitant que parlo del tema de la internacionlització us recomano una eina per traduir els fitxers d’idioma (XLIFF) és una eina multiplataforma programada en java: open language tools XLIFF editor. Com podeu veure l’aspecte i la simplicitat és inmillorable. Ideal per persones no tècniques que ens poden fer les traduccions de les aplicacions.

Per generar els fitxers XLIFF des de symfony us recomano: HowToGenerateI18NFiles. És un petit manual que he trobat al wiki de symfony.

symfony: Problemes de javascript

Reading time: 1 – 2 minutes

prototype.png

Symfony usa prototype com a framework de JavaScript. Malgrat la potència del projecte té un petit problema de disseny que ens dona problemes quan intentem integrar el nostre codi fet en prototype/symfony amb codi JavaScript de tercers. De fet, el problema de disseny és molt senzill prototype exten dues classes bàsiques de JavaScript: Object i Array ambdues són classes molt bàsiques i sovint usades en qualsevol script així doncs quan aquest codi intenta usar aquestes classes bàsiques al estar exteses no tenen el comportament habitual, així doncs el codi d’aquestes persones s’ha d’adaptar per suportar les modificacions de prototype. Així doncs, si això no és possible tindrem un problema d’incompatibilitat entre codis.

Si voleu més detalls tèncis sobre el problema l’Oriol m’ha passat un parell d’enllaços es raona el problema:

Un parell d’enllaços molt bons sobre UTF-8 i PHP

Reading time: 1 – 2 minutes

Primer una cosa realment útil, un detector de quin format té un text per poder-lo transformar a UTF8 si cal. Sembla una tonteria però el no tenir-ho sempre et fa anar de corcoll: Detectando UTF8 en PHP (local).

L’altre enllaç és d’un wiki, on ens parlen del comportament de diverses funcions de PHP amb UTF8 i com jugar amb elles sense morir en l’intent i alguna coseta més:

Trac – Control de versions i gestió de Projectes

Reading time: 2 – 4 minutes

trac.png

Ja he comentat varies vegades que com a eina per documentar, mantenir i desenvolupar un projecte (programa) uso trac. Doncs bé en faré cinc cèntims del perquè m’agrada tant. Bàsicament disposa d’un visor del codi a mode del ViewSVN, això ens permet tenir sempre visible el codi font del repositori del subversion, si no recordo malament també pot treballar amb CVS i algún altre.

A través del sistema de tiquets podem generar incidències i requisits pels membres del projecte i per qualsevol altre persona aliena a ell, amb o sense autenticació. Malgrat no és un sistema te tiquets tan elavorat com el bugzilla, per la majoria de projecte relativament petits (menys de 100 persones) jo diria que esta més que bé. A més tota la part de visor de tiquets és molt configurable si volem anar més enllà.

Totes les accions que fem amb qualsevol component del sistema es registra en una línia de temps (timeline) que ens permet veure sempre quina es l’activitat del projecte i en quines parts. A més també podem marcar-nos fites (roadmap) per les noves versions amb dates i el sistema ens farà un seguiment dels tiquets oberts que hi ha perquè es pugui considerar assolida la fita de la nova versió. Per tant, aquests tres components estan molt ben integrats.

Per mi la guinda del pastel és el wiki, que permet documentar el projecte amb un sistema súper integrat amb la resta de móduls del Trac. O sigui, podem per exemple incloure imatges al wiki que realment estan dintre del repositori i les podem referenciar de forma molt senzilla. A més també podem referenciar tiquets, parts del roadmap o de la timeline. A més d’altres funcions típiques dels wikis com poder adjuntar fitxers a les pàgines o fer un control de versions implíssit del contingut de les mateixes. A més tot aquest control de versions també surt reflexat a la línia de temps.

Per si tot això fos poc disposa de funcions tan necessaries com la possilitat de poder-nos sindicar per RSS als tiquets i a la timeline, s’exporten els roadmaps a iCalendar (.ICS), fer busquedes per tot el sistema, transformar gran part dels documents a formats imprimibles i obviament també fa highlight del codi font del repositori. Les ajudes i documentació esta prou bé i és senzill d’usar. A més el sistema de control d’usuaris malgrat ser força primari és força potent, li faltaria poder treballar sobre BBDD o tenir una interfície per gestionar-lo, però per equips de treball no massa grans esta bé.