Archivo de la categoría: PHP

PHP

Snippet: Verificar si una fecha está dentro de un rango de fechas en PHP.

La saqué de la documentación de PHP creo recordar, y a alguien le puede ser útil ;)

<?php
/**
 * Verifica que una fecha esté dentro del rango de fechas establecidas
 * @param $start_date fecha de inicio
 * @param $end_date fecha final
 * @param $evaluame fecha a comparar
 * @return true si esta en el rango, false si no lo está
 */
function check_in_range($start_date, $end_date, $evaluame) {
    $start_ts = strtotime($start_date);
    $end_ts = strtotime($end_date);
    $user_ts = strtotime($evaluame);
    return (($user_ts >= $start_ts) && ($user_ts <= $end_ts));
}

Ejemplo de uso:

<?php
$start_date = '2010-06-01';
$end_date = '2010-06-30';
$fecha_a_evaluar = '2010-06-15';
if (check_in_range($start_date, $end_date, $fecha_a_evaluar)) {
    echo "estas en rango";
} else {
    echo "fuera de rango";
}
Druplicon

Múltiples drupal_execute() en Drupal 6 es imposible… O NO :)

El otro día Nicolas, un amigo y compañero de trabajo se quebró la cabeza con este tema. La cosa debía ser mas bien simple, en un bucle tenia que procesar una serie de datos, rellenar un formulario programaticamente y darle un drupal_execute() para que se creen una cantidad de nodos…

Eso fue de todo menos simple. Resulta que el que programó la función drupal_validate_form() se olvidó que podía caber la posibilidad de que alguien quisiera llamarlo en bucle, y no se le ocurrió mejor idea que cachear la primera validación y cortar cualquier otra dentro de un mismo request.

La solución por la que se decantó Nicolas fue la de crear una implementación propia de ciertas funciones. Antes que digan algo, recomiendo que se den una vuelta por los foros de Drupal y se convensan de la imposibilidad de aplicar una solución mejor.
De hecho esta solución es bastante buena, porque no tenes mas que poner el código en tu modulo, e invocar la versión modificada de drupal_execute().

La modificación se tuvo hacer mucho antes de llegar a drupal_validate_form() para poder tomar control sobre la misma, por lo que en esta modificación hubo que reemplazar funciones de:
drupal_execute() -> drupal_execute_no_cache()
drupal_process_form() -> drupal_process_form_no_cache()
drupal_validate_form() -> drupal_validate_form_no_cache();

los archivos modificados son estos:

/**
 * @see drupal_execute
 * Unica diferencia, utiliza métodos propios (_no_cache) para evitar el cacheo de validaciones
 */
function drupal_execute_no_cache($form_id, &$form_state) {
    $args = func_get_args();
    // Make sure $form_state is passed around by reference.
    $args[1] = &$form_state;
    $form = call_user_func_array('drupal_retrieve_form', $args);
    $form['#post'] = $form_state['values'];
    drupal_prepare_form($form_id, $form, $form_state);
    drupal_process_form_no_cache($form_id, $form, $form_state);
}
/**
 * @see drupal_process_form
 *
 * @param $form_id
 * @param $form
 * @param $form_state
 */
