Archivo de la etiqueta: php

Detectar problemas de memoria en PHP


echo "Memory after attachment: ".memory_get_usage(true).PHP_EOL;
$attachmentId = pods_attachment_import(LODGE_FEATURE_PHOTOS_FOLDER.$image, $lodge["ID"], true);
echo "Memory before attachment: ".memory_get_usage(true).PHP_EOL;

Poniendo varias de estas líneas en el código podemos saber qué llamada es la que nos está consumiendo memoria. Se empieza por dividir el código en partes “sospechosas” y luego en el log vamos viendo entre cuáles se hizo la diferencia de memoria. Ejemplo:

Memory before attachment: 47972352
Memory after metadata: 47972352

Está claro que ahí no hay un problema de memoria.

 

El rey de Internet

PHP sigue siendo el rey del desarrollo web. Esta nota lista una o dos de las varias ventajas que sigue teniendo sobre Ruby, Python, Java, etc. y el mercado al que apunta:

http://blog.samuellevy.com/post/41-php-is-the-right-tool-for-the-job-for-all-the-wrong-reasons.html

Destaco uno de los últimos comentarios, donde dice que PHP es uno de los pocos (o quizás el único) lenguajes destinados a hacer exclusivamente preprocesamiento de páginas web. Ruby fue diseñado como lenguaje de scripting, y después se usó para web development. PHP fue diseñado para preprocesar páginas desde sus inicios.

Programación funcional en PHP

Al parecer, todos los lenguajes de programación están incorporando características funcionales (Java es otro ejemplo). Este es un breve repaso de las características funcionales de PHP, agregadas en las últimas versiones.

Asignar una función a una variable


<?php

$func = function($message) {

  if ($message) {
    echo $message."\n";
  } else {
    echo "This is a function\n";
  }
}; // nótese que el ';' al final de esta llave es necesario!

Diferentes formas de llamar a la función


call_user_func($func);
$func('Custom message');
call_user_func($func, 'Custom message 2');

Funciones lambda / anónimas, in-line

function func1($items, $func2) {
 foreach($items as $item) {
    call_user_func($func2, $item);
 }
}

$items = array('item1', 'item2', 'item3');
 func1($items, function($item) {
echo $item."\n";
} );

Closures

function constantSum($par1, $par2) {
    return function($number) use ($par1, $par2) {
        return $number + $par1 + $par2;
    };
}

$func = constantSum(2, 3);
// 2 + 3 + 5 = 10
echo $func(5)."\n";

Los argumentos se pasan por valor, pero pueden ser pasados por referencia

Extraído de [https://wiki.php.net/rfc/closures]

$x = 1;
$lambda1 = function () use ($x) {
    $x *= 2;
};
$lambda2 = function () use (&$x) {
    $x *= 3;
};
$lambda1 ();
var_dump ($x); // gives: 1
$lambda2 ();
var_dump ($x); // gives: 3

Invocar objetos como si fueran funciones

Ahora todos los objetos pueden ser funciones! Sólo necesitás implementar el método __invoke()

class ObjectOrFunction {
    public function __invoke() {
        echo "I'm being invoked as a function... what I am??\n";
    }
}
$obj = new ObjectOrFunction();
$obj();

PHP, IMAP y encoding

Hoy sí que estuve renegando con los encoding y las funciones IMAP de PHP. El problema es que hay dos encodings, uno es el encoding de caracteres del body (UTF-8, ISO, etc.) y otro el encoding “quotable string” que es una especie de encoding de transporte. El tema es que para lograr, por ejemplo, que los mails que obtenemos de un servidor vengan en UTF-8 tenemos que hacer toda esta magia:


private function _get_plain_text_email_body($inbox, $email_number) {
 $st = imap_fetchstructure($inbox, $email_number);

 $body = null;
 $is_html = false;

 if (!empty($st->parts)) {
 for ($i = 0, $j = count($st->parts); $i < $j; $i++) {
 $part = $st->parts[$i];
 if ($part->subtype == 'PLAIN') {
 $body = imap_fetchbody($inbox, $email_number, $i+1);
 $part = $st->parts[$i+1];
 break;
 } elseif ($part->subtype == 'HTML') {
 $body = imap_fetchbody($inbox, $email_number, $i+1);
 $part = $st->parts[$i+1];
 $is_html = true;
 // No break - keep looking for PLAIN part
 }
 }
 } else {
 // TODO: implementar el checkeo de encoding cuando los mails vienen SOLO en texto plano o SOLO en HTML
 if ($st->subtype == 'PLAIN') {
 $body = imap_body($inbox, $email_number);
 } elseif ($st->subtype == 'HTML') {
 $body = imap_body($inbox, $email_number);
 $is_html = true;
 }
 }

 $body = imap_qprint($body);
 $charset = 'UTF-8';

 if(!empty($part->parameters)){
 for ($k = 0, $l = count($part->parameters); $k < $l; $k++) {
 $attribute = $part->parameters[$k];
 if(strtolower($attribute->attribute) == 'charset'){
 $charset = $attribute->value;
 }
 }
 }
 echo "Body's character encoding: $charset";

 $bodytext = mb_convert_encoding($body, 'UTF-8', $charset);

// Probablemente querramos implementar un método para evitar tener contenido HTML en los mails.
//if ($is_html){
//$bodytext = convert_html_to_text($bodytext);
//}
 return $bodytext;
 }

De donde saqué parte de la solución: http://stackoverflow.com/questions/10462212/mail-reading-in-php-with-imap

Enviar mails con PyroCMS

PyroCMS tiene su propia forma de enviar mails. Usa unos templates guardados en la base de datos. Así se manda un mail en PyroCMS:

  Events::trigger('email', array(
            'slug' => 'messaging_email',
            'from' => 'myemailaddress@mydomain.com',
            'reply-to' => 'myemailaddress@mydomain.com',
            'to' => $to,
            'subject' => $email_data['subject'],
            'body' => $email_data['body']
        ), 'array');

Para crear un template en la base de datos, es ir a Design / Email Templates y agregar un template. Este template tiene que tener el mismo “slug” que el que se indica en el trigger.