Category Archives: Programación

Restricciones en las asociaciones ORM de Doctrine2

Es importante conocer las restricciones que Doctrine2 presenta cuando tenemos que elaborar asociaciones entre Entidades. Copiado de la Documentación de Doctrine2:

Because we only work with collections for the references we must be careful to implement a bidirectional reference in the domain model. The concept of owning or inverse side of a relation is central to this notion and should always be kept in mind. The following assumptions are made about relations and have to be followed to be able to work with Doctrine 2. These assumptions are not unique to Doctrine 2 but are best practices in handling database relations and Object-Relational Mapping.

  • Changes to Collections are saved or updated, when the entity on the owning side of the collection is saved or updated.
  • Saving an Entity at the inverse side of a relation never triggers a persist operation to changes to the collection.
  • In a one-to-one relation the entity holding the foreign key of the related entity on its own database table is always the owning side of the relation.
  • In a many-to-many relation, both sides can be the owning side of the relation. However in a bi-directional many-to-many relation only one is allowed to be.
  • In a many-to-one relation the Many-side is the owning side by default, because it holds the foreign key.
  • The OneToMany side of a relation is inverse by default, since the foreign key is saved on the Many side. A OneToMany relation can only be the owning side, if its implemented using a ManyToMany relation with join table and restricting the one side to allow only UNIQUE values per database constraint.

Consistency of bi-directional references on the inverse side of a relation have to be managed in userland application code. Doctrine cannot magically update your collections to be consistent.

Entendiendo la asociaciones Many-To-One y One-To-Many

El texto está claro pero me queda la siguiente duda, a partir de lo documentado sobre una relación Many-To-One Unidirectional: El lado Many es el owning side por qué guarda la clave foránea. En el ejemplo facilitado, una dirección puede pertenecer a diferentes usuarios, y la Entidad Usuario podrá acceder a la Entidad Dirección. Pero desde la Entidad Dirección no se podrá acceder a los usuarios que la tienen asignada. Por ese motivo se llama Unidireccional. A la hora de persistir un objeto Dirección, no se pueden persistir objetos Usuario, ya que no dispone de asociación en ese sentido, es decir, un objeto Dirección no guarda en su instancia ningún Usuario.

En el caso de la relación One-To-Many Bidirectional, se están generando dos relaciones. Una One-To-Many desde Producto a Característica, y otra Many-To-One desde Característica a Producto. El owning side aquí será el lado Característica, por qué guarda la clave foránea en la tabla de la BDD. En la persistencia se entiende que cuando se crea una Característica se asigna a qué Producto pertenece. Si yo creo un nuevo Producto y una nueva Característica, y le asigno el Producto a la Característica y persisto la Característica, en la BDD se guardan ambos. Y entiendo que si en cambio asigno la nueva Característica al Producto y persisto el Producto, sólo se guardaría éste, pero sí se guarda la Característica (¿?).

Incluir tiempo estimado e imputado en las líneas de tareas en Feng Office

Feng Office és una buena herramienta de gestión de proyects, open source y gratuita. Las herramientas gestoras de proyectos siempre tienen el inconveniente que no todas las funcionalidades se adaptan a la manera de trabajar de uno, sin embargo, gracias a ser open source, se puede modificar para conseguirlo.

Una de las necesidades que tenía, era la de visualizar rápidamente y en cada tarea el tiempo estimado en esa tarea y el tiempo acumulado en el desarrollo de la misma, para poder valorar en mientras trabajo si estoy cumpliendo los plazos.

Línea de tarea en Feng Office

A continuación voy a detallar los cambios que he realizado para visualizarlo. He trabajado sobre la versión de Feng Office 1.7.5.

Continue reading

Copiar y pegar desde word con TinyMCE

Desde que empecé a utilitzar los conocidos “HTMLarea”, “textarea enriquecido” o editor WYSIWYG han surgido problemas cuando el cliente hacía copy paste de los textos desde word debido a que mantenía el formato. El código de estilos acababa desmontando la página del site, con la correspondiente llamada del cliente: “Oye, que de repente la página se ve mal…”.