function drupal_process_form_no_cache($form_id, &$form, &$form_state) {
    $form_state['values'] = array();
    $form = form_builder($form_id, $form, $form_state);
    // Only process the form if it is programmed or the form_id coming
    // from the POST data is set and matches the current form_id.
    if ((!empty($form['#programmed'])) || (!empty($form['#post']) && (isset($form['#post']['form_id']) && ($form['#post']['form_id'] == $form_id)))) {
        $form_state['process_input'] = TRUE;
        drupal_validate_form_no_cache($form_id, $form, $form_state);
        // form_clean_id() maintains a cache of element IDs it has seen,
        // so it can prevent duplicates. We want to be sure we reset that
        // cache when a form is processed, so scenerios that result in
        // the form being built behind the scenes and again for the
        // browser don't increment all the element IDs needlessly.
        form_clean_id(NULL, TRUE);
        if ((!empty($form_state['submitted'])) && !form_get_errors() && empty($form_state['rebuild'])) {
            $form_state['redirect'] = NULL;
            form_execute_handlers('submit', $form, $form_state);
            // We'll clear out the cached copies of the form and its stored data
            // here, as we've finished with them. The in-memory copies are still
            // here, though.
            if (variable_get('cache', CACHE_DISABLED) == CACHE_DISABLED && !empty($form_state['values']['form_build_id'])) {
                cache_clear_all('form_' . $form_state['values']['form_build_id'], 'cache_form');
                cache_clear_all('storage_' . $form_state['values']['form_build_id'], 'cache_form');
            }
            // If batches were set in the submit handlers, we process them now,
            // possibly ending execution. We make sure we do not react to the batch
            // that is already being processed (if a batch operation performs a
            // drupal_execute).
            if ($batch =& batch_get() && !isset($batch['current_set'])) {
                // The batch uses its own copies of $form and $form_state for
                // late execution of submit handers and post-batch redirection.
                $batch['form'] = $form;
                $batch['form_state'] = $form_state;
                $batch['progressive'] = !$form['#programmed'];
                batch_process();
                // Execution continues only for programmatic forms.
                // For 'regular' forms, we get redirected to the batch processing
                // page. Form redirection will be handled in _batch_finished(),
                // after the batch is processed.
            }
            // If no submit handlers have populated the $form_state['storage']
            // bundle, and the $form_state['rebuild'] flag has not been set,
            // we're finished and should redirect to a new destination page
            // if one has been set (and a fresh, unpopulated copy of the form
            // if one hasn't). If the form was called by drupal_execute(),
            // however, we'll skip this and let the calling function examine
            // the resulting $form_state bundle itself.
            if (!$form['#programmed'] && empty($form_state['rebuild']) && empty($form_state['storage'])) {
                drupal_redirect_form($form, $form_state['redirect']);
            }
        }
    }
}
/**
 * @see drupal_validate_form
 *
 * @param $form_id
 * @param $form
 * @param $form_state
 */
function drupal_validate_form_no_cache($form_id, $form, &$form_state) {
    // If the session token was set by drupal_prepare_form(), ensure that it
    // matches the current user's session.
    if (isset($form['#token'])) {
        if (!drupal_valid_token($form_state['values']['form_token'], $form['#token'])) {
            // Setting this error will cause the form to fail validation.
            form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.'));
        }
    }
    _form_validate($form, $form_state, $form_id);
}

Como dije. Copienlo a su módulo y usen drupal_execute_no_cache() en lugar de drupal_execute().

debug

Configurar Xdebug en Xampp 1.7.3 con PHP 5.3.1

Si querés configurar Xdebug en linux puede interesarte el post “Instalar Xdebug en Ubuntu (cualquier versión)

Vayan a la carpeta en la que esta instalado Xampp y entren en la carpeta de PHP.
Abran php.ini y busquen:

;zend_extension = "\xampp\php\ext\php_xdebug.dll"

Quítenle el punto y coma del principio para descomentarlo (Habilitarlo).

Ahora solo queda configurar los parámetros de Xdebug:
Busquen ahora “[XDebug]“. Lo que ven por debajo de esta etiqueta es su configuración, como se que es una putada tener que andar leyendo y habilitando uno a uno les dejo una configuración funcional para que la usen. (Borren todo lo que hay por debajo de la etiqueta [xdebug] antes de pegar esta nueva configuración).

