Tag: Web

Qwant – Recuperando la búsqueda orgánica

¿Nunca has tenido la sensación de que Google te muestra lo que quieres ver en vez de lo que has buscado? ¿Cuántas veces has buscado algo o hablado de algo y ves que hasta los anuncios parece que te han oído? ¿Te has fijado lo que pasa cuando ves en un red social, por ejemplo vídeos de "gatitos", cómo de repente te empiezan a recomendar tantos vídeos de gatitos que no podrías terminar de verlos ni en una vida... Incluso cuando quieres prestar tu atención en otra cosa, tu atención es robada por vídeos de gatitos... Sí, los algoritmos de búsqueda y de recomendación tienen vida propia y compiten por tu atención.

¿Te has planteado alguna vez cuando buscas en Google, si realmente te está buscando el mejor resultado de acuerdo a tu búsqueda? ¿O es una búsqueda sesgada por intereses comerciales (mayormente publicitarios), mezclada con contenido que capte tu atención y te retenga? Si usas el buscador de Google, te adelanto que estás en el segundo caso y lo que debería ser una búsqueda de acuerdo a posicionamiento natural u orgánico, resulta que no lo es, siendo algo coyuntural y anecdótico lo que realmente buscas. Esto quiere decir que los resultados mostrados no son los que tú estás buscando, sino los que Google por diversos ajustes en sus algoritmos está seleccionado para ti.

Esto crea lo que se conoce como un efecto burbuja de información y de contenido, los algoritmos de búsqueda y recomendación van a reforzar el tipo de búsquedas que mejor encajen con tu perfil, porque sí, lo que Google busca es hacer perfiles, conocerte mejor, para ofrecer el mejor servicio de publicidad del mundo y eso implica entender qué llama tu atención. Alguno puede pensar que se salva porque navega de manera privada en Chrome, y nada más lejos de la realidad. Chrome es la punta de lanza con la que Google ha copado el mercado de los navegadores y que usa para que su negocio de publicidad esté mejor controlado y sea más prospero.

Tampoco te libras si usas Firefox y usas el buscador de Google. Ni aún navegando en privado, ya que siempre hay elementos que pueden identificarte (aunque Firefox trabaja incansablemente para protegerte de ese rastreo), como la IP desde la que te conectas que puede acotar una zona geográfica, las maravillosas cookies (esas que acabas aceptando porque no puedes decir que no), las cosas que buscas (dónde entras..., qué miras...) ...

⚠️ Recuerda que todo esto no es por la privacidad, que también debería importarte, sino que esto va de la visión sesgada que recibes cuando un buscador como el de Google da los resultados que da cuando haces una búsqueda, los cuales son sesgados y acomodados a tu perfil.

Foto Buscador de Google 2013 obtenida de Principiantes Socialmedia

Todo esto se mezcla con el SEO (Search Engine Optimization) y el SEM (Search Engine Marketing), que en sí constituyen un negocio, en el que al final el que más relevancia tiene suele ser el que más paga… Alguno pensará que es normal, y lo era... Ya que antiguamente Google tenía en el resultado que veías sin hacer scroll, una parte de resultados orgánicos y otra de promocionados. Actualmente voces del sector dicen que toda la primera página, y hasta la décima página de resultados, son resultado convenientemente colocados por Google, ya sea para publicitarte algo o para retener tu atención de una forma u otra. Sobre este tema, puedes encontrar un buen documental en Neflix llamado "El dilema de las redes sociales" .

Qwant una alternativa a Google con sello Europeo 🇪🇺

Qwant es un buscador que se autodefine como "el primer motor de búsqueda europeo, eficiente y ético". Su motor de búsqueda respeta tu privacidad, y esto lo hace ofreciendo una garantía de neutralidad e imparcialidad en la que ofrece los mejores resultados disponibles para tus consultas y nunca intenta adivinar quién eres o qué estás haciendo. Esto hace que toda la web sea visible "sin ninguna discriminación y sin prejuicios". Afirman que sus algoritmos de clasificación "se aplican por igual en todas partes y para todos los usuarios, sin intentar presentar sitios web o esconder otros basados en intereses comerciales, políticos o morales".

Instalación en Firefox 💾