Hace ya tiempo que empecé a implementar TinyMCE, para mí el mejor editor WYSIWYG, y he descubierto que dispone de un plugin realmente bueno y que soluciona los problemas que antes comentaba: SimplePaste.

El plugin es realmente simple. Cuando haces crtl+v sobre el editor borra todo el formato del texto que has pegado. Y ya está. Yo lo he empezado a utilizar y es ideal.

Instalarlo es muy sencillo:

  1. Descargar el archivo zip i descomprimirlo.
  2. Colocar la carpeta simplepaste dentro de la carpeta plugins de la instalación de TinyMCE.
  3. Modificar la configuración del TinyMCE en la página web para que cargue el plugin:

plugins: simplepaste

paste_auto_cleanup_on_paste : true,
paste_create_linebreaks : false,
paste_use_dialog : false,
paste_remove_styles: true,
paste_convert_middot_lists : false,
paste_unindented_list_class : ‘unindentedList’,
paste_strip_class_attributes: ‘all’,
paste_convert_headers_to_strong: false,
paste_as_plain_text: true

El que quiera saber más puede visitar el hilo de discusión sobre SimplePaste en el foro de TinyMCE.

Multibox para mootools 1.2

La necesidad de los nuevos proyectos me ha obligado a adaptar el Multibox de phatfusion para la versión de mootools 1.2, ya que no podía esperar a la versión oficial. Como seguro que más de uno tendrá la misma necesidad aquí dejo un enlace para descargarlo.

Descargar


Detalles del zip:

Incluye los archivos multibox.js y overlay.js.

Instalación:

Simplemente substituir los archivos multibox.js y overlay.js de tu web por los incluidos en el zip.

Actualizaciones:

8/10/2008 – Borrado el código que causaba un mensaje alert

5/09/2008 – Corregido el error que sucedía al querer realizar una carga de html por AJAX

Aviso:

No he conseguido que las opciones onOpen y onClose funcionen. Como que no las he utilizado nunca por ahora no le he dedicado más tiempo.

Indexació de webs multiidioma amb PHP i Apache

La indexació de pàgines als buscadors és quelcom que s’ha tornat gairebé imprescindible a l’hora de publicar una pàgina web. I aquesta importància recau d’igual manera en sites multiidioma on totes les pàgines en tots els idiomes han d’estar indexades.

Jo conec dos sistemes per fer pàgines web multiidioma. El primer seria el clàssic de ficar la web en un idioma, per exemple català, dins http://www.javierseixas.com/blog/wp-admin/post.php?action=edit&post=23la carpeta ‘ca’. Per traduïr-la a un altre idioma, per exemple el castellà, es duplica la carpeta, se li assigna el nom ‘es’ i es tradueixen tots els arxius html que la componen. Aquest sistema no el recomano ja que obliga a que quan s’hagi de fer una modificació fer-la en tants arxius com pàgines hi hagin, lo qual duplica el treball i el temps. De totes maneres no queda més remei que fer-ho així en servidors que no suportin algun tipus de llenguatge.

El segon sistema que conec és mitjantçant includes que contenen les textos fixes, com titol de seccions, nom de botons, etc. Hi ha un include per cada idioma, i mitjançant una sessió carregarà un include o un altre. S’haurà de declarar una sessió per defecte, per quan l’usuari entri per primer cop l’assigni i carregui l’idioma per defecte. Si l’usuari canvia l’idioma canviarà el valor de la sessió.

Fins aquí tot bé, però què passa quan un robot entra al nostre site? El robot trobarà l’enllaç per canviar d’idioma, però no sabrà interpretar el canvi de sessió, per lo qual, el robot només detectarà i indexarà el nostre site en l’idioma per defecte. I com es soluciona aquest problema?

La clau està en col·locar a l’enllaç on es canvia l’idioma una adreça falsa. Per exemple:

<a href="http://www.javierseixas.com/ca">Català</a>
<a href="http://www.javierseixas.com/es">Castellà</a>

Fet això, el PHP haurà de saber en quin idioma s’està navegant. Això es pot saber per la funció $_SERVER['REQUEST_URI'] que retorna la part de l’adreça després del domini. Tot seguit, el PHP haurà de decidir quin include incloure segons hagi dit el REQUEST_URI, per exemple, ca per català , es pel castellà, en per l’anglés. En aquest punt recomano seguir les sigles que utilitza la wikipedia.