[XDebug]
xdebug.auto_trace = 0
xdebug.collect_includes = 1
xdebug.collect_params = 1
xdebug.collect_return = 1
xdebug.collect_vars = "On"
xdebug.default_enable = "On"
xdebug.dump.SERVER = REMOTE_ADDR,REQUEST_METHOD
xdebug.dump.SERVER = REMOTE_ADDR,REQUEST_METHOD
xdebug.dump_globals = 1
xdebug.dump_once = 1
xdebug.dump_undefined = 0
xdebug.extended_info = 1
xdebug.file_link_format = ""
xdebug.manual_url = "http://www.php.net"
xdebug.max_nesting_level = 100
xdebug.overload_var_dump = 1
xdebug.profiler_append = 0
xdebug.profiler_enable = 0
xdebug.profiler_enable_trigger = 0
xdebug.profiler_output_dir = "\xampp\tmp"
xdebug.profiler_output_name = "xdebug_profile.%p"
xdebug.remote_autostart = 1
xdebug.remote_enable = 1
xdebug.remote_handler = "dbgp"
xdebug.remote_host = "localhost"
xdebug.remote_mode = "req"
xdebug.remote_port = 9000
xdebug.show_exception_trace = 0
xdebug.show_local_vars = 0
xdebug.trace_output_dir = "\xampp\tmp"
xdebug.var_display_max_children = 256
xdebug.var_display_max_data = 512
xdebug.var_display_max_depth = 10

Listo, de acá en mas solo tienen que configurar su eclipse, netbeans, o lo que sea que usen.

Druplicon

Setear y recuperar fields de Apache Solr en Drupal (y PHP en general)

Voy a partir de la premisa de que ya tenemos un apache solr corriendo y un drupal con el modulo configurado.

Dicho lo anterior, se nos plantea la siguiente pregunta: ¿Cómo hago para tomar un dato relacionado a un nodo, se lo paso a solr para que lo indexe como un field en el documento de solr y luego lo recupero junto a los documentos/resultados de una búsqueda?

Aunque parezca mentira, es mas bien fácil de hacer, pero si les pasa como a mi, seguramente gasten una horita en conseguir este dato, porque no es un tema extensamente documentado Solr + Drupal.

1) Agregar un dato X a un field de un documento:

Para este primer paso apelamos al hook hook_apachesolr_update_index(). ¿que hace?, nos da la oportunidad de agregar o quitar información al documento que se esta por enviar a solr, y ya puestos, nos manda el nodo del cual se extrajo la información para sacar de ahi (o de cualquier otro lado) información extra. (esto nos evita tener que hacer un node_load() ).

/**
 * Implementarion of hook_apachesolr_update_index()
 * */
function mimodulo_apachesolr_update_index(&$documentoSolr, $node) {
    //Por aca obtenemos informacion extra
    $documentoSolr->addField('is_apellido_de_creador', $apellido_creador);
    $documentoSolr->addField('is_edad_creador', $edad_creador);
}

Arriba no hay mucho que aclarar, básicamente por medio del método addField() seteo un par de  nuevos field (is_apellido_creador y is_edad_creador) asignandoles un valor que anteriormente habre recogido de algun lugar.

NOTA: Mucha atención al prefijo que usé en los nombres de los field (“is_“). No lo hice por que si, sino porque en el schema.xml los creadores del modulo de drupal han predefinido una serie de prefijos para las filas dinámicas como las que estamos creando. Dicho de otra forma, si no usamos uno de los prefijos definidos en schema.xml, los field no se van a indexar.

2) Pedir un field a Solr:

Solr puede tener en un documento cualquier cantidad de fields almacenados en su interior, lo que no quiere decir que en cada resultado de una busqueda se vayan a incluir todos estos field… imaginarán que la performance no se basa justamente en la premisa de “mandame todo lo que tengas que ya veré yo que es lo que me hace falta“. Mas bien hay que decirle a Solr en la consulta, que es lo que necesitas recibir de un documento de la siguiente manera:

/**
 * Implementarion of hook_apachesolr_prepare_query()
 */
function mimodulo_apachesolr_prepare_query(&$query, &$params, $caller) {
    //concatenamos los nuevs campos a la peticion.
    $params ["fl"] = $params ["fl"] . ", is_apellido_de_creador, is_edad_de_creador";
}

Como pueden ver, lo que hago aquí es sumarle a “fl” dos campos más. “fl” es justamente la clave que almacena todos los field que le vamos a pedir a Solr.

Listo, ya podemos setear y recuperar fields. Solo queda que modifiques la pagina de resultados para poder imprimir cada uno de los nuevos field que recibiste, pero esa es otra historia.