La instalación en Firefox es muy cómoda. Entra en Qwant dale a "Add Qwan to Firefox" y sigue los pasos.

Puedes elegir que Qwant sea tu motor de búsqueda por defecto o no, pudiendo cambiar los ajustes en "Opciones > Buscar". 💡 Como consejo adicional decirte que puedes asignar atajos para indicar si usas un buscador u otro en tus búsquedas en la barra del navegador (por ejemplo "q mascandobits" o "@google mascandobits").

💡 También puedes seleccionar el motor de búsqueda desde la barra de búsqueda antes de darle a enter, seleccionado el buscador que quieres usar.

Más ℹ️ información en la ayuda de Firefox.

Móvil 📱

Para Firefox móvil la cosa no es tan cómoda, pero puedes añadir Qwant como motor de búsqueda y si quieres puedes hacerlo buscador predeterminado en "Ajustes > Buscar". Si quieres añadir Qwant como motor de búsqueda, dale a "Añadir buscador > Otro" y rellenas:

  • Nombre: Qwant
  • Cadena de búsqueda a usar: https://www.qwant.com/?l=es&q=%s

Con eso ya puedes usar Qwant desde tu Firefox móvil. Lamentablemente tiene que hacerse así porque la extensión de Qwant no funciona en la versión móvil, como tantas otras que requieren de una actualización para ser usadas en versiones modernas de Firefox.

Instalación en Chrome 💾

La instalación en Chrome también es muy cómoda, aunque nos metemos en la guarida del lobo (a Google no le gusta que el motor de búsqueda en Chrome sea otro al suyo) y tienes sus peros. Entra en Qwant dale a "Add Qwan to Chrome" y sigue los pasos.

Por motivos internos que se desconocen y que no han trascendido, con la extensión de Qwant obligatoriamente tienes que usarlo como motor predeterminado y desactivar la extensión para elegir otro. Seguramente tenga mucho que ver con estos mensajes que te saltan en el navegador, en un amago de rescatar la posición de privilegio del motor de Google en su navegador Chrome:

Entiendo que no es una opción del todo cómoda, pero si quieres tener la posibilidad de elegir motor de búsqueda predeterminado puedes introducirlo manualmente. Google se reserva el hecho de sacarlo en cualquier momento de la lista de motores de búsqueda predeterminados, razón por la que ya ha sido varias veces sancionado por la Unión Europea por abuso de posición dominante. Para ello ve a "Configuración > Buscador > Administrador buscadores". Si quieres añadir Qwant como motor de búsqueda dale a "Añadir" en las sección "Otros buscadores" y rellenas:

Un vez creado aparecerá en la lista que hay debajo de "Otros buscadores", dale a los tres puntos para establecerlo como predeterminado.

⚠️ Si lo quitas como predeterminado desaparecerá de la lista de los navegadores seleccionables y tendrás que volver a hacer este paso de añadirlo como predeterminado.

Ahora veis la razón del comportamiento de la extensión de Qwant. 😎 En cualquier caso, aunque lo quitéis como predeterminado lo podréis seguir usando para buscar si usáis la palabra clave al principio de vuestra búsqueda en la barra de búsqueda de Chrome (por ejemplo "@qwant mascandobits").

Móvil 📱

Para Chrome móvil, siendo Android bastión de Chrome, la cosa está complicada y mucho... Es imposible añadir un nuevo buscador en "Configuración > Buscador", sólo permite elegir entre los que te ofrece y vuelve a reservarse el derecho Google de poner su buscador como buscador predeterminado.

Aún así existe una pequeña opción de usar Qwant como motor de búsqueda predeterminado. Es iniciando sesión con una cuenta de Google en Chrome, en un equipo de sobremesa y habilitar la sincronización, pudiendo así sincronizar extensiones. ¡Muy buena Google!, así puedes controlar la extensión, no se te escapa una 😉😅. Reza el dicho que: "mantengas cerca a tus amigos, pero aún más cerca a tus enemigos".

Tristemente la mejor opción de usar Qwant en Chrome desde un móvil, es estableciendo Qwant como página principal. 😢

Impresiones

Qwant ♥️ Firefox 👌

