martes, 8 de mayo de 2012

Funciones : Mail_() - Error_log() - Pear_mail()



FUNCION MAIL()

Para enviar emails sencillos en modo texto el uso de la función mail() es sin lugar a dudas lo más cómodo. Su uso es el siguiente:

mail('direccion@del.destinario.com','Asunto','Mensaje');
 
Devuelve TRUE en caso de éxito y FALSE en caso contrario. También podemos pasarle cabeceras adicionales como cuarto parámetro, esto puede ser útil, por ejemplo, para enviar mensajes HTML usando mail() pero a la mínima q necesites enviar emails un poco más complejos es recomendable usar las PEAR.

FUNCION ERROR_LOG()

Para todos aquellos emails de debug o alertas internas de nuestro software podemos usar error_log(). Con esta función podemos hacer log a distintos destinos: el log del sistema, un archivo, la conexión de debug y también enviar por email. Por ejemplo para enviarnos por email información acerca de una exception q nos salta en nuestro código:

try {
  // código con posibles errores
} catch (Exception $e) {
  $msg = 'ERROR #'.$e->getCode()."\n";
  $msg .= $e->getMessage()."\n";
  $msg .= print_r($e->getTrace(),true);
  @error_log($msg, 1, 'direccion@del.destinario.com');
}

CLASE PEAR MAIL_MINE

Como comentaba esta es una de las clases existentes para el envío de emails con soporte de extensiones MIME, lo que permite enviar HTML con imágenes, vídeo, archivos adjuntos, etc. Este es un ejemplo sencillo de como enviar un email HTML con su versión texto y con un archivo adjunto:

require_once 'Mail.php';
require_once 'Mail/mime.php';
$destinario = 'direccion@del.destinario.com';
$from = 'direccion@del.from.com';
$asunto = 'Asunto del mensaje';
$mensaje = '<html><head><title>'.$asunto.'</title></head>'."\n";
$mensaje .= '<body><p><h1>Hola</h1></body></html>';
$mime = new Mail_mime("\n");
$mime->setTXTBody (strip_tags($mensaje));
$mime->setHTMLBody($mensaje);
$mime->addAttachment('fichero_adjunto.zip', 'application/zip');
$body = $mime->get();
$hdrs = array('From' => $from, 'Subject' => $asunto);
$hdrs = $mime->headers($hdrs);
$mail =&Mail ::factory('mail');
$res = $mail->send($destinario, $hdrs, $body);
if (PEAR::isError($res)) echo 'error enviando el email';
 
Todos los métodos anteriormente descritos necesitan de un servidor de correo funcionando y las directivas de configuración del PHP correctamente fijadas. Si tienes un ISP un poco decente casi seguro q no tendrás ningún problema.
Una técnica alternativa a todos estos métodos y que no necesita de servidor de correo es usar sockets (función fsckopen()) para mandar nosotros mismos los mensajes desde nuestro código. Se trata de hacer desde PHP el trabajo q antes nos hacía el servidor. Esto, en general, no es recomendable ya q puede presentar serios problemas d rendimiento y gestión de errores (nunca funcionará mejor nuestro código PHP q unQmail:) y la única ventaja destacable q presenta, a parte de no necesitar d un servidor d correo, es disponer de un mayor control de lo que pasa cuando se envía el email. Podemos por ejemplo saber en el momento si el servidor del destinatario del correo existe y nos acepta el mensaje, etc... Aunque con los métodos descritos y leyendo los mensajes devueltos por el servidor de correo también puedes saber si todo va bien... como consejo, si tienes un servidor de correo úsalo.

Funciones Simples-Con Argumento -Include -Require


FUNCIONES DEFINIDAS POR EL USUARIO

Una función puede ser definida usando una sintaxis como la siguiente:


<?php
function foo($arg_1$arg_2/* ..., */ $arg_n)
{
    echo 
"Función de ejemplo.\n";
    return 
$valordevuelto;
}
?>

