Archivo de la categoría: Programación

js-icon

Boilerplate (esqueleto) de plugin jQuery de la casa y en español ;)

Hola!. Me complace anunciar que pongo a disposición de todo el que quiera hacer plugins de jQuery, el boilerplate que he estado usando en los últimos años.

Es otro boilerplate como los demas, con la diferencia que al estar usandolo todo el tiempo lo fui puliendo poco a poco. Pero mucho mas importante: está en español XD

Pase pasen y vean https://github.com/capynet/jQueryPluginBoilerplate

Chau!

PHP

Detectar el navegador y toda su información desde PHP o Javascript

Hola, les hago una intro bien corta y pasamos al código.

Browscap es un proyecto que recoge la información de todos los navegadores web en una base de datos que distribuye de forma gratuita y en varios formatos.

PHP tiene soporte nativo para hacer uso de esta DB, pero debido a un par de limitaciones que PHP aun no ha solventado en su API, en GitHub un usuario creó una soluciona basada también en la DB de Browscap pero mucho mas robusta y fácil de usar.

Bien, llegados a este punto sabemos que lo que necesitamos usar es Browscap junto a la librería que se creó para explotarla.

Para mas información, toda la documentación completa de php-browscap la pueden encontrar aquí. Yo me centro en una implementación mucho mas simple porque realmente creo que de los 40 datos que entrega sobre el navegados, con apenas 7 tenemos el 99% de los casos cubiertos.

Acá tienen un ejemplo funcionando para que vean lo rápido y certero que es a la hora de conseguir la info del browser (pruébenlo con mas de uno)

Ok, pongamos algo de código que sino todo esto es muy aburrido:
Vamos a aprovechar esta librería bajo dos situaciones. en PHP y en JS

En PHP

Descarguen la librería php-browscap via Composer o a mano. Pueden saber mas sobre como descargarla aquí
Ahora que la tenemos creamos un archivo index.php para usarla.

<?php
require 'vendor/autoload.php';
use phpbrowscap\Browscap;
$bc = new Browscap('cache');
/** @var stdClass $current_browser */
$current_browser = $bc->getBrowser();
?>

Fácil, no?. Ok ya tenemos un stdClass en $current_browser con toda la información disponible del browser que llame a index.php

Aplicaciones?

Puedes por ejemplo tomar decisiones del tipo

<?php
$curr_br = $current_browser->Browser;
$CoolBrowsers = $curr_br == 'Chrome' || $curr_br == 'Firefox';
if ($CoolBrowsers) {
  add_asset('css', 'just-for-cool-browsers.css');
  $output = renderAdvancedLayout();
}
else {
  add_asset('css', 'just-for-bad-bad-browsers.css');
  $output = renderBasicLayout();
}
?>

También puedes detectar si están accediendo desde un móvil o una tablet, incluso saber si es Android, IOS, la version del SO, etc. Con toda esta información a resumidas cuentas puedes entregar un contenido muy preciso.

Beneficios

Estas entregando contenidos a medida, ergo necesitas entregar menos HTML, CSS, Js y las imágenes mas adecuadas al navegador. Esto finalmente se traduce en menos procesamiento del lado del servidor, lo que se entrega pesa menos KB y el navegador tarda menos en leer y renderizar todos los recursos (en especial JS).

En JS

Por ultimo me gustaría compartir un tip para poder aprovechar la detección de browsers en JS:
A ver, con js podemos detectar el browser usando un poco de expresiones regulares, pero llegar al detalle y la precisión a la que llega browscap es virtualmente imposible. Dicho esto, comentar que se puede entregar toda la información del browser detectado desde php simplemente haciendo esto:

<script type="application/javascript">
  var browser = <?php= json_encode($current_browser = $bc->getBrowser()); ?>;
  alert(browser.Browser);
  alert(browser.Version);
</script>

Hasta la próxima!

Desplegar una aplicación Node.js como servicio systemd (demonio)

En el mundo linux hay dos gestores de demonios que se suelen usar en casi todas las distribuciones. Upstart o systemd.

Si lo que quieres es crear un demonio para Ubuntu o cualquier otro SO que use Upstart, tienes que leer este articulo, y si lo que quieres es crear el demonio para Debian u otros que usen systemd, sigue leyendo este post.

Vamos al lio. Para nuestro demonio vamos a necesitar 3 cosas: forever, un script para crear el servicio y un script para avisar a monit para que mire nuestro servicio y lo reinicie si se cae.

El script del servicio