I el darrer punt clau el juga Apache. S’ha d’activar el ModRewrite i escriure les regles per l’idioma concret:

RewriteRule ^ca/(.+) /?sec=$1
RewriteRule ^es/(.+) /?sec=$1
RewriteRule ^en/(.+) /?sec=$1

Carregar swfobject per AJAX amb mootools

Construïnt la web de Grapa hem vaig trobar amb un problema: carregar un flash dins d’una capa modificada per AJAX.

Per què ve el problema? Per un costat tenim que el swfobject s’executa quan la pàgina es carrega. Per l’altre costat sabem que l’AJAX carrega un contingut que importa des de una altra pàgina. Quan importa aquest “codi” el que fa és imprimir-lo allà on li dius. Amb mootools es faria així:

var showContents = this.showContents.bind(this);

var ajaxOptions = {
method: 'get',
update: $('section_cont'),
onComplete: showContents
};

this.ajaxRequest = new Ajax(this.url, ajaxOptions).request();

L’AJAX executa un Javascript però no torna a executar la pàgina de nou, per lo qual cridar al swfobject com es fa tradicionalment no funciona.

Com arrivar a la solució? Doncs cal saber una mica com funciona el swfobject. Bàsicament el que fa és crear un objecte i posteriorment imprimir-lo a la capa que li dius. Si això no deixa de ser Javascript, no podriem fer que crees aquest objecte quan ha de carregar l’AJAX?

Doncs efectivament, es pot! Seria alguna cosa així:

showContents: function() {
var interactive_flash = new FlashObject("/swf/reproductor.swf", "header", "548", "425", "8", "#ffffff", true);

interactive_flash.addParam("wmode", "opace");
interactive_flash.addParam("scale", "noscale");
interactive_flash.addVariable("file", this.video);
interactive_flash.write("embed_cont");
}

Si us fixeu, la crida AJAX del primer codi té una linia dins la variable “ajaxOptions” que diu onComplete: showContents. Això vol dir que quan hagi carregat l’AJAX cridarà la funció showContents, la qual crearà el swfobject.

I ja ho tenim. No és pas tan difícil!

Javascript no intrusiu

Vaig començar a treballar amb mootools farà poc més d’un mes, i mirant tot d’exemples de com programar-ho vaig veure en exemples quelcom que ja havia sentit però del que mai havia prestat atenció: el JavaScript no intrusiu.

Bàsicament el JavaScript no intrusiu és el que permet realitzar accions al DOM i manipular els esdeveniments o events però sense haver d’escriure el codi JavaScript dins de les etiquetes html. Fins ara ho veiem així:

<div onclick="executa_funcio()">text qualsevol</div>

Això no està pas malament, però xoca una mica amb la filosofia de separar la web les tres capes de lògica, disseny i estructura perquè estàs barrejant lògica (JavaScript) i estructura (HTML).

Mootools dòna un pas endevant i permet introduïr en el codi el JS no intrusiu d’una forma semblant a la següent:

$A($$('.delete')).each(function(el) {
el.onclick = this.click.pass(el, this);
}, this);

Com es veu en l’exemple el JavaScript crea un Array ($A) amb tots els elements que tenen la classe delete, i inicia un bucle per aquest array on assigna l’event onclick per cadascun d’aquests elements. Com es pot veure no hi ha cap etiqueta html afectada directament. Aquest mètode ajuda a tenir el codi més net i endreçat en les tres capes.

I com passem es paràmetres? Doncs si vols recollir informació ho faries a través dels atributs de l’element afectat. Si tenim a l’html quelcom així:

<div title="Un valor qualsevol" alt="Un altre valor">Text qualsevol</div>

A l’arxiu JS ho recolliriem així (el fa referència al element html):

var param_tit = el.title; // Recull Un valor qualsevol
var param_alt = el.alt // Recull Un altre valor

En definitiva, una passada i que dòna moltes possibilitats!

No sé si Prototype, jquery o el JavaScript tradicional permet fer-ho, però probablement sí.