Llevo ya unos cuantos meses usándolo y estoy encantado con Qwant, lo tengo como motor principal de búsqueda. No lo he sustituido completamente por Google, porque a veces resulta interesante el efecto burbuja de los resultados de sus búsquedas, sobre todo en ámbitos profesionales. No obstante cuando quiero abrir mi mundo, mi herramienta es Qwant sin duda.

Además no debemos olvidar que cotejar varias fuentes es algo básico en nuestra sociedad de la "desinformación". Y un buscador por mucho que nuestras leyes digan que es, o debería ser, un agente neutro, no lo es. Coteja varios resultados de distintos buscadores siempre y no uses sólo uno.

Buenas Prácticas para el Buen Diseño de una API RESTful

Según pasa el tiempo y vas haciendo servicios que tienen que escalarse e integrarse con otros servicios, te vas dando cuenta de lo necesario que es un buen diseño o por lo menos de un diseño mínimamente bien pensando y ejecutado que cumpla una serie de requisitos mínimos. Ésta es la idea que pretendo transmitiros, pero antes os ubico un poco.

En la entrada de Linkero – Creación de APIs RESTful en Python os presenté el framework Linkero que permitía montar APIs RESTful, y se presentaba junto con un ejemplo a forma de iniciación en las mismas.  En este entrada voy presentar una serie de recomendaciones, que pueden considerarse buenas prácticas, y que debéis tener en cuenta para asegurar un buen diseño de vuestras APIs RESTful.

El concepto subyacente de una API RESTful es la de dividir la estructura de la API en recursos lógicos, montados sobre una URL, que nos permitan acceder a información o datos concretos usando métodos HTTP como POST, GET, PUT y DELETE para operar con los recursos. Estos métodos son equiparables a las operaciones CRUD (Create, Read, Update, Delete) de las bases de datos. Aclarado esto, empecemos con las recomendaciones.

 

Usar nombres pero no verbos


Por cuestiones de mejor comprensión y legibilidad de la semántica de la API, usa sólo nombres para toda su estructura.

RecursoPOST
create
GET
read
PUT
update
DELETE
/carsCrea un nuevo cocheDevuelve la lista de cochesActualización en bloque de cochesBorrar todos los coches
/cars/711Método no permitido (405)Devuelve un coche específicoActualiza un coche específicoBorra un coche específico

No usar verbos como:

/getAllCars
/createNewCar
/deleteAllRedCar

La propia semántica que compone la URL, junto con el método  HTTP usado (POST, GET, PUT, DELETE), permite prescindir de verbos como "create", "get", "update" y "delete".

 

Métodos GET y los parámetros de consulta no deben alterar el estado


Usa los métodos POST, PUT o DELETE para cambiar los estados de los recursos, en vez de hacerlo con el método GET o un petición con parámetros de consulta. Para algo tienes 3 métodos que te permiten hacer eso 😉 .

Esto es lo que no se debería hacer:

GET /users/711?activate
GET /users/711/activate

Es mucho mejor hacer esto:

PUT /users/711/activate

o esto:

POST /users/711/activate

Cuál usar dependerá del diseño de la base de datos o la lógica con la que se estructura el almacenamiento de la misma.

 

Usar nombres en plural


No mezcles nombres en singular con nombres en plural. Hazlo simple y mantén los nombres en plural.

En vez de usar:

/car
/user
/product
/setting

Usa el plural:

/cars 
/users 
/products 
/settings

El uso del plural te permitirá posteriormente hacer operaciones del tipo:

/cars/<id> 
/users/<id> 
/products/<id> 
/settings/<name>

 

Usar subrecursos para establecer relaciones


Si un recurso está relacionado con otro, usa subrecursos montados sobre la estructura de la URL.

GET /cars/711/drivers/ Devuelve una lista de conductores para el coche 711
GET /cars/711/drivers/4 Devuelve el conductor #4 para el coche 711

 

Usar cabeceras HTTP para la serialización de formatos


Tanto la parte cliente como la del servidor, necesitan saber en qué formato se están pasando los datos para poder comunicarse. Lo más sencillo es especificarlo en la cebecera HTTP.

Content-Type: Define el formato de la petición.
Accept: Define la lista de formatos aceptados en la respuesta.

 