Como me gusta ponértelo fácil, voy a obviar la explicación y simplemente les digo que copies el siguiente código y lo pegues dentro de un archivo que se llame como el servicio que quieres crear dentro de /etc/init.d/my-service (por ejemplo).

Dentro de este archivo solo tienes que tocar dos o tres cosas al principio del archivo en la zona de configuración. Es fácil, básicamente es poner el nombre del servicio (en mi ejemplo es “my-service”), el directorio donde está alojado, y el nombre del archivo principal de la aplicación.
Hay algunas cositas mas que se pueden configurar, pero en general con esto basta.

#!/bin/bash
# This service requires you have forever app installed in your system.
### CONFIG ZONE
# This is the service name. It cant have any special char or space.
serviceName="my-service"
# Where is located your app
appFilePath="/var/node/my-service-node-app"
# Whats the name of your main app file.
appIndex="app.js"
enviroment=production
### END CONFIG ZONE
###### DO NOT EDIT BELOW THIS LINE ######
# Source function library.
. /lib/lsb/init-functions
pidFile="/var/run/$serviceName.pid"
logFile="/var/run/$serviceName.log"
command="node"
nodeApp="$appFilePath/$appIndex"
foreverApp="forever"
start() {
	echo "Starting $serviceName"
	PATH=/usr/local/bin:$PATH
	export NODE_ENV=$enviroment
	$foreverApp start --pidFile $pidFile -l $logFile -a -d -c "$command" $nodeApp
	RETVAL=$?
}
restart() {
	echo -n "Restarting $serviceName"
	$foreverApp restart $nodeApp
	RETVAL=$?
}
stop() {
	echo -n "Shutting down $serviceName"
	$foreverApp stop $nodeApp
	RETVAL=$?
}
status() {
   echo -n "Status $serviceName"
   $foreverApp list
   RETVAL=$?
}
case "$1" in
   start)
        start
        ;;
    stop)
        stop
        ;;
   status)
        status
       ;;
   restart)
   	restart
        ;;
	*)
       echo "Usage:  {start|stop|status|restart}"
       exit 1
        ;;
esac
exit $RETVAL

Tambien dejo el gist para que cualquier mejora que quieras añadir lo hagas por esta via.
https://gist.github.com/capynet/2de13de81ef8a71f2b2f

Ya tenemos servicio! ¿Y como lo usamos?. Pues como cualquier servicio:

sudo service my-service start
sudo service my-service stop
sudo service my-service restart
sudo service my-service status

Esto debería alcanzar, pero no. Este demonio no sabe volver a arrancarse si la aplicación de nodejs se para. Esa parte la vamos a solucionar usando monit.

Configurar monit

El rol de monit es el de “mirar” todo el tiempo al demonio que creamos anteriormente, y arrancarlo si este se muere.

En Debian y la mayoría de distros, a los archivos de configuración que tenemos que crear (uno por demonio) los pondremos en “/etc/monit/monitrc.d/“.
Yo por lo general creo un archivo con el formato monit-[MI-SERVICIO].conf.

Dentro de este archivo SIEMRPE vamos a usar el siguiente formato, así que simplemente cópialo, pon el nombre del demonio y el puerto, guarda los cambios, reinicia monit y listo.

check process my-service with pidfile "/var/run/my-service.pid"
        start program = "/etc/init.d/my-service start"
        stop program = "/etc/init.d/my-service stop"
        if failed
                port [THE NODEJS PORT HERE] protocol HTTP
                request / with timeout 10 seconds
        then restart

De nuevo, aqui está el gist para que contribuyas si quieres.
https://gist.github.com/capynet/c7aa09a996fe909a0960