Concepto original extraído de:

http://www.agileapproach.com/blog-entry/filtering-apache-solr-search-results-based-drupal-user-permissions

PHP

Recoger atributos con SimpleXML

Digamos que tengo el siguiente xml:

<libros>
    <libro>
    <autor edad="62">Stephen King</autor><autor>
    </autor></libro>
</libros>

Para recoger el valor del atributo “edad” simplemente XD tenemos que hacer lo siguiente

<?php
$libros = simplexml_load_file('libros.xml');
$edad = $libros->libro->autor->attributes()->edad;
PHP

Pasar un array asociativo a formato clave valor en una URL con PHP

Rápido y cortito. Si lo que necesitan es preparar una serie de variables dentro de un array y después quieren serializarlo en formato url, no tienen más que hacer lo siguiente:

Extraído de php.net

<?php
$data = array(
    'foo' => 'bar',
    'baz' => 'boom',
    'cow' => 'milk',
    'php' => 'hypertext processor'
);
echo http_build_query($data); //la magia en esta linea
//nos imprime:  foo=bar&baz=boom&cow=milk&php=hypertext+processor

Los amantes de Java, Python, .NET y demases dirán lo que sea de PHP, pero cuando ves estas cosas no te quedan dudas que PHP es un RAD de puta madre!.

PD: para no parecer un purista, tengo que decir que Python me encanta y Groovy tanbien, pero cada cosa para lo que es :)

PHP

Problemas de codificación con MySQL y PHP

No había tenido un problema asi nunca, pero en uno de los últimos proyectos se dio.

Al recuperar unos registros de la base de datos ya me estaban llegando mal codificados. Así como áóñ.

Buscando y buscando por todos lados encontré una serie de soluciones, y la combinación resultante para solucionar este problemita fue:

  • Cambiar la codificación del documento PHP a UTF-8
  • En Mysql revisar que las tablas tengan la codificación utf8_spanish_ci
  • Antes de <head></head> poner <meta http-equiv=”Content-type” content=”text/html; charset=utf-8″ />
  • Todo lo anterior es preventivo. Pero lo que realmente me dio el resultado correcto en las consultas fue poner lo siguiente entes de lanzar la consulta (en la linea que esta justo encima del mysql_db_query()):
    mysql_query(“SET NAMES ‘utf8′”);

Y listo, ya me salían bien los caratéres especiales.

PHP

Instalar XDebug en Windows 7 y XAMPP

Windows 7 es claramente el paso mas firme que ha dado Microsoft en sus ultimos 9 años con lo que respecta a su principal S.O. Y soy de los que  saben cuando han de aceptar que algo que odias ha mejorado.

Ciertamente me gusta este Windows. Básicamente vuela y es todo lo que XP no puede ser por ser tan viejo.

Lo único que me impedía cambiar definitivamente era que no podía debugear con Xdebug, y no es poco decir cuando trabajas con el.

Peeeeeeeero, gracias a Diembo que dejó un post mas que concreto pero letalmente eficaz en ihostnz, hoy puedo decir que Windows 7 pasa a ser mi sistema operativo principal por el resto de… bueno hasta que haya algo mejor.

A lo nuestro. Según nuestro amigo los pasos a seguir son:

  1. Download XAMPP 1.7.2 from sourceforge.net/projects/xampp/files/XAMPP%20Windows/1.7.2/xampp-win32-1.7.2.exe/download
  2. Install
  3. Download php_xdebug-2.0.5-5.3-vc6.dll from xdebug.org/download.php
  4. Place it in C:\xampp\php\ext
  5. Edit C:\xampp\php\php.ini add:zend_extension = “C:\xampp\php\ext\php_xdebug-2.0.5-5.3-vc6.dll”[xdebug]
    xdebug.remote_enable=on
    xdebug.remote_host=127.0.0.1
    xdebug.remote_port=9000
    xdebug.remote_handler=”dbgp”
  6. Enjoy!