Usar HATEOAS


El uso de HATEOAS (Hypermedia as the Engine of Application State) es un diseño que nos permite incluir el principio de hipervínculos de manera similar a la navegación web, lo que nos permite una mejor navegación por la API.

En este ejemplo la respuesta en formato JSON nos devuelve junto con la información del equipo con id 5000, una serie de referencias a recursos relacionados, como pueden ser el estadio del equipo o sus jugadores. Normalmente se suele agrupar todas las referencias dentro de una propiedad o atributo llamada "links".

{
    "links": [{
        "rel": "self",
        "href": "http://localhost:8080/soccer/api/teams/5000"
    }, {
        "rel": "stadium",
        "href": "http://localhost:8080/soccer/api/teams/5000/stadium"
    }, {
        "rel": "players",
        "href": "http://localhost:8080/soccer/api/teams/5000/players"
    }],
    "teamId": 5000,
    "name": "Real Madrid C.F.",
    "foundationYear": 1902,
    "rankingPosition": 1
}

Este tipo de diseño está pensado para la longevidad del software y la evolución independiente, ya que frecuentemente en la arquitectura de sistemas y servicios, es a corto plazo lo que más suele fallar.

 

Proveer filtrado, ordenación, selección de campos y paginación para colecciones


 

Filtrado

Utilizar un parámetro de consulta único para todos los campos o un lenguaje de consulta formalizado para filtrar.

GET /cars?color=red Devulve una lista de coches rojos
GET /cars?seats<=2 Devuelve una lista de coches con un máximo de 2 plazas

 

Ordenación

Permitir ordenación ascendente o descendente sobre varios campos

GET /cars?sort=-manufactorer,+model

En el ejemplo se devuelve una lista de coches ordenada con los fabricantes de manera descendiente y los modelos de manera ascendente.

 

Selección de campos

Permitir la selección de unos pocos campos de un recurso si no se precisan todos. Dar al consumidor de la API la posibilidad de qué campos quiere que se devuelvan, reduce el volumen de tráfico en la comunicación y aumenta la velocidad de uso de la API.

GET /cars?fields=manufacturer,model,color

En el ejemplo se pide la lista de coches, pero pidiendo sólo los campos de "fabricante", "modelo" y "color".

 

Paginación

Uso de "offset" para establecer la posición de partida de una colección y "limit" para establecer el número de elementos de la colección a devolver desde el offset. Es un sistema flexible para el que consume la API y bastante extendido entre los sistemas de bases de datos.

GET /cars?offset=10&limit=5

En el ejemplo se devuelve una lista de coches correspondiente a los coches comprendidos de la posición 10 a la 15 de la colección.

Para devolver al consumidor de la API el número total de entradas se puede usar la cabecera HTTP  "X-Total-Count" y para completar la información proporciona, por ejemplo, devolver los enlaces a la página previa y siguiente, entre otros, usando la cabecera HTTP "Link".

Link: <http://localhost/sample/api/v1/cars?offset=15&limit=5>; rel="next",
<http://localhost/sample/api/v1/cars?offset=5&limit=5>; rel="prev",
<http://localhost/sample/api/v1/cars?offset=50&limit=3>; rel="last",
<http://localhost/sample/api/v1/cars?offset=0&limit=5>; rel="first",

Como alternativa es posible usar HATEOAS, como ya he comentado anteriormente.

 

Versionar la API


Es muy recomendable, tirando a obligatorio 😉 , el poner versión de API y no liberar APIs sin versión. Usa un simple número para especificar la versión y no uses un versionado tipo semver del tipo 1.5.

Si se usa la URL para marcar la versión, pon una "v" precediendo el número de versión.

/blog/api/v1

Es la forma más sencilla y eficaz de asegurar la compatibilidad en el versionado de la API. Especificarla como parámetro o en la petición y/o en la respuesta, conlleva el aumento del tráfico y el  coste de  computación, al tener que existir lógica para discriminar las distintas versiones soportadas sobre una misma URL.

 

Manejar errores con código de estado HTTP