NOTA: En algunas instalaciones de monit, hay que tocar su archivo de configuración general para que incluya los archvos de monitorización que añadamos. El archivo es /etc/monit/monitrc y tienes que editarlo como sudo y añadir al final “include/etc/monit/monitrc.d/*” si no lo tuviera ya puesto.

Bueno si a estas alturas todavía no tienes instalado forever, instalalo con sudo npm install forever -g

Hemos acabado, ya puedes arrancar monit o reiniciarlo si ya estaba corriendo. Monit va a usar el script que creamos para el para ver si el servicio está corriendo, si no es así, el solito se encarga de levantarlo y mantenerlo en funcionamiento inclusive después de reiniciar el servidor.

Chau!

Herramientas

Habilitar el opcache que viene con php ( >= 5.5 ) en xampp

Ya en el futuro de va a demostrar si este nuevo opcache es mejor que los ya conocidos, pero de momento es el ÚNICO que funciona razonablemente bien en WINDOWS.

Edita tu “php.ini” y pega esto al final del archivo (si tenes configurado xdebug, al opcache ponelo por encima de este)

[Opcache]
; poné el path real donde esté alojado php_opcache.dll
zend_extension = "C:\xampp\php\ext\php_opcache.dll"
opcache.memory_consumption = 500
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=1

Y listo, tenemos un motivo menos de sufrimiento a la hora de programar en este SO.

Chau!

Druplicon

Drupal: Importar y sincronizar desde un XML local o remoto con Migrate

Continuando con Migrate, hoy toca importar XML’s de forma local y remota. Para la forma remota he colocado un XML de ejemplo con un solo item que pueden usar para probar que todo funcione.

Ok sin más dilación esta es la clase para importar de forma remota:

<?php
class WPMigrationFromXML extends XMLMigration {
  public function __construct($arguments) {
    parent::__construct($arguments);
    $items_url = 'http://ecapy.com/wp-content/uploads/2013/06/wordpress.xml_.txt';
    $item_xpath = '/rss/channel/item';
    $item_ID_xpath = 'wp:post_id';
    $this->source = new MigrateSourceXML($items_url, $item_xpath, $item_ID_xpath);
    $this->destination = new MigrateDestinationNode('page');
    $this->map = new MigrateSQLMap($this->machineName,
      array(
        'wp:post_id' => array(
          'type' => 'int',
          'unsigned' => TRUE,
          'not null' => TRUE,
        )
      ),
      MigrateDestinationNode::getKeySchema()
    );
    $this->addFieldMapping('uid')->defaultValue(1);
    $this->addFieldMapping('created', 'wp:post_date')->xpath('wp:post_date');
    $this->addFieldMapping('title', 'title')->xpath('title');
    $this->addFieldMapping('body', 'content:encoded')->xpath('content:encoded');
  }
}

La primer diferencia y que es única para la importación de XML es que no extiende de la clase Migration como vimos en la importación desde DB’s, sino que lo hace de XMLMigration() ya que los XML son un poco especiales a la hora de tratarlos.

Otra cosa que cambia obviamente es el source, que esta vez es MigrateSourceXML() y que requiere 3 cosas como mínimo: la ubicación del archivo ya sea local o remota la ruta, el path que representa un item y por ultimo el identificador único del item. Si revisan el xml que adjunté van a poder verle mas sentido.

Y la última cosa que es única de los XML, es el mapeo de los fields. Pueden ver que MigrateSourceXML() añade un método ->xpath() para que le digamos de donde sacar la información.

Y para la importación local solo hay que cambiar $items_url por algo como:

<? $items_url = DRUPAL_ROOT . '/' . drupal_get_path('module', 'mimodulo') . '/sources/wordpress.xml';

Chau!

Druplicon

Drupal: Importar y sincronizar desde una DB con Migrate

En el post anterior vimos por encima como implementar un migrator, que no es mas que una clase que extiende de Migration. La clase Migration nos quita prácticamente todo el trabajo de encima (en lo que se refiere a procesar la importación y creación de contenidos). Lo único que se necesita para crear un migrator es implementar el método __construct() y decirle donde esta la info que entra, que hace con esa info y la relación de cada fila de un item entrante con respecto a la fila de una entidad.

Dicho lo anterior, el ejemplo de uso para migrar desde DB externas sería:

<?php
class WPMigrationFromDB extends Migration {
  public function __construct($arguments) {
    // 1
    parent::__construct($arguments);
    // 2
    Database::addConnectionInfo('temporal', 'MI_DB', array(
      'driver' => 'mysql',
      'database' => 'MI_DB',
      'username' => 'USUARIO',
      'password' => 'CLAVE',
      'host' => 'localhost',
    ));
    // 3
    $query = Database::getConnection('MI_DB', 'temporal')
      ->select('wp_posts', 'posts')
      ->fields('posts', array(
        'id',
        'post_title',
        'post_content',
      ))
      ->condition("post_type", "post", "=")
      ->condition("post_status", "publish", "=");
    // 4
    $this->source = new MigrateSourceSQL($query);
    // 5
    $this->destination = new MigrateDestinationNode('page');
    // 6
    $this->map = new MigrateSQLMap($this->machineName,
      array(
        'id' => array(
          'type' => 'int',
          'unsigned' => TRUE,
          'not null' => TRUE,
        )
      ),
      MigrateDestinationNode::getKeySchema()
    );
    // 7
    $this->addFieldMapping('uid')->defaultValue(1);
    $this->addFieldMapping('title', 'post_title');
    $this->addFieldMapping('body', 'post_content');
  }
}

Enumeré cada uno de los puntos mas importantes:

  1. Dejamos que Migration ejecute su constructor
  2. Conectamos con una DB externa
  3. Preparamos la query que va a devolvernos solo las columnas que necesitamos.
  4. Pasamos la query a $this->source para que sepa desde donde extraer la información.
  5. Especificamos el destino.
  6. Establecemos el mapeo entre los campos extraídos de la DB y los field de la entidad que se va a crear.

Y eso es todo lo que necesita una implementación de Migration para procesar la información desde una DB. como siempre, esto es solo un ejemplo rapido para que sepan por donde arrancar, pero si realmente quieren conocer mas sobre implementar un migrator usando de fuente una DB lean https://drupal.org/node/1152150

Chau!

Node.js

Desplegar una aplicación Node.js como servicio Upstart (demonio)

Cuando quise desplegar mi app, imagine que iba a ser fácil, que lanzaba el comando “node miapp.js” y punto, pero aprendí a palos que así no va la cosa.

Para desplegar una aplicación web, necesitas que funcione como apache por lo menos: que puedas arrancarla, pararla, reiniciarla, ver su estado, acceder a su log, que se reinicie si se produce un error, etc etc etc.

Busque por Internet y leí un montón de artículos y foros que te dicen como montartelo: haciendo scripts en /etc/init.d y combinándolo con monit para reiniciarlo si se cae, Usando Upstart, lanzando la aplicación con “node miapp.js &” (proceso en background pero es la peor solución que leí en años), y alguna que otra mas.

La mas razonable fue la de Upstart, aunque ninguna de las soluciones fue bastante clara o completa como para copiar, pegar y arrancar. Por eso hice este script que toma en cuenta todo lo que hace falta para montar tu app como un servicio:

description "Demonio para mi aplicación en Node.js"
author "Capy - http://ecapy.com"
env LOG_FILE=/var/log/node/miapp.log
env APP_DIR=/var/node/miapp
env APP=app.js
env PID_NAME=miapp.pid
env USER=www-data
env GROUP=www-data
env POST_START_MESSAGE_TO_LOG="miapp ha sido iniciada."
env NODE_BIN=/usr/local/bin/node
env PID_PATH=/var/opt/node/run
env SERVER_ENV="production"
######################################################
# A partir de aquí no debería hacer falta tocar nada #
######################################################
#Nuestro proceso espera hasta que el sistema este cargado
start on runlevel [2345]
#Y se detiene cuando el sistema se apague
stop on runlevel [016]
#Levanta el proceso automáticamente si se muere:
respawn
#limitamos el "respawn" a 99 veces con un timeout de 5s para que no intente levantar el proceso infinitamente.
respawn limit 99 5
pre-start script
    #Necesitamos asegurarnos que el path del pid exista antes de arrancar el proceso.
    mkdir -p $PID_PATH
    mkdir -p /var/log/node
end script
script
	#Seteamos NODE_ENV para que nuestra app se ejecute en modo production, development, test, etc.
	export NODE_ENV=$SERVER_ENV
	#El siguiente comando es el que realmente arranca el proceso:
	#Utiliza el usuario y grupo www-data (--chuid)
	#Asigna un pid y lo crea si no existe (--make-pidfile y --pidfile)
	#Cambia el directorio de ejecución a donde esté nuestra app de node (--chdir)
	#Ejecuta la app (--exec)
	#Envía cualquier output que genere nuestra app al log (>> $LOG_FILE 2>&1)
    exec start-stop-daemon --start --chuid $USER:$GROUP --make-pidfile --pidfile $PID_PATH/$PID_NAME --chdir $APP_DIR --exec $NODE_BIN -- $APP >> $LOG_FILE 2>&1
end script
post-start script
	echo $POST_START_MESSAGE_TO_LOG >> $LOG_FILE
end script

Puede parecer un poco largo, pero si lo lees detenidamente vas a ver que es bastante concreto:

  1. Autor y descripción: son parte básica de un script Upstart
  2. Variables de configuración para que no tengas que meterte entre el código para ajustar el script para cada nueva app que crees.
  3. Cuerpo del script.

Acá esta el mismo script sin comentarios:

description "Demonio para mi aplicación en Node.js"
author "Capy - http://ecapy.com"
env LOG_FILE=/var/log/node/miapp.log
env APP_DIR=/var/node/miapp
env APP=app.js
env PID_NAME=miapp.pid
env USER=www-data
env GROUP=www-data
env POST_START_MESSAGE_TO_LOG="miapp ha sido iniciada."
env NODE_BIN=/usr/local/bin/node
env PID_PATH=/var/opt/node/run
env SERVER_ENV="production"
######################################################
start on runlevel [2345]
stop on runlevel [016]
respawn
respawn limit 99 5
pre-start script
    mkdir -p $PID_PATH
    mkdir -p /var/log/node
end script
script
    export NODE_ENV=$SERVER_ENV
    exec start-stop-daemon --start --chuid $USER:$GROUP --make-pidfile --pidfile $PID_PATH/$PID_NAME --chdir $APP_DIR --exec $NODE_BIN -- $APP >> $LOG_FILE 2>&1
end script
post-start script
	echo $POST_START_MESSAGE_TO_LOG >> $LOG_FILE
end script

Uso:

Por cada aplicación en nodejs que quieras montar tenes que crear un archivo en /etc/init/. El nombre del archivo tiene que terminar en .conf. por ejemplo miapp-service.conf. Una cosa importante es que el servicio que estas creando se llama como el archivo (sin el .conf), por lo que en nuestro ejemplo se va a llamar miapp-service.

Dentro de /etc/init/miapp-service.conf pegas el script y personalizas todo lo que haya hasta la linea divisoria.

Un par de aclaraciones:
env APP=app.js define el nombre del “index” de tu aplicación, y por lo general se usan o app.js o server.js. Pon el nombre de tu app sin el path hasta ella. Si tu aplicación lleva parámetros podes encerrar en comillas dobles algo asi como “env APP=app.js -extrasettings ../settrings.json”
env APP_DIR=/var/node/miapp el path hasta tu aplicación
env PID_NAME=miapp.pid pon el nombre que quieras, pero que sea único. por ejemplo, si tu app es una pagina web pon el nombre de tu pagina “mipaginaweb_com.pid” o algo así.
env USER=www-data y env GROUP=www-data no sería muy responsable usar root para ejecutar tu aplicación salvo que esta si que necesite estar en root, pero en el caso de que sea una pagina web, usa el usuario y grupo www-data así podes unificar criterios. Es solo una sugerencia, yo para mi app uso www-data aunque podes usar el grupo y usuario que te parezca mejor.
POST_START_MESSAGE_TO_LOG es solo un mensaje que se envía al log de la app cuando esta arranca.
NODE_BIN indica donde esta ubicado node, por lo general está en /usr/local/bin/node aunque si no estuviera allí podes cambiar este parámetro.
env SERVER_ENV=”production” Posiblemente tu aplicación web utilice entornos de “development“, “test” y “production“. Bien, especificalo acá.

El resto del script está comentado en código así que no añado nada.

Cuando hayas acabado ya vas a disponer de tu servicio y tratarlo como cualquier otro:

start miapp-service
stop miapp-service
restart miapp-service
status miapp-service

Espero que les sirva.

Chau!

Node.js

req.flash() en express 3

A partir de la versión 3 de http://expressjs.com/ framework req.flash() fue quitado del core ya que estrictamente hablando, ésta funcionalidad no es “core”.

No pasa nada, seguimos teniendo los mensajes flash pero en un modulo aparte:

Para instalarlo:

npm install connect-flash

O bien lo agregas a tu proyecto expressjs dentro de las dependencias y lo actualizas con npm:

{
    "name": "application-name",
    "version": "0.0.1",
    "scripts": {
        "start": "node app"
    },
    "dependencies": {
        "express": "3.1.0",
        "connect-flash": "*"
    }
}
path/a/tu/app$: npm update

A partir de allí, su uso sigue siendo el mismo que en versiones anteriores:

Cargamos el modulo:

app.configure(function () {
    app.use(express.session());
    //flash(); SIEMPRE VA ENTRE express.session() Y app.router
    app.use(flash());
    app.use(app.router);
});

Y ya lo podemos usar. Por ejemplo para indicar a nuestro usuario que ha puesto mal sus datos de login:

app.post('/user/login', function(req, res){
  req.flash('error', 'Tu usuario o contraseña están mal!')
  res.redirect('/user/login');
});
app.get('/user/login', function(req, res){
 res.render('index', { messages: req.flash('info') });
});
Druplicon

Entidades en Drupal: 2) Trabajar con la entidad

En el capitulo anterior definimos una entidad, pero solo eso, no hacia nada. Ahora vamos a ver como interactuar con ella.

Hoy vamos a conocer las 5 operaciones mas comunes que se le suelen hacer a una entidad:

  • crear
  • guardar
  • cargar
  • actualizar
  • borrar

Tenemos dos formas de hacer esto. una es usando funciones y otra usando el controlador directamente. En este articulo vamos a usar el controlador.
Las funciones son solo otra forma de tratar con las entidades. y queda en el gusto de cada uno usar controlador o funciones.

NOTA sobre las funciones para entidades: Drupal provee entity_load(), entity_label() y entity_uri() mientras que Entity API agrega las que faltan: entity_save(), entity_create(), entity_delete(), entity_revision_delete(), entity_view() y entity_access() entre otras.
Este es uno de los motivos por el cual se creó Entity API. Faltaban funcionalidades a la hora de tratar con entidades.

Crear

<?php
$datos = array('nombre' => "ejemplo");
$controller = entity_get_controller('laEntidad');
$entidad = $controller->create($datos);

Es simple de ver. Cargamos el controlador de la entidad y creamos una.
Si cabe aclaremos un poco “$controller = entity_get_controller(‘laEntidad’);“: Pedimos a Drupal que nos de el controlador de la entidad “laEntidad”.

NOTA: entity_get_controller() instancia el controlador de nuestra entidad y lo cachea, así que pueden pedirlo una o mil veces, que no va a impactar en la performance del request actual.

Guardar

<?php
//retorna los mismos estados que drupal_write_record()
$saved = entity_get_controller('laEntidad')->save($entidad);

La única diferencia con el caso anterior es que en lugar de asignar el controlador a una variable, la hemos usado al vuelo.
$entidad es el objeto que creamos antes.

Cargar

<?php
$entities = entity_get_controller('laEntidad')->load($ids);

->load() siempre nos devuelve un array
$ids es un array de entityID.

Actualizar

Supongamos que sabemos que el ID de nuestra entidad es el 11:

<?php
$entities = entity_get_controller('laEntidad')->load(array(11));
$entidad = $entities[11];
$entidad->nombre = "nombre cambiado";
entity_get_controller('laEntidad')->save($entidad);

Borrar

<?php
entity_get_controller('laEntidad')->delete(array(1, 2, 3, 4));

Donde el array que se le pasa es un listado de los entityID que queremos borrar.
NOTA: el método ->delete() no devuelve nada.

Eso es todo. Para acabar queda comentar que el controlador que nos proporciona Entity API tiene mas métodos bastante útiles y que les recomiendo revisar. Estos están en el archivo “entity.controller.inc” del modulo (busquen la clase “EntityAPIController”).

Chau!

Druplicon

Drupal 7: Obtener el valor del field de una entidad

Como ya sabemos de sobra, en Drupal 7 todo es una entity (aka entidad). Los nodos son entidades, los comentarios son entidades, las taxonomias, los usuarios, todo es una entidad, y las entidades usan fields, y obtener el valor de un field de una entidad programaticamente es algo que no suele estar muy claro.

Hoy vamos a ver dos formas de obtener el valor de un field en una entidad.

Nuestro conejillo de indias: una entidad User que tiene un field llamado “field_apellidos“.

La primer forma de obtener el valor que guarda “field_apellido” es usando la API de drupal directamente:

<?php
$user = user_load(1);
$apellidos = field_get_items('user', $user, 'field_apellidos');
echo $apellidos[0]["value"];
?>

Y en el caso de que sea de múltiples valores:

<?php
$user = user_load(1);
$muchos_apellidos = field_get_items('user', $user, 'field_apellidos');
foreach($muchos_apellidos as $apellido){
    $apellidos[] = $apellido["value"];
}
$apellidos = trim(implode(" ", $apellidos));
?>

La segunda forma es usando Entity API (y para quien no lo conozca créanme que es tan necesario como ctools, views o panels si te dedicas a la programación en Drupal 7):

<?php
$user = user_load(1);
$entidadUsuario = entity_metadata_wrapper('user', $user);
$apellidos = $entidadUsuario->field_apellidos->value();
echo $apellidos;
?>

Y en el caso de que sea de múltiples valores:

<?php
$user = user_load(1);
$muchos_apellidos = $entidadUsuario->field_apellidos->value();
$apellidos = trim(implode(" ", $muchos_apellidos));
?>

Nota final: Solo con hacer user_load() ya tenes disponibles el field_apellidos, pero no es una practica recomendada accederlo directamente.

Chau!