jueves, 21 de abril de 2011

Estudiando PHP 5.3 - I - Tipos

Este es el inicio de un conjunto de posts de características especiales, importantes o elementos que puedan hacerme fallar algún test de PHP, algo no muy básico pues ya sé un poco del lenguaje pero con muchos "Tips & Trics".

Primero quiero exponer un tipo de comentario en PHP que he visto muy pocas veces y es el que se usa en archivo shell o perl, he aquí algunos ejemplos de comentario incluyéndolo:
- Comentario de varias líneas
/* echo "A"; */

- Comentario de una línea
// echo "A";

- Comentario de una línea tipo shell
# echo "A";
* Incluso al día del post la última versión de SyntaxHighlighter no lo resalta de la forma correcta, pero créanme: funciona.



Tipos
Tomado casi textual de php.net los tipos son: 8 primitivos y 3 de documentación (pseudo-tipos), agrupados como sigue:

Simples: integer, float, string, boolean
Complejos: array, object
Especiales: resource, NULL

Pseudo-tipos: mixed, number, callback

PHP no soporta definir las variables con un tipo específico, el tipo se adquiere al asignarle el valor.
Probando: La columna de la izquierda asigna el valor a $foo y la columna derecha muestra el resultado de la función var_dump($foo).
$foo = true;
$foo = "10";
$foo += 2;
$foo = 010;
$foo = 0x10;
$foo = $foo + "1.3";
$foo = 5 + "10 manzanas";
$foo = 5 + "010 peras";
$foo = 5 + "0x10 uvas";
$foo = 5 + "otras 2 uvas";
$foo = "5 manzanas" + "3 peras";
$foo = false + 5;
$foo = true + 5;
$foo = array() + 5;
boolean true
string '10' (length=2)
int 12
int 8
int 16
float 17.3
int 15
int 15
int 21
int 5
int 8
int 5
int 6
Fatal error: Unsupported operand types
Lo importante:
- Las líneas resaltadas son solo para facilitar la lectura.
- 010 es la notación octal equivalente a 8 en notación decimal.
- 0x10 es la notación hexadecimal equivalente a 16 en notación decimal.
- La notación octal dentro de una cadena no es evaluada como tal al sumarse con un número.
- Sí se puede sumar manzanas y peras.

Para asegurar el tipo de valor almacenado en una variable se pude usar una conversión directa (cast) o la función settype( ).
Los posibles cast son:
  • (int),(integer)
  • (bool),(boolean)
  • (float),(double),(real)
  • (string)
  • (array)
  • (object)
  • (unset) - cast a NULL (PHP 5)
  • (binary) - igual que poner el prefijo 'b' a una cadena (PHP 5.2.1)

La función settype se define así:
  • bool settype ( mixed &$var , string $type )
    Donde $type puede ser el nombre de cualquier tipo primitivo o la cadena "null".

Pruebas (int):
$foo = (int)1.7;
$foo = (int)true;
$foo = (int)false;
$foo = (int)"10";
$foo = (int)"A";
$foo = (int)"2A";
$foo = (int)-1;
$foo = (int)new Exception("int cast");
$foo = new Exception("int cast");
settype( $foo, "int" );
$foo;
$foo = (int)"0x10";
$foo = (int)0x10;
$foo = (int)010;
$foo = (int)"010";
$foo = (int)b"010";
$foo = (int)array();
$foo = (int)array( 2 );
$foo = (int)null;
$foo = (int)!null;
int 1
int 1
int 0
int 10
int 0
int 2
int -1
int 1 // Notice
object(Exception)
boolean true // Notice
int 1
int 0
int 16
int 8
int 10
int 10
int 0
int 1
int 0
int 1
Lo importante:
- Las líneas 8 y 10 lanzan una noticia "Notice: Object of class Exception could not be converted to int" y el objeto se transforma en el entero 1.
- Las notación diferentes a la decimal no son evaluadas correctamente como se ve el las líneas 12, 15 y 16.
- Un arreglo vacío es 0 uno con elementos es 1.
- No sé qué es el negado de null pero trasformado a en entero da 1.

Los resultados con (float) en general son los mismos, así que...

Pruebas (string):
$foo = (string)1.7;
$foo = (string)0xF;
$foo = (string)010;
$foo = (string)true;
$foo = (string)false;
$foo = (string)null;
$foo = (string)!null;
$foo = (string)'';
$foo = (string)!'';
$foo = (string)array(1,2,3);
string '1.7' (length=3)
string '15' (length=2)
string '8' (length=1)
string '1' (length=1)
string '' (length=0)
string '' (length=0)
string '1' (length=1)
string '' (length=0)
string '1' (length=1)
string 'Array' (length=5)
Lo importante:
- Solo me parece importante el caso del array

Pruebas (array):
$foo = (array)1.7;

$foo = (array)"10";

$foo = (array)0xF;

$foo = (array)true;

$foo = (array)false;

$foo = (array)null;

$foo = (array)'';
.
array
  0 => float 1.7
array
  0 => string '10' (length=2)
array
  0 => int 15
array
  0 => boolean true
array
  0 => boolean false
array
  empty
array
  0 => string '' (length=0)
Lo importante:
- Solo me parece importante el caso del null

Pruebas (object):
$foo = (object)1.7;

$foo = (object)"10";

$foo = (object)true;

$foo = (object)false;

$foo = (object)null;
$foo = (object)'';

$foo = (object)array(1,2,3);
.
.
.
object(stdClass)[1]
  public 'scalar' => float 1.7
object(stdClass)[2]
  public 'scalar' => string '10' (length=2)
object(stdClass)[1]
  public 'scalar' => boolean true
object(stdClass)[2]
  public 'scalar' => boolean false
object(stdClass)[1]
object(stdClass)[2]
  public 'scalar' => string '' (length=0)
object(stdClass)[1]
  int 1
  int 2
  int 3
Todo estaba claro y simple hasta mi intento de convertir un array en objeto, no hubo errores pero luego de ver el resultado por un momento no se me ocurrió como obtener los valores que tenía el arreglo ahora que es objeto, hice un par de intentos usando Reflection pero no lo logré, ¿alguno de ustedes sabe cómo?

No hay comentarios:

Publicar un comentario