Es difícil trabajar con una API que ignora el manejo de errores, por no decir imposible 😉 . La devolución de un código HTTP 500 para cualquier tipo de error o acompañado de una traza de error del código del servidor no es muy útil, además de que puede ponernos en peligro ante una vulnerabilidad que un atacante quisiera explotar.

 

Usar códigos de estado HTTP

El estándar HTTP proporciona más de 70 códigos de estado para describir los valores de retorno. En general no los utilizaremos todos, pero se debe utilizar por lo menos un mñinimo de 10, que suelen ser los más comunes:

CódigoSignificadoExplicación
 200 OK Todo está funcionado
 201 OK Nuevo recurso ha sido creado
 204 OK El recurso ha sido borrado satisfactoriamente
 304 No modificado El cliente puede usar los datos cacheados
 400 Bad Request La petición es inválida o no puede ser servida. El error exacto debería ser explicado en el payload de respuesta
 401 Unauthorized La petición requiere de la autenticación del usuario
 403 Forbidden El servidor entiende la petición pero la rechaza o el acceso no está permitido
 404 Not found No hay un recurso tras la URI
 422 Unprocessable Entity Debe utilizarse si el servidor no puede procesar la entidad. Por ejemplo, faltan campos obligatorios en el payload.
 500 Internal Server Error Los desarrolladores de APIs deben evitar este error. Si se produce un error global, el stracktrace se debe registrar y no devolverlo como respuesta.

 

Usar el payload para los errores

Todas las excepciones deben ser asignadas en un payload de error. A continuación se muestra un ejemplo de cómo podría verse un payload de error en formato JSON:

{
  "errors": [
   {
    "userMessage": "Sorry, the requested resource does not exist",
    "internalMessage": "No car found in the database",
    "code": 34,
    "more info": "http://dev.mascandobits.es/blog/api/v1/errors/12345"
   }
  ]
}

 

Permitir la sustitución del método HTTP


Algunos proxys sólo admiten métodos POST y GET. Para que una API RESTful funcione con estas limitaciones, la API necesita una forma de sustituir el método HTTP.

Una opción es utilizar la cebecera HTTP "X-HTTP-Method-Override" para sobrescribir el método POST y así personalizar la petición POST para que cumpla, por ejemplo, una operación DELETE.

X-HTTP-Method-Override: DELETE

 

Espero que esta concisa guía os permita realizar APIs RESTful con un mejor diseño, o mejorar aquellas que ya tengáis desarrolladas, eso sí generando una nueva versión de la API 😉 .

 

Simple RFC1738 Encoder – Codificación de una URL

La Informática e Internet es una piña de estándares que muchas veces a los desarrolladores nos son transparentes. Esto provoca que habitualmente no nos formulemos la pregunta de cómo se codifica, se procesa y se manda una dato, ya que existen funciones de alto nivel que nos resuelven dicha problemática o simplemente se realiza de manera transparente al desarrollador mediante un Framework o Librería.

¿Alguna vez te has preguntado cómo se codifican los caracteres que escribes? La verdad es que esto de la informática nació en los Estados Unidos y su Silicon Valley. Esto hace obvio que las codificaciones se pensaron para el inglés.

Con el tiempo la informática se extendió hasta su uso normalizado que tenemos hoy en día. El problema que tuvimos los de habla latina era que la codificación de base era UTF-8 y no incluía nuestros caracteres latinos, tales como: tildes, signos de exclamación e interrogación en la apertura, letra ñ ... para caracteres codificados con 1 byte. Esto hacía necesario usar 2 bytes para codificar los caracteres latinos, ya que con 1 byte los caracteres incluidos son los de US-ASCII, subconjunto con un total de 128 caracteres correspondientes a las primeras posiciones de la tabla ASCII (American Standard Code for Information Interchange).

UTF-8 es un formato de codificación de caracteres Unicode e ISO-10646. La necesidad de usar 2 bytes para codificar caracteres latinos hace que la codificación en términos de consumo de espacio sea mayor, siendo necesario usar el doble de espacio (16 bits) si estamos codificando en algún idioma con caracteres latinos. A tal efecto se creó ISO-8859 y la derivación concreta ISO-8859-1 que es la norma de la ISO que define la codificación del alfabeto latino, incluyendo los diacríticos (como letras acentuadas, ñ, ç), y letras especiales (como ß, Ø). Esta codificación permite que dichos caracteres latinos se codifiquen en 8 bits, permitiendo la codificación del rango de los 128 primeros caracteres de la tabla ASCII y otros 128 caracteres más para lo que se denomina el conjunto de códigos extendidos de la tabla extendida ASCII. Puedes echarle un ojo a dicha tabla en:

https://github.com/RDCH106/Simple-RFC1738-Encoder#ascii-code---the-extended-ascii-table

Esta introducción que espero que haya servido para aclarar ciertos conceptos, sirve como base para la segunda parte que paso a explicar en las siguientes líneas.

Una forma habitual de pasar información en peticiones HTTP, es mediante el uso de encolado de parámetros en la URL (Uniform Resource Locator). Esto nos permite comunicarnos con APIs de otros servicios y a la vez es la base de las APIs RESTful como la que presentaba en la entrada "Linkero – Creación de APIs RESTful en Python".

Obviamente de nuevo tenemos una especificación para codificar las URLs que es la RFC-1738 de 1994 creada por Tim Berners-Lee, el inventor de World Wide Web. Dicha especificación define que sólo un reducido conjunto de caracteres puede usarse en las URLs, los cuales son:

  • A to Z (ABCDEFGHIJKLMNOPQRSTUVWXYZ)
  • a to z (abcdefghijklmnopqrstuvwxyz)
  • 0 to 9 (0123456789)
  • $ (Dollar Sign)
  • - (Hyphen / Dash)
  • _ (Underscore)
  • . (Period)
  • + (Plus sign)
  • ! (Exclamation / Bang)
  • * (Asterisk / Star)
  • ' (Single Quote)
  • ( (Open Bracket)
  • ) (Closing Bracket)

Para mapear el amplio rango de caracteres utilizados en todo el mundo en los 60 caracteres permitidos en una URL, se utiliza un proceso estándar de dos pasos:

  • Conversión de la cadena de caracteres, en una secuencia de bytes utilizando la codificación UTF-8.
  • Conversión de cada byte que no sea una letra o dígito ASCII a% HH, donde HH es el valor hexadecimal del byte.

Por ejemplo, la cadena: "Rubén", sería codificada como: "Rub%C3%A9n"

Este es el proceso que de manera estándar se usa y que puedes encontrar en funciones como encodeURI en Javascript o urlencode en PHP. Pero esto no quiere decir que no puedas usar ISO-8859 como codificación base y luego codificar la URL con RFC-1738, consiguiendo de esta forma trabajar sobre una base de caracteres que permite ciertos caracteres, que aunque se puedan codificar en UTF-8, resultan ilegibles. Por ejemplo, la cadena: "Rubén", sería codificada como: "Rubén". No se entiende, ¿verdad?

El uso de UTF-8 nos obliga siempre a codificar dos veces, mientras que si se asume la codificación  ISO-8859, sólo es necesario aplicar la RFC-1738. Veis por donde voy, ¿no? UTF-8 es un estándar que nos penaliza por no ceñirse nuestra grafía de las letras de nuestro alfabeto al conjunto de caracteres ingleses. A pesar de que podamos codificarlo luego de nuevo, se antoja un paso prescindible si directamente se asume ISO-8859 en cualquiera de sus variantes como base de codificación de los caracteres. En mi caso la ISO-8859-1. De esta forma la codificación con RFC-1738 queda con un único valor hexadecimal (perteneciente a la tabla ASCII extendida) para los caracteres ilegibles codificados con UTF-8. Esto además genera URLs más cortas al no tener que usar dos conjuntos de hexadecimales para un único caracter. Por ejemplo, la cadena: "Rubén", sería codificada como: "Rub%E9n".

Esta problemática me llevó a desarrollar Simple RFC1738 Encoder, al cual podéis acceder a su código desde la dirección del proyecto:

https://github.com/RDCH106/Simple-RFC1738-Encoder

En el proyecto se explica de manera más resumida lo presentado en esta entrada y se ofrece la posibilidad de probar la librería desde:

https://rawgit.com/RDCH106/Simple-RFC1738-Encoder/master/demo.html