Cualquier código PHP válido puede aparecer dentro de una función, incluso otras funciones y definiciones de CLASES
Los nombres de las funciones siguen las mismas reglas que otras etiquetas de PHP. Un nombre de función válido comienza con una letra o guión bajo, seguido de cualquier número de letras, números, o guiones bajos. Como expresión regular se expresaría así: [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*.
Sugerencia

Las funciones no necesitan ser definidas antes de que se referencien, excepto cuando una función está condicionalmente definida como se muestra en los dos ejemplos de abajo.
Cuando una función está definida de una forma condicional como en los dos ejemplos mostrados, sus definiciones deben ser procesadas antes de ser llamadas.


<?php

$haceralgo 
true;

/* No podemos llamar a foo() desde aquí
   ya que no existe aún,
   pero podemos llamar a bar() */

bar();

if (
$haceralgo) {
  function 
foo()
  {
    echo 
"No existo hasta que la ejecución del programa llegue hasta mí.\n";
  }
}

/* Ahora podemos llamar de forma segura a foo()
   ya que $haceralgo se evaluó como verdadero */

if ($haceralgofoo();

function 
bar() 
{
  echo 
"Existo desde el momento inmediato que comenzó el programa.\n";
}

?>
 

 Funciones dentro de funciones

<?php
function foo() 
{
  function 
bar() 
  {
    echo 
"No existo hasta que se llame a foo().\n";
  }
}

/* No podemos llamar aún a bar()
   ya que no existe. */

foo();

/* Ahora podemos llamar a bar(),
   el procesamiento de foo()
   la ha hecho accesible. */

bar();

?>
 
Todas las funciones y las clases de PHP tienen ámbito global - pueden ser llamadas fuera de una función incluso si fueron definidas dentro, y viceversa.
PHP no soporta la sobrecarga de funciones, ni es posible 'desdefinir' ni redefinir funciones previamente declaradas.

Nota: Los nombres de las fuciones son insensibles a mayúsculas-minúsculas, por lo que es una buena idea llamar a las funciones tal y como aparecen en sus declaraciones.
El numero variable de argumentos y losargumentos predeterminados están soportados por las funciones. En PHP es posible llamar a funciones recursivas. Sin embargo, evite las llamadas a funciones/métodos recursivos con más de 100-200 niveles de recursividad ya que pueden agotar la pila y causar la terminación del script actual. 
  
Funciones recursivas
 
<?php
function recursividad($a)
{
    if (
$a 20) {
        echo 
"$a\n";
        
recursividad($a 1);
    }
}
?>





FUNCIONES CON ARGUMENTOS CON VALOR Y REFERENCIA



Por defecto, los parámetros de una función se pasan por valor, de manera que, al cambiar el valor de un parámetro dentro de la función, no se ve modificado fuera de ella. Para permitir que dichos cambios se vean reflejados fuera de la función, hay que pasar los parámetros por referencia.
Para conseguir que un parámetro de una función siempre se pase por referencia, hay que anteponer un ampersand (&) al nombre del parámetro en la definición de la función:

Para pasar una variable por referencia a una función que no toma el parámetro por referencia por defecto, hay anteponer un ampersand (&) al nombre del parámetro en la llamada a la función:

Nota: Este procedimiento para pasar parámetros por referencia desde la llamada de la función ha quedado en desuso y provocará Warnings en las configuraciones por defecto de PHP.


Parámetros por defecto
Una función puede definir valores por defecto para los parámetros escalares. Estos valores serán asignados a los parámetros de la función en caso de que el número de parámetros en la llamada a la función sea inferior al número de parámetros en la definición de la función.
 
El código anterior produce la siguiente salida: 
Haciendo una taza de cappucino.
Haciendo una taza de espresso. 

Nota: El valor por defecto tiene que ser una expresión constante, y no una variable. En PHP 4.0 también es posible especificar unset como parámetro por defecto. Esto significa que el argumento no tomará ningún valor en absoluto si el valor no es suministrado.

Importante: Cuando se usan parámetros por defecto, estos tienen que estar a la derecha de cualquier parámetro sin valor por defecto; de otra manera las cosas no funcionarán de la forma esperada.
  
La salida del ejemplo anterior es: 

Veamos cómo sería el código correcto:


Devolver valores
Para que una función devuelva un valor se emplea la instrucción opcional return. Puede devolverse cualquier tipo de valor, incluyendo listas y objetos.
  
No es posible devolver múltiples valores desde una función, pero un efecto similar se puede conseguir devolviendo una lista, para ello se emplea la función de PHP list(), veamos un ejemplo:
    
El ejemplo anterior muestra por pantalla: 0,1,2,3

Funciones variable
PHP soporta el concepto de funciones variable, esto significa que si una variable tiene unos paréntesis añadidos al final, PHP buscará una función con el mismo nombre que la evaluación de la variable, e intentará ejecutarla.
 
El resultado es:



Librería de funciones PHP
En los apartados anteriores hemos estudiado las funciones definidas por el usuario, es decir, funciones creadas por el programador a medida de sus necesidades.
Pero hay que tener en cuenta que PHP cuenta con una extensa y enormemente útil librería de funciones  que debemos conocer y aprovechar al máximo con el fin de agilizar nuestro trabajo. Dada la gran cantidad de funciones predefinidas con las que cuenta PHP, resulta imposible estudiarlas en esta unidad por lo que las iremos estudiando a medida que las necesitemos.


INCLUDE

(PHP 4, PHP 5)
La sentencia include incluye y evalúa el archivo especificado.
La siguiente documentación también se aplica a require.
Los archivos son incluidos con base en la ruta de acceso dada o, si ninguna es dada, el include_path especificado. Si el archivo no se encuentra en el include_path , include finalmente verificará en el propio directorio del script que hace el llamado y en el directorio de trabajo actual, antes de fallar. El constructor include emitirá una advrtencia si no puede encontrar un archivo, éste es un comportamiento diferente al de require el cual emitirá un error fatal
Si una ruta es definida — ya sea absoluta (comenzando con una letra de unidad o \ en Windows o / en sistemas Unix/Linux) o relativa al directorio actual (comenzando con . o ..) — el include_path  será ignorado por completo. Por ejemplo, si un nombre de archivo comienza con ../, el interprete buscará en el directorio padre para encontrar el archivo solicitado.
Para más información sobre como PHP maneja la inclusión de archivos y la ruta de accesos para incluir, ver la documentación de include_path 
Cuando se incluye un archivo, el código que contiene hereda el ambito de las variables de la línea en la cual ocurre la inclusión. Cualquier variable disponible en esa línea del archivo que hace el llamado, estará disponible en el archivo llamado, desde ese punto en adelante. Sin embargo, todas las funciones y clases definidas en el archivo incluido tienen el ámbito global. 

Ejemplo básico de include

vars.php
<?php

$color 
'verde';
$fruta 'manzana';

?>

test.php
<?php

echo "Una $fruta $color"// Una

include 'vars.php';

echo 
"Una $fruta $color"// Una manzana verde

?>
 
Si la inclusión ocurre al interior de una función dentro del archivo que hace el llamado, entonces todo el código contenido en el archivo llamado se comportará como si hubiera sido definida dentro de esa función. Por lo tanto, seguirá el ámbito de las variables de esa función. Una excepción a esta regla son las constantes mágicas las cuales son evaluadas por el intérprete antes que ocurra la inclusión. 

Incluyendo dentro de funciones

<?php

function foo()
{
    global 
$color;

    include 
'vars.php';

    echo 
"Una $fruta $color";
}

/* vars.php está en el ámbito de foo() así que *
* $fruta NO está disponible por fuera de éste  *
* ámbito. $color sí está porque fue declarado *
* como global.                                 */

foo();                      // Una manzana verde
echo "Una $fruta $color";   // Una verde

?>
 
Cuando un archivo es incluido, el intérprete abandona el modo PHP e ingresa al modo HTML al comienzo del archivo objetivo y se reanuda de nuevo al final. Por esta razón, cualquier código al interior del archivo objetivo que deba ser ejecutado como código PHP, tendrá que ser encerrado dentro de etiquetas validas de comienzo y terminacion php.
Si las"envolturas URL_fopen" están activadas en PHP (las cuales lo están en la configuración predeterminada), se puede especificar el archivo a ser incluido usando una URL (vía HTTP u otra envoltura soportada - ver Protocolos y envolturas soportados para una lista de protocolos) en lugar de una ruta de acceso local. Si el servidor objetivo interpreta el archivo objetivo como código PHP, las variables se pueden pasar al archivo incluido usando una string de petición como la usada con HTTP GET. Esto no es, en estricto rigor, lo mismo que haber incluido el archivo y que haya heredado el ámbito de variables del archivo padre; el script realmente está siendo ejecutado en el servidor remoto y el resultado entonces se incluye dentro del script local.
Advertencia
Versiones de PHP para Windows anteriores a 4.3.0, no soportan el acceso remoto a archivos para esta función, no funcionará ni activando siquiera allow url fopen

 include por medio de HTTP

<?php

/* Este ejemplo asume que www.example.com está configurado para interpretar archivos
* .php y no archivos .txt. Además, aquí 'Funciona' quiere decir que las variables
* $foo y $bar están disponibles dentro del archivo incluido. */

// No funciona; file.txt no puede ser manejado por www.example.com como PHP
include 'http://www.example.com/file.txt?foo=1&bar=2';

// No funciona; busca por un archivo llamado 'file.php?foo=1&bar=2' en el
// sistema de archivos local.
include 'file.php?foo=1&bar=2';

// Si funciona.
include 'http://www.example.com/file.php?foo=1&bar=2';

$foo 1;
$bar 2;
include 
'file.txt';  // Funciona.
include 'file.php';  // Funciona.

?>

Advertencia de seguridad

El archivo remoto puede ser procesado en el servidor remoto (dependiendo de la extensión del archivo y del hecho de si el servidor remoto corre PHP o no) pero aun así tiene que producir un script PHP válido, porque será procesado en el servidor local. Si el archivo desde el servidor remoto debe ser procesado allá y entregar la salida solamente,readfile()es la mejor función para usar. De lo contrario, debe tenerse especial cuidado para asegurar que el script remoto produce un código válido y deseado.
Ver también archivos remotos, fopen() y file() para información relacionada.
Manejando retornos: Es posible ejecutar una sentencia retum dentro de un archivo incluido con el fin de terminar el procesamiento en ese archivo y volver a script que lo llamó. Además, es posible retornar valores desde los archivos incluidos. Se puede tomar el valor de la llamada "include" de la misma forma como se haría con una función normal. Esto no es, sin embargo, posible si se incluyen archivos remotos, a menos que la salida del archivo remoto tenga unas etiquetas vaidas de inico y terminacion de PHP (igual que con cualquier archivo local). Se pueden declarar la variables necesarias dentro de esas etiquetas y serán introducidas en el punto del archivo en el cual fue incluido.
Debido a que include es un constructor especial del lenguaje, los paréntesis no son necesarios en torno a su argumento. Se debe tener cuidado cuando se compara el valor de retorno. 

Comparando el valor de retorno de include

<?php
// no funciona, evaluado como include(('vars.php') == 'OK'), es decir include('')
if (include('vars.php') == 'OK') {
    echo 
'OK';
}

// si funciona
if ((include 'vars.php') == 'OK') {
    echo 
'OK';
}
?>



REQUIRE

(PHP 4, PHP 5)
require es idéntico a include excepto que en caso de fallo producirá un error fatal de nivel E_COMPILE_ERROR. En otras palabras, éste detiene el script mientras que include sólo emitirá una advertencia (E_WARNING) lo cual permite continuar el script.
Véase la documentación de include para más información.


<?php
// file and get, if you need to include a file.php?query_string.

function pinclude($file, $type, $get = null) {
    $p = explode('/', $file);
    $file = end($p);
    $dir = '';
    $n = count($p) - 1;

    for($i = 0; $i < $n; $i++)
        $dir .= $p[$i] . '/';

    if($get !== null) {
        $tmp = $_GET; // back up
        $_GET = array();
        $get = explode('&', $get);
        $n = count($get);

        for($i = 0; $i < $n; $i++) {
            if(strpos($get[$i], '=') === false)
                $_GET[$get[$i]] = 1;
            else {
                list($name, $val) = explode('=', $get[$i], 2);
                $_GET[$name] = $val;
            }
        }
    }

    ob_start();
    chdir($dir);
    require $file;
    $out = ob_get_clean();

    if($tmp)
        $_GET = $tmp;

    return $out;
}

$out = pinclude('./dir/yourfile.php', 'a=b&c=d&e');
echo $out;
// i'm sorry but i forgot post requests...
?>