Que traducido por medio de algoritmos muy complejos nos da algo como esto:

  1. Descargar la ultima versión de XAMPP
  2. Instalarlo
  3. Descargar PHP 5.3 VC6 TS (32 bit)
  4. Poner el archivo descargado (php_xdebug-2.1.1-5.3-vc6.dll) en C:\xampp\php\ext o donde este instalado tu Xampp.
  5. Editar C:\xampp\php\php.ini y añadir al final de todo:
    zend_extension = "C:\xampp\php\ext\php_xdebug-2.1.1-5.3-vc6.dll" 
    [xdebug] 
    xdebug.remote_enable=on 
    xdebug.remote_host=127.0.0.1 
    xdebug.remote_port=9000 
    xdebug.remote_handler="dbgp" 

    Ojo, no toquen nada mas, a pesar de que van a ver que en php.ini hay configuraciones de xdebug, no hay que tocarlas.

  6. Disfrutar!

Es tan simple que da miedo, y lo peor de todo es que desde que tengo W7 nunca lo había podido hacer funcionar.

Druplicon

Copié una instalación de Drupal a Linux y solo puedo navegar en la página principal. El resto me devuelve “Not Found”

Una vez más espero que esto pueda ahorrarle tiempo a mas de uno.

Digamos que por algún motivo de la vida, comenzamos un proyecto desarrollando en Drupal 6 sobre Windows.

Digamos que se nos da por corregir nuestro craso error y nos llevamos la página a nuestro entorno Linux. Exportamos la DB, copiamos la instalación, importamos, damos permisos a lo que hay que darle permiso… genial, se ve, naveguemos… OMG! dirán ustedes, seguirán con un WTF! para asentir nuestro asombro cuando nos damos cuenta que solo se puede ver la pagina principal….

Después de respirar hondo tres o cuatro veces, van a hacer lo mismo que hice yo. Buscar en Google. Por eso están leyendo esto ;)

Resulta que en Windows teníamos activada las URL aliases, y claro, en Linux no, y es por eso que no se puede ir mas allá de la pagina principal básicamente.

Solución: Hacer las cosas bien desde un principio y desarrollar todo en linux activar los rewrites con:

sudo a2enmod rewrite

Además tenemos que AllowOverride este en All. Para eso vamos a tirar el siguiente comando (para instalaciones Ubuntu por lo menos)

sudo gedit /etc/apache2/sites-enabled/000-default

Donde encontremos:

<Directory /ruta/hasta/mi/carpeta/raiz/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>

Por ultimo debemos recargar Apache:

sudo /etc/init.d/apache2 force-reload

Listo, ya deberíamos poder navegar correctamente por nuestra instalación de Drupal.
Una ultima cosa a considerar, y que puede provocar el mismo error, es que se hayan pasado de alto copiar .htaccess que por defecto está oculto en sistemas Linux. En ese caso, si lo están copiando en red por medio de Nautilus, presionen la combinación ctrl+h para mostrar archivos ocultos. Si lo hacen desde Filezilla vayan al menú “Servidor” -> “Forzar mostrar archivos ocultos”.

PHP

Snippet para limpiar palabras en PHP

Es más un apunte para mi que para alguien más, aunque a cualquiera que quiera limpiar una cadena para almacenar un nombre de usuario por ejemplo, le va a ser util.

$patronBusqueda = array(
    "\\",
    "ª",
    "º",
    "-",
    "~",
    "#",
    "@",
    "|",
    "!",
    "\"",
    "·",
    "$",
    "%",
    "&",
    "/",
    "(",
    ")",
    "?",
    "'",
    "¡",
    "¿",
    "[",
    "^",
    "`",
    "]",
    "+",
    "Ç",
    "}",
    "{",
    "¨",
    "´",
    "ñ",
    "Ñ",
    ">",
    "<",
    ";",
    ",",
    ":",
    ".",
    " ",
    "á",
    "é",
    "í",
    "ó",
    "ú",
    "Á",
    "É",
    "Í",
    "Ó",
    "Ú"
);
 
$nombre_usuario = str_replace($patronBusqueda, "", "cadena con caracteres especiales");