En la demo se pueden probar los distintos ejemplos de codificación presentados durante la entrada como son la codificación UTF-8 y la codificación RFC-1738 con o sin UTF-8 como codificación base. Podéis comprobar los resultados con las tablas facilitadas en el README del proyecto:

https://github.com/RDCH106/Simple-RFC1738-Encoder/blob/master/README.md

El proyecto Simple RFC1738 Encoder pretende ofrecer la capacidad de codificar las URLs usando RFC-1738 pero sin la necesidad de codificar con UTF-8 como base, pudiendo usar cualquier otra codificación como las recogidas en ISO-8859.

Activación de XDebug en XAMPP para depuración con Netbeans

Uno de los problemas de desarrollar en PHP, es que se interpreta en el lado del servidor y lo que devuelve es la información procesada de la lógica de PHP. Esto nos lleva a la problemática de que es poco útil inundar de trazas  de PHP que escriban en el HTML resultante de vuelta, los estados concretos de las variables procesadas durante la ejecución de la lógica programada.

Esto nos obliga a poner algún tipo de servicio de depuración que nos interrumpa la ejecución del intérprete de PHP y nos mande la información del estado de ejecución de cada punto de ruptura o de parada (breakpoint) que queramos añadir.

Uno de los frameworks de depuración más extendidos es XDebug, que además de ofrecer capacidades de depuración (debugging) también  ofrece características de análisis de rendimiento (profiling). Este framework se integra muy bien con todos las soluciones de servidor PHP,  como es mi caso concreto de XAMPP y mi entorno de desarrollo integrado Netbeans.

Para integrarlo lo primero que tenemos que hacer es localizar el fichero de configuración "php.ini" que contiene la información de configuración del intérprete de PHP que se encuentra en el directorio "xampp/php". Abrimos el fichero con un editor de texto cualquiera y buscamos la existencia de "[XDebug]" y descomentamos las siguiente líneas quitando el punto y coma de delante de cada línea para conseguir las siguiente configuración:

[XDebug]
zend_extension = php_xdebug.dll
xdebug.remote_enable = 1
xdebug.remote_handler = dbgp
xdebug.remote_host = localhost
xdebug.remote_port = 9000

En el caso de no estar todas las líneas añade las que falten y si no encuentras nada que te referencie a XDebug, añádelo. En las últimas versiones de XAMPP sigue estando incluido XDebug, pero no hay rastro de él en el fichero de configuración. No obstante comprueba que existe en el directorio "xampp/php/ext" la libería dinámica "php_xdebug.dll".

Si alguno le echa un ojo al resto del fichero "php.ini", se dará cuenta que existen un apartado de extensiones dinámicas (Dynamic Extensions), donde se referencian otras librerías dinámicas del directorio "xampp/php/ext", cargadas con  "extension=", en vez de "zend_extension=". Esto es debido a que se carga usando el motor Zend. Si no lo respetáis, no os funcionará a pesar de que PHP os lo reconozca.

Para que la configuración tenga efecto guardamos el fichero y reniniciamos Apache si estaba ya funcionando. Si todo está correcto, entrando en la siguientes direcciones:

... deberíamos poder encontrar XDebug y poder ver toda la configuración.

php_xdebug

Ahora vayamos a Netbeans, quien por defecto ya viene con XDebug preconfigurado. En "Herramientas-->Opciones-->PHP-->Debugging", comprobamos que "Debugger Port" sea el 9000 (el que configuramos en el fichero php.ini) y desmarcamos, si lo estuviera, la opción "Stop at First Line" para que no entre en modo depuración en la primera línea del proyecto, sino cuando encuentra un breakpoint.

netbeans-php-debugging-config

Ahora si marcamos en cualquier parte del código con un breakpoint y lanzamos el proyecto en modo depuración netbeans-debug, la ejecución parará en el breakpoint marcado, pudiendo continuar la ejecución paso a paso si lo necesitásemos, supervisando la lógica y valores tomados durante la ejecución.

xdebug_break_point

Como habéis podido ver, el depurado XDebug configurado en XAMPP  e integrado con Netbeans, resulta de los más útil, dotándonos de una herramienta de depuración perfecta para trabajar en nuestros proyectos de PHP.