Expectedly <?php $string[$x] ?> and <?php substr($string, $x, 1) ?> will yield the same result... normally!
However, when you turn on the Function Overloading Feature (http://de.php.net/manual/en/mbstring.overload.php), this might not be true!
If you use this Overloading Feature with 3rd party software, you should check for usage of the String access operator, otherwise you might be in for some nasty surprises.
Cadenas
Un valor string es una serie de caracteres. Antes de PHP 6, un caracter es lo mismo que un byte, es decir, hay exactamente 256 tipos de caracteres diferentes. Esto implica también que PHP no tiene soporte nativo de Unicode. Vea utf8_encode() y utf8_decode() para conocer sobre una funcionalidad básica para Unicode.
Note: El que una cadena se haga muy grande no es un problema. PHP no impone lÃmite práctico alguno sobre el tamaño de las cadenas; el único lÃmite es la memoria disponible en la máquina en la que PHP esté corriendo.
Sintaxis
Un literal tipo string puede especificarse en cuatro formas diferentes.
- comillas simples
- comillas dobles
- sintaxis heredoc
- sintaxis nowdoc (a partir de PHP 5.3.0)
Comillas simples
La forma más simple de especificar un string es rodearla de comillas simples (el caracter ').
Para especificar una comilla sencilla literal, necesita escaparla con una barra invertida (\). Para especificar una barra invertida literal antes de una comilla sencilla, o al final de la cadena, dóblela (\\). Note que intentar escapar cualquier otro caracter imprimirá la barra invertida también.
Note: A diferencia de las otras dos sintaxis, las variables y secuencias de escape para caracteres especiales no serán expandidas cuando ocurren al interior de cadenas entre comillas sencillas.
<?php
echo 'esta es una cadena simple';
echo 'También puede tener saltos de lÃnea embebidos
en las cadenas de esta forma, ya que
es válido';
// Imprime: Arnold dijo una vez: "I'll be back"
echo 'Arnold dijo una vez: "I\'ll be back"';
// Imprime: Ha eliminado C:\*.*?
echo 'Ha eliminado C:\\*.*?';
// Imprime: Ha eliminado C:\*.*?
echo 'Ha eliminado C:\*.*?';
// Imprime: Esto no va a expandirse: \n una nueva lÃnea
echo 'Esto no va a expandirse: \n una nueva lÃnea';
// Imprime: Las variables no se $expanden $tampoco
echo 'Las variables no se $expanden $tampoco';
?>
Comillas dobles
Si el valor string se encuentra rodeado de comillas dobles ("), PHP interpretará más secuencias de escape para caracteres especiales:
| Secuencia | Significado |
|---|---|
| \n | alimentación de lÃnea (LF o 0x0A (10) en ASCII) |
| \r | retorno de carro (CR o 0x0D (13) en ASCII) |
| \t | tabulación horizontal (HT o 0x09 (9) en ASCII) |
| \v | tabulación vertical (VT o 0x0B (11) en ASCII) (desde PHP 5.2.5) |
| \f | alimentación de forma (FF o 0x0C (12) en ASCII) (a partir de PHP 5.2.5) |
| \\ | barra invertida |
| \$ | signo de dólar |
| \" | comilla-doble |
| \[0-7]{1,3} | la secuencia de caracteres que coincide con la expresión regular es un caracter en notación octal |
| \x[0-9A-Fa-f]{1,2} | la secuencia de caracteres que coincide con la expresión regular es un caracter en notación hexadecimal |
Como ocurre con las cadenas entre comillas sencillas, escapar cualquier otro caracter resultará en que la barra invertida sea impresa también. Antes de PHP 5.1.1, la barra invertida en \{$var} no venÃa imprimiéndose.
La caracterÃstica más importante de las cadenas entre comillas dobles es el hecho de que los nombres de variables serán expandidos. Vea procesamiento de cadenas para más detalles.
Heredoc
Una tercera forma de delimitar valores string es mediante el uso de la sintaxis heredoc: <<<. Después de este operador debe indicarse un identificador, luego un salto de lÃnea. La cadena sigue a continuación y luego el mismo identificador de nuevo para cerrar el bloque.
El identificador de cierre debe comenzar en la primera columna de la lÃnea. Asimismo, el identificador usado debe seguir las mismas reglas que cualquier otra etiqueta en PHP: debe contener solo caracteres alfanuméricos y de subrayado, y debe iniciar con un caracter no-dÃgito o de subrayado.
Es muy importante notar que la lÃnea con el identificador de cierre no contenga otros caracteres, excepto quizás por un punto-y-coma (;). Esto quiere decir en especial que el identificador no debe usar sangrÃa, y no debe haber espacios o tabuladores antes o después del punto-y-coma. Es importante notar también que el primer caracter antes del identificador de cierre debe ser un salto de lÃnea, tal y como lo defina su sistema operativo. Esto quiere decir \n en sistemas UNIX, incluyendo Mac OS X. El delimitador de cierre (posiblemente seguido de un punto-y-coma) debe ser seguido también por una nueva lÃnea.
Si esta regla es rota y el identificador de cierre no es "limpio", entonces no se considera un identificador de cierre y PHP continuará en busca de uno. Si no se encuentra un identificador de cierre antes del final del archivo actual, un error del analizador sintáctico se producirá en la última lÃnea.
No es posible usar la sintaxis heredoc para inicializar miembros de clase. Use nowdocs en su lugar.
Example #1 Ejemplo inválido
<?php
class foo {
public $bar = <<<EOT
bar
EOT;
}
?>
El texto heredoc se comporta tal como una cadena entre comillas dobles, sin las comillas dobles. Esto quiere decir que no necesita escapar tales comillas en sus bloques heredoc, pero aun puede usar los códigos de escape listados anteriormente. Las variables son expandidas, aunque debe tenerse el mismo cuidado cuando se expresen variables complejas al interior de un segmento heredoc, al igual que con otras cadenas.
Example #2 Ejemplo de uso de una cadena heredoc
<?php
$cadena = <<<FIN
Ejemplo de una cadena
que se extiende por varias lÃneas
usando la sintaxis heredoc.
FIN;
/* Un ejemplo más complejo, con variables. */
class foo
{
var $foo;
var $bar;
function foo()
{
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
$nombre = 'MiNombre';
echo <<<FIN
Mi nombre es "$nombre". Estoy imprimiendo algo de $foo->foo.
Ahora, estoy imprimiendo algo de {$foo->bar[1]}.
Esto deberÃa imprimir una letra 'A' mayúscula: \x41
FIN;
?>
El resultado del ejemplo seria:
Mi nombre es "MiNombre". Estoy imprimiendo algo de Foo. Ahora, estoy imprimiendo algo de Bar2. Esto deberÃa imprimir una letra 'A' mayúscula: A
Note: El soporte heredoc fue agregado en PHP 4.
Nowdoc
Nowdocs es para las cadenas en comillas sencillas lo que heredocs es para las cadenas en comillas dobles. Un nowdoc es especificado de forma similar a heredoc, pero no se realiza ningún procesamiento al interior de un nowdoc. Esta construcción es ideal para embeber código PHP u otros bloques grandes de texto sin la necesidad de escaparlo. Comparte algunas caracterÃsticas en común con la construcción de SGML <![CDATA[ ]]>, en el sentido de que declara un bloque de texto que no debe ser procesado.
Un nowdoc es identificado con la misma secuencia <<< usada para heredocs, pero el identificador que sigue a continuación debe ser rodeado de comillas sencillas, p.ej. <<<'FIN'. Todas las reglas para los identificadores heredoc también se aplican a los identificadores nowdoc, especialmente aquellas relacionadas con la apariencia del identificador de cierre.
Example #3 Ejemplo de uso de una cadena nowdoc
<?php
$cadena = <<<'FIN'
Ejemplo de una cadena
que se extiende por varias lÃneas
usando la sintaxis nowdoc.
FIN;
/* Un ejemplo más complejo, con variables. */
class foo
{
var $foo;
var $bar;
function foo()
{
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
$nombre = 'MiNombre';
echo <<<'FIN'
Mi nombre es "$nombre". Estoy imprimiendo algo de $foo->foo.
Ahora, estoy imprimiendo algo de {$foo->bar[1]}.
Esto no deberÃa imprimir una letra 'A' mayúscula: x41
FIN;
?>
El resultado del ejemplo seria:
Mi nombre es "$nombre". Estoy imprimiendo algo de $foo->foo. Ahora, estoy imprimiendo algo de {$foo->bar[1]}. Esto no deberÃa imprimir una letra 'A' mayúscula: \x41
Note: A diferencia de los bloques heredoc, nowdocs pueden ser usados en cualquier contexto de datos estáticos. El ejemplo tÃpico es la inicialización de miembros o constantes de clase:
Example #4 Ejemplo de datos estáticos
<?php
class foo {
public $bar = <<<'EOT'
bar
EOT;
}
?>
Note: El soporte para nowdoc fue agregado en PHP 5.3.0.
Procesamiento de variables
Cuando un valor string es especificado en comillas dobles o al interior de un bloque heredoc, las variables son interpretadas en su interior.
Existen dos tipos de sintaxis: una simple y una compleja. La sintaxis simple es la más común y conveniente. Ésta ofrece una forma de interpretar una variable, un valor array, o una propiedad de un objeto al interior de una cadena con un mÃnimo de esfuerzo.
La sintaxis compleja fue introducida en PHP 4, y puede reconocerse por las llaves que rodean la expresión.
Sintaxis simple
Si un signo de dólar ($) es encontrado, el analizador sintáctico tomará ambiciosamente tantos lexemas como le sea posible para formar un nombre de variable válido. Rodee el nombre de la variable de llaves si desea especificar explÃcitamente el final del nombre.
<?php
$cerveza = 'Heineken';
echo "El sabor de varias $cerveza's es excelente"; // funciona, "'" no es un caracter válido para nombres de variables
echo "Tomó algunas $cervezas"; // no funciona, 's' es un caracter válido para nombres de variables
echo "Tomó algunas ${cerveza}s"; // funciona
echo "Tomó algunas {$cerveza}s"; // funciona
?>
De forma similar, el Ãndice de un array o una propiedad de un object pueden ser interpretados. En el caso de los Ãndices de matrices, el corchete cuadrado de cierre (]) marca el final del Ãndice. Las mismas reglas usadas con variables simples se aplican a las propiedades de objetos.
<?php
// Estos ejemplos son especÃficos al uso de matrices al interior de
// cadenas. Cuando se encuentre por fuera de una cadena, siempre rodee
// de comillas las claves tipo cadena de su matriz, y no use {llaves}.
// Mostrar todos los errores
error_reporting(E_ALL);
$frutas = array('fresa' => 'roja', 'banano' => 'amarillo');
// Funciona pero note que esto trabaja de forma diferente por fuera de
// cadenas entre comillas
echo "Un banano es $frutas[banano].";
// Funciona
echo "Un banano es {$frutas['banano']}.";
// Funciona, pero PHP busca una constante llamada banano primero, como
// se describe más adelante.
echo "Un banano es {$frutas[banano]}.";
// No funciona, use llaves. Esto resulta en un error de análisis sintáctico.
echo "Un banano es $frutas['banano'].";
// Funciona
echo "Un banano es " . $frutas['banano'] . ".";
// Funciona
echo "Este cuadro tiene $cuadro->ancho metros de ancho.";
// No funciona. Para una solución, vea la sintaxis compleja.
echo "Este cuadro tiene $cuadro->ancho00 centÃmetros de ancho.";
?>
Para cualquier cosa más sofisticada, deberÃa usarse la sintaxis compleja.
Sintaxis compleja (llaves)
Esta no es llamada compleja porque la sintaxis sea compleja, sino porque es posible incluir expresiones complejas de esta forma.
De hecho, cualquier valor que sea parte del espacio de nombres puede ser incluido en una cadena con esta sintaxis. Simplemente escriba la expresión en la misma forma que lo harÃa si se encontrara por fuera de una cadena, y luego la ubica entre { y }. Ya que no es posible escapar {, esta sintaxis será reconocida únicamente cuando el caracter $ se encuentra inmediatamente después de {. Use {\$ para obtener una secuencia literal {$. Algunos ejemplos para aclarar el asunto:
<?php
// Mostrar todos los errores
error_reporting(E_ALL);
$genial = 'fantástico';
// No funciona, imprime: Esto es { fantástico}
echo "Esto es { $genial}";
// Funciona, imprime: Esto es fantástico
echo "Esto es {$genial}";
echo "Esto es ${genial}";
// Funciona
echo "Este cuadro tiene {$cuadro->ancho}00 centÃmetros de ancho.";
// Funciona
echo "Esto funciona: {$matriz[4][3]}";
// Esto está mal por la misma razón por la que $foo[bar] está mal por
// fuera de una cadena. En otras palabras, aun funciona pero sólo porque
// PHP busca primero una constante llamada foo; genera un error de
// nivel E_NOTICE (constante indefinida).
echo "Esto está mal: {$matriz[foo][3]}";
// Funciona. Cuando se usan matrices multi-dimensionales, use siempre
// llaves alrededor de las matrices al interior de cadenas
echo "Esto funciona: {$matriz['foo'][3]}";
// Funciona.
echo "Esto funciona: " . $arr['foo'][3];
echo "Esto funciona también: {$obj->valores[3]->nombre}";
echo "Este es el valor de la variable llamada $nombre: {${$nombre}}";
echo "Este es el valor de la variable llamada por el valor devuelto por getName(): {${getName()}}";
echo "Este es el valor de la variable llamada por el valor devuelto por \$objeto->getName(): {${$objeto->getName()}}";
?>
Note: Las llamadas a funciones y métodos al interior de {$} trabajan a partir de PHP 5.
Acceso a cadenas y modificación por caracter
Los caracteres al interior de una cadena pueden ser consultados y modificados al especificar el desplazamiento, comenzando en cero, del caracter deseado después de la cadena usando corchetes cuadrados tipo-matriz como $cadena[42]. Para este propósito, piense en un valor string como un array de caracteres.
Note: Las cadenas son accesibles también usando llaves, como en $cadena{42}, para el mismo propósito. Sin embargo, esta sintaxis ha sido marcada como obsoleta en PHP 6. Use los corchetes cuadrados en su lugar.
Example #5 Algunos ejemplos de cadenas
<?php
// Obtener el primer caracter de una cadena
$cadena = 'Esta es una prueba.';
$primer = $cadena[0];
// Obtener el tercer caracter de una cadena
$tercer = $cadena[2];
// Obtener el último caracter de una cadena.
$cadena = 'Esta es también una prueba.';
$ultimo = $cadena[strlen($cadena)-1];
// Modificar el último caracter de una cadena
$cadena = 'Observe el mar';
$cadena[strlen($cadena)-1] = 'l';
?>
Note: Al accesar variables de otros tipos mediante [] o {} se devuelve silenciosamente NULL.
Funciones y operadores útiles
Las cadenas pueden ser concatenadas usando el operador '.' (punto). Note que el operador '+' (adición) no funciona para este propósito. Por favor refiérase a la sección Operadores de cadena para más información.
Existen bastantes funciones útiles para la modificación de valores string.
Vea la sección de funciones de cadena para consultar funciones de uso general, y las funciones de expresiones regulares o las funciones de expresiones regulares compatibles con Perl para funcionalidad avanzada de búsquedas y reemplazos.
Existen también funciones para cadenas tipo URL, y funciones para encriptar/descifrar cadenas (mcrypt y mhash).
Finalmente, vea también las funciones de tipo de caracter.
Conversión a cadena
Un valor puede ser convertido a string usando el moldeamiento (string) o la función strval(). La conversión a cadena se realiza automáticamente en el ámbito de una expresión cuando se necesita una cadena. Esto ocurre cuando usa las funciones echo() o print(), o cuando una variable es comparada con una cadena. El contenido de las secciones del manual sobre Tipos y Manipulación de Tipos ayudan a aclarar el contenido presentado a continuación. Vea también la función settype().
Un valor boolean TRUE es convertido a la cadena "1", el valor FALSE se representa como "" (la cadena vacÃa). De esta forma, usted puede convertir de ida y vuelta entre valores booleanos y de cadena.
Un número integer o de punto flotante (float) es convertido a una cadena que representa el número textualmente (incluyendo la parte del exponente para los números de punto flotante). Los números de punto flotante pueden ser convertidos usando la notación exponencial (4.1E+6).
Note: El caracter de punto decimal es definido en la localización del script (categorÃa LC_NUMERIC). Vea la función setlocale().
Las matrices son siempre convertidas a la cadena "Array"; por esta razón, echo() y print() no pueden por su cuenta mostrar los contenidos de un valor array. Para ver un elemento sencillo, use una construcción como echo $arr['foo']. Vea más adelante algunos consejos sobre el volcado/vista del contenido completo.
Los objetos en PHP 4 son convertidos siempre a la cadena "Object". Para imprimir los valores de miembros de un objeto para efectos de depuración, lea los parágrafos siguientes. Para obtener el nombre de la clase de un objeto, use la función get_class(). A partir de PHP 5, el método __toString es usado si resulta aplicable.
Los recursos son siempre convertidos a cadenas con la estructura "Resource id #1" en donde 1 es el número único del valor resource asignado por PHP en tiempo de ejecución. No escriba código que dependa de esta estructura; está sujeta a cambios. Para obtener el tipo del recurso, use la función get_resource_type().
NULL se convierte siempre a una cadena vacÃa.
Como se ha indicado anteriormente , convertir directamente un valor tipo array, object, o resource a un string no ofrece información útil sobre los valores más allá de su tipo. Consulte las funciones print_r() y var_dump() para conocer mejores formas de inspeccionar los contenidos de estos tipos.
La mayorÃa de valores PHP pueden ser convertidos también a string para su almacenamiento permanentemente. Este método es conocido como seriación, y es efectuado por la función serialize(). Si el motor PHP fue compilado con soporte WDDX, los valores PHP pueden ser seriados también como texto XML correctamente formado.
Conversión de cadenas a números
Cuando una cadena es evaluada en un ámbito numérico, el valor resultante y su tipo son determinados como sigue.
El valor string será evaluado como un float si contiene cualquier caracter entre '.', 'e', o 'E'. De otra forma, será evaluado como un integer.
El valor es dado por la porción inicial de la cadena. Si la cadena comienza con datos numéricos válidos, éstos serán el valor usado. De lo contrario, el valor será 0 (cero). Un dato numérico válido consiste de un signo opcional, seguido por uno o más dÃgitos (que pueden contener un punto decimal), seguidos por un exponente opcional. El exponente es una 'e' o 'E' seguida de uno o más dÃgitos.
<?php
$foo = 1 + "10.5"; // $foo es flotante (11.5)
$foo = 1 + "-1.3e3"; // $foo es flotante (-1299)
$foo = 1 + "bob-1.3e3"; // $foo es entero (1)
$foo = 1 + "bob3"; // $foo es entero (1)
$foo = 1 + "10 Cerditos"; // $foo es entero (11)
$foo = 4 + "10.2 Cerditos"; // $foo es flotante (14.2)
$foo = "10.0 cerdos " + 1; // $foo es flotante (11)
$foo = "10.0 cerdos " + 1.0; // $foo es flotante (11)
?>
Para más información sobre esta conversión, vea la página del manual Unix sobre strtod(3).
Si quisiera probar cualquiera de los ejemplos presentados en esta sección, puede cortar y pegar los ejemplos e insertar la siguiente lÃnea para verificar por sà mismo lo que está sucediendo:
<?php
echo "\$foo==$foo; tipo es " . gettype ($foo) . "<br />\n";
?>
No espere obtener el código de un caractar convirtiéndolo a un entero, como se hace en C. Use las funciones ord() y chr() para convertir entre códigos ASCII y caracteres.
Cadenas
16-Nov-2008 02:21
15-Oct-2008 05:33
An interesting finding about Heredoc "syntax error, unexpected $end".
I got this error because I did not use the php close tag "?>" and I had no code after the heredoc code.
foo1.php code gives "syntax error, unexpected $end".
But in foo2.php and foo3.php, when you add a php close tag or when you have some more code after heredoc it works fine.
Example Code:
foo1.php
1. <?php
2. $str = <<<EOD
3. Example of string
4. spanning multiple lines
5. using heredoc syntax.
6. EOD;
7.
foo2.php
1. <?php
2. $str = <<<EOD
3. Example of string
4. spanning multiple lines
5. using heredoc syntax.
6. EOD;
7.
8. echo $str;
9.
foo3.php
1. <?php
2. $str = <<<EOD
3. Example of string
4. spanning multiple lines
5. using heredoc syntax.
6. EOD;
7. ?>
30-Sep-2008 05:33
Simple function to create human-readably escaped double-quoted strings for use in source code or when debugging strings with newlines/tabs/etc.
<?php
function doubleQuote($str) {
$ret = '"';
for ($i = 0, $l = strlen($str); $i < $l; ++$i) {
$o = ord($str[$i]);
if ($o < 31 || $o > 126) {
switch ($o) {
case 9: $ret .= '\t'; break;
case 10: $ret .= '\n'; break;
case 11: $ret .= '\v'; break;
case 12: $ret .= '\f'; break;
case 13: $ret .= '\r'; break;
default: $ret .= '\x' . str_pad(dechex($o), 2, '0', STR_PAD_LEFT);
}
} else {
switch ($o) {
case 36: $ret .= '\$'; break;
case 34: $ret .= '\"'; break;
case 92: $ret .= '\\\\'; break;
default: $ret .= $str[$i];
}
}
}
return $ret . '"';
}
?>
11-Sep-2008 12:42
To save Your mind don't read previous comments about dates ;)
When both strings can be converted to the numerics (in ("$a" > "$b") test) then resulted numerics are used, else FULL strings are compared char-by-char:
<?php
var_dump('1.22' > '01.23'); // bool(false)
var_dump('1.22.00' > '01.23.00'); // bool(true)
var_dump('1-22-00' > '01-23-00'); // bool(true)
var_dump((float)'1.22.00' > (float)'01.23.00'); // bool(false)
?>
01-Sep-2008 07:05
So you want to get the last character of a string using "String access and modification by character"? Well negative indexes are not allowed so $str[-1] will return an empty string.
<?php
//Tested using: PHP 5.2.5
$str = 'This is a test.';
$last = $str[-1]; //string(0) ""
$realLast = $str[strlen($str)-1]; //string(1) "."
$substr = substr($str,-1); //string(1) "."
echo '<pre>';
var_dump($last);
var_dump($realLast);
var_dump($substr);
06-Jun-2008 04:40
It's also valuable to note the following:
<?php
${date("M")} = "Worked";
echo ${date("M")};
?>
This is perfectly legal, anything inside the braces is executed first, the return value then becomes the variable name. Echoing the same variable variable using the function that created it results in the same return and therefore the same variable name is used in the echo statement. Have fun ;).
30-Apr-2008 04:46
<?php
$F = "F";
function F($s) { return $s; }
$filename = '<some code>';
echo "{$F(htmlspecialchars($filename))}";
?>
31-Mar-2008 11:21
This example of the heredoc has wrong output:
Code: This should print a capital 'A': \x41
Output should be: This should print a capital 'A': A
The example of the nowdoc has wrong code:
Code: This should not print a capital 'A': x41
That should be: This should not print a capital 'A': \x41
24-Mar-2008 11:58
For anyone who reads Evan K, please note that:
// a string to test, and show the before and after
$before = 'Quantity:\t500\nPrice:\t$5.25 each';
$after = expand_escape($before);
var_dump($before, $after);
Is identical to (note all I added was a backslash before $):
$before = "Quantity:\t500\nPrice:\t\$5.25 each";
var_dump($before);
So its definitely better to escape a dollar instead of all the overhead of his regex and evals and such, although clever completely unnecessary.
-Chris
28-Feb-2008 07:03
I encountered the odd situation of having a string containing unexpanded escape sequences that I wanted to expand, but also contained dollar signs that would be interpolated as variables. "$5.25\n", for example, where I want to convert \n to a newline, but don't want attempted interpolation of $5.
Some muddling through docs and many obscenties later, I produced the following, which expands escape sequences in an existing string with NO interpolation.
<?php
// where we do all our magic
function expand_escape($string) {
return preg_replace_callback(
'/\\\([nrtvf]|[0-7]{1,3}|[0-9A-Fa-f]{1,2})?/',
create_function(
'$matches',
'return ($matches[0] == "\\\\") ? "" : eval( sprintf(\'return "%s";\', $matches[0]) );'
),
$string
);
}
// a string to test, and show the before and after
$before = 'Quantity:\t500\nPrice:\t$5.25 each';
$after = expand_escape($before);
var_dump($before, $after);
/* Outputs:
string(34) "Quantity:\t500\nPrice:\t$5.25 each"
string(31) "Quantity: 500
Price: $5.25 each"
*/
?>
07-Feb-2008 04:31
I think there's not that much to string comparison as claiming date recognition:
It's simply comparing ordinal values of the characters from the {0} to the {strlen-1} one.
In this case
<?php
$a = '2007-11-06 15:17:48';
$b = '2007-11-05 15:17:48';
var_dump($a > $b);
?>
mArIo@luigi ~ $: php test.php
bool(true)
here all characters match till it reaches position 9 (the "day")
there, 6 has a bigger ord()inal value than 5
<?php
$a = 'January 25th, 2008 00:23:38';
$b = 'Janury 24th, 2008 00:23:37'; // ($a > $b) === false
?>
Here when we reach 'r' in "Janury" we see that "a" is "less" than "r" so the example would evaluate as ($a < $b) === true
Here:
<?php
$a = 'February 1st, 2008 00:23:38';
$b = 'January 25th, 2008 00:23:38';
?>
as expected the letter "F" comes before "J" as an ordinal character, so $a is less than $b
Even here:
<?php
var_dump('Z' > 'M'); //bool(true)
?>
it gets confirmed that the string comparison operators >, <, =>, =<, == just do a ordinal character comparison starting from position {0} to the first difference or the end of the string.
28-Jan-2008 02:25
@qriz at example dot com
Numerical comparisons, such as <, > are simply _NOT_ valid on strings. Thus, before a comparison can be made by a numerical comparison operator, the operands must be _casted_ to a numerical type (either float or int). What I was attempting to say in my previous post is that >, < are date-aware; the tests I included were examples, and not intended to represent the full scope of my comparison.
"Works correctly since there is a comparing between strings. The comparisson is done on the last number/letter (since thats the only thing that is difference in the string) and that is in this case: the 9 and 8."
What you say here is mere assumption; a few quick tests show that this is indeed not the case. If PHP indeed compares only the last character in the string, then the following assertion should be false:
test.php:
<?php
$a = '2007-11-06 15:17:48';
$b = '2007-11-05 15:17:48';
var_dump($a > $b);
?>
mArIo@luigi ~ $: php test.php
bool(true)
Further, consider the following choices for $a and $b, which, as expected, demonstrate that the <, > operators can indeed understand date formats:
<?php
$a = 'January 25th, 2008 00:23:37';
$b = 'January 24th, 2008 00:23:38'; // ($a > $b) === true, but 8
?>
If you remain unconvinced, consider what happens if I spell January incorrectly:
<?php
$a = 'January 25th, 2008 00:23:38';
$b = 'Janury 24th, 2008 00:23:37'; // ($a > $b) === false
?>
Looks like it can understand ISO 8601 date formats? (for more information, see http://en.wikipedia.org/wiki/ISO_8601)
Further investigation yields that this doesn't even work as it should:
<?php
$a = 'February 1st, 2008 00:23:38';
$b = 'January 25th, 2008 00:23:38';
var_dump($a > $b); //bool(false)
var_dump(strtotime($a)); //int(1201843418)
var_dump(strtotime($b)); //int(1201238618)
var_dump(strtotime($a) - strtotime($b)); //int(604800)
?>
Keeping $b constant and varying the month in $a shows that this comparison correctly interprets the date with the following months: January,March,May,June,July,September,October,November. Interestingly enough, these are all the months having the property that ord($a[0]) >= ord($b[0]).
<?php
var_dump('Z' > 'M'); //bool(true)
?>
Conclusion:
The <,> comparison operators definitely have functionality that is undocumented, including date awareness; however, this functionality may not always work as expected and should not be trusted for portability.
23-Jan-2008 12:38
this is the sql string that use the variable and and \' and function.It generate the correct result.
$sql1=<<<EOT
INSERT INTO hp_visitHistory ( col1,col2,col3)
VALUES ( NOW(), '{$col2}', '{$_SERVER['REQUEST_URI']}')
EOT;
echo $sql1;
13-Nov-2007 02:54
<?php
$a = '2007-11-05 15:17:49';
$b = '2007-11-05 15:17:48';
$bool = $a > $b;
var_dump($bool); //bool(true)
?>
works correctly since there is a comparing between strings. The comparisson is done on the last number/letter (since thats the only thing that is difference in the string) and that is in this case: the 9 and 8.
8 > 9 = true
if you want to compare the string as pure numbers then you must type cast it to numbers or type juggle it:
<?php
$a = '2007-11-05 15:17:49';
$b = '2007-11-05 15:17:48';
$bool1 = ($a + 0) > ($b + 0); // 2007 > 2007
$bool2 = (int) $a > (int) $b; // 2007 > 2007
$bool3 = intval($a) > intval($b); // 2007 > 2007
var_dump($bool1,$bool2,$bool3); //bool(false)
?>
05-Nov-2007 09:48
I have come across this several times, and as far as I can tell, the < and > operators have undocumented functionality when it comes to comparing strings. Consider the following script:
<?php
$a = '2007-11-05 15:17:49';
$b = '2007-11-05 15:17:48';
$bool = $a > $b;
var_dump($bool); //bool(true)
/**
* The manual tells us that $a and $b should be
* truncated at -, thus giving a floating-point value of 2007.
* But (2007 > 2007) === false...
*/
$a = (float)$a;
$b = (float)$b;
var_dump($a); //float(2007);
var_dump($b); //float(2007);
/**
* And the manual is right. So why does it correctly
* compare the dates (which should be treated
* as normal strings? Clearly some hidden functionality...
*/
26-Sep-2007 04:35
If you want to use a variable in an array index within a double quoted string you have to realize that when you put the curly braces around the array, everything inside the curly braces gets evaluated as if it were outside a string. Here are some examples:
<?php
$i = 0;
$myArray[Person0] = Bob;
$myArray[Person1] = George;
// prints Bob (the ++ is used to emphasize that the expression inside the {} is really being evaluated.)
echo "{$myArray['Person'.$i++]}<br>";
// these print George
echo "{$myArray['Person'.$i]}<br>";
echo "{$myArray["Person{$i}"]}<br>";
// These don't work
echo "{$myArray['Person$i']}<br>";
echo "{$myArray['Person'$i]}<br>";
// These both throw fatal errors
// echo "$myArray[Person$i]<br>";
//echo "$myArray[Person{$i}]<br>";
?>
07-Jul-2007 04:51
Heredocs can be used for more than just echoing or setting variables - use them whenever you want to include a string.
function header() {
return <<<EOT
<html>
<head>
<title>This is my heredoc</title>
</head>
<body>
EOT;
Also, note the strict syntax:
- No semicolon after initial EOT (think of the heredoc as a literal string arg - you wouldn't want a semicolon in front of it, would you?)
- BUT need semicolon after final EOT (the command is finished here)
- Final EOT is on the left margin - don't indent it!
03-Jul-2007 06:32
Function calls within double-quote variable interpolation work in PHP 5, but not quite as you'd expect. Basically the function has to be a variable function. I.e. a variable that holds the name of a function. So if you've got a function named 'x' that you want to call, you'll have to assign the function name to a variable. It's easiest to just assign it to a variable with the same name:
function x () { return 4; }
$x = 'x';
echo "x = {$x()}";
I'm not sure what the point of that is though, since it would be easier to do it this way:
function x () { return 4; }
$x = x();
echo "x = $x";
01-Jun-2007 12:31
Unlike bash, we can't do
echo "\a" #beep!
Of course, that would be rather meaningless for PHP/web, but it's useful for PHP-CLI. The solution is simple: echo "\x07"
25-Apr-2007 09:06
easy transparent solution for using constants in the heredoc format:
DEFINE('TEST','TEST STRING');
$const = get_defined_constants();
echo <<<END
{$const['TEST']}
END;
Result:
TEST STRING
24-Apr-2007 02:14
error control operator (@) with heredoc syntax:
the error control operator is pretty handy for supressing minimal errors or omissions. For example an email form that request some basic non mandatory information to your users. Some may complete the form, other may not. Lets say you don't want to tweak PHP for error levels and you just wish to create some basic template that will be emailed to the admin with the user information submitted. You manage to collect the user input in an array called $form:
<?php
// creating your mailer
$mailer = new SomeMailerLib();
$mailer->from = ' System <mail@yourwebsite.com>';
$mailer->to = 'admin@yourwebsite.com';
$mailer->subject = 'New user request';
// you put the error control operator before the heredoc operator to suppress notices and warnings about unset indices like this
$mailer->body = @<<<FORM
Firstname = {$form['firstname']}
Lastname = {$form['lastname']}
Email = {$form['email']}
Telephone = {$form['telephone']}
Address = {$form['address']}
FORM;
?>
01-Apr-2007 12:44
A simple benchmark to check differents about :
- simple and double quote concatenation and
- double quote and heredoc replacement
<?php
function test_simple_quote_concat()
{
$b = 'string';
$a = ' string'.$b.' string'.$b.' srting'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
$a .= ' string'.$b.' string'.$b.' string'.$b;
}
function test_double_quote_concat()
{
$b = "string";
$a = " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
$a .= " string".$b." string".$b." string".$b;
}
function test_double_quote_replace()
{
$b = "string";
$a = " string$b string$b string$b
string$b string$b string$b
string$b string$b string$b
string$b string$b string$b
string$b string$b string$b
string$b string$b string$b
string$b string$b string$b
string$b string$b string$b";
}
function test_eot_replace()
{
$b = <<<EOT
string
EOT;
$a = <<<EOT
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
string{$b} string{$b} string{$b}
EOT;
}
$iter = 2000;
for( $i=0; $i<$iter; $i++ )
test_simple_quote_concat();
for( $i=0; $i<$iter; $i++ )
test_double_quote_concat();
for( $i=0; $i<$iter; $i++ )
test_double_quote_replace();
for( $i=0; $i<$iter; $i++ )
test_eot_replace();
?>
I've use xdebug profiler to obtain the followed results:
test_simple_quote_concat : 173ms
test_double_quote_concat : 161ms
test_double_quote_replace : 147ms
test_eot_replace : 130ms
27-Feb-2007 05:16
As of (at least) PHP 5.2, you can no longer convert an object to a string unless it has a __toString method. Converting an object without this method now gives the error:
PHP Catchable fatal error: Object of class <classname> could not be converted to string in <file> on line <line>
Try this code to get the same results as before:
<?php
if (!is_object($value) || method_exists($value, '__toString')) {
$string = (string)$value;
} else {
$string = 'Object';
}
?>
21-Feb-2007 03:20
It may be obvious to some, but it's convenient to note that variables _will_ be expanded inside of single quotes if these occur inside of a double-quoted string. This can be handy in constructing exec calls with complex data to be passed to other programs. e.g.:
$foo = "green";
echo "the grass is $foo";
the grass is green
echo 'the grass is $foo';
the grass is $foo
echo "the grass is '$foo'";
the grass is 'green'
28-Mar-2006 05:58
You may use heredoc syntax to comment out large blocks of code, as follows:
<?php
<<<_EOC
// end-of-line comment will be masked... so will regular PHP:
echo ($test == 'foo' ? 'bar' : 'baz');
/* c-style comment will be masked, as will other heredocs (not using the same marker) */
echo <<<EOHTML
This is text you'll never see!
EOHTML;
function defintion($params) {
echo 'foo';
}
class definition extends nothing {
function definition($param) {
echo 'do nothing';
}
}
how about syntax errors?; = gone, I bet.
_EOC;
?>
Useful for debugging when C-style just won't do. Also useful if you wish to embed Perl-like Plain Old Documentation; extraction between POD markers is left as an exercise for the reader.
Note there is a performance penalty for this method, as PHP must still parse and variable substitute the string.
30-Nov-2005 01:57
Use caution when you need white space at the end of a heredoc. Not only is the mandatory final newline before the terminating symbol stripped, but an immediately preceding newline or space character is also stripped.
For example, in the following, the final space character (indicated by \s -- that is, the "\s" is not literally in the text, but is only used to indicate the space character) is stripped:
$string = <<<EOT
this is a string with a terminating space\s
EOT;
In the following, there will only be a single newline at the end of the string, even though two are shown in the text:
$string = <<<EOT
this is a string that must be
followed by a single newline
EOT;
01-Nov-2005 01:05
Just some quick observations on variable interpolation:
Because PHP looks for {? to start a complex variable expression in a double-quoted string, you can call object methods, but not class methods or unbound functions.
This works:
<?php
class a {
function b() {
return "World";
}
}
$c = new a;
echo "Hello {$c->b()}.\n"
?>
While this does not:
<?php
function b() {
return "World";
}
echo "Hello {b()}\n";
?>
Also, it appears that you can almost without limitation perform other processing within the argument list, but not outside it. For example:
<?
$true = true;
define("HW", "Hello World");
echo "{$true && HW}";
?>
gives: Parse error: parse error, unexpected T_BOOLEAN_AND, expecting '}' in - on line 3
There may still be some way to kludge the syntax to allow constants and unbound function calls inside a double-quoted string, but it isn't readily apparent to me at the moment, and I'm not sure I'd prefer the workaround over breaking out of the string at this point.
27-Oct-2004 04:01
You can use the complex syntax to put the value of both object properties AND object methods inside a string. For example...
<?php
class Test {
public $one = 1;
public function two() {
return 2;
}
}
$test = new Test();
echo "foo {$test->one} bar {$test->two()}";
?>
Will output "foo 1 bar 2".
However, you cannot do this for all values in your namespace. Class constants and static properties/methods will not work because the complex syntax looks for the '$'.
<?php
class Test {
const ONE = 1;
}
echo "foo {Test::ONE} bar";
?>
This will output "foo {Test::one} bar". Constants and static properties require you to break up the string.
06-Aug-2004 04:03
A note on the heredoc stuff.
If you're editing with VI/VIM and possible other syntax highlighting editors, then using certain words is the way forward. if you use <<<HTML for example, then the text will be hightlighted for HTML!!
I just found this out and used sed to alter all EOF to HTML.
JAVASCRIPT also works, and possibly others. The only thing about <<<JAVASCRIPT is that you can't add the <script> tags.., so use HTML instead, which will correctly highlight all JavaScript too..
You can also use EOHTML, EOSQL, and EOJAVASCRIPT.
28-Apr-2004 11:49
watch out when comparing strings that are numbers. this example:
<?php
$x1 = '111111111111111111';
$x2 = '111111111111111112';
echo ($x1 == $x2) ? "true\n" : "false\n";
?>
will output "true", although the strings are different. With large integer-strings, it seems that PHP compares only the integer values, not the strings. Even strval() will not work here.
To be on the safe side, use:
$x1 === $x2
11-Apr-2004 07:53
Here is a possible gotcha related to oddness involved with accessing strings by character past the end of the string:
$string = 'a';
var_dump($string[2]); // string(0) ""
var_dump($string[7]); // string(0) ""
$string[7] === ''; // TRUE
It appears that anything past the end of the string gives an empty string.. However, when E_NOTICE is on, the above examples will throw the message:
Notice: Uninitialized string offset: N in FILE on line LINE
This message cannot be specifically masked with @$string[7], as is possible when $string itself is unset.
isset($string[7]); // FALSE
$string[7] === NULL; // FALSE
Even though it seems like a not-NULL value of type string, it is still considered unset.
19-Jan-2004 08:41
By the way, the example with the "\n" sequence will insert a new line in the html code, while the output will be decided by the HTML syntax. That's why, if you use
<?
echo "Hello \n World";
?>
the browser will receive the HTML code on 2 lines
but his output on the page will be shown on one line only.
To diplay on 2 lines simply use:
<?
echo "Hello <br>World";
?>
like in HTML.
11-Apr-2003 09:37
Note that in PHP versions 4.3.0 and 4.3.1, the following provides a bogus E_NOTICE (this is a known bug):
echo "$somearray['bar']";
This is accessing an array inside a string using a quoted key and no {braces}. Reading the documention shows all the correct ways to do this but the above will output nothing on most systems (most have E_NOTICE off) so users may be confused. In PHP 4.3.2, the above will again yield a parse error.
Regarding "String access by character":
Apparently if you edit a specific character in a string, causing the string to be non-continuous, blank spaces will be added in the empty spots.
echo '<pre>';
$str = '0123';
echo "$str\n";
$str[4] = '4';
echo "$str\n";
$str[6] = '6';
echo "$str\n";
This will output:
0123
01234
01234 6
Notice the blank space where 5 should be.
03-Nov-2002 10:41
Even if the correct way to handle variables is determined from the context, some things just doesn't work without doing some preparation.
I spent several hours figuring out why I couldn't index a character out of a string after doing some math with it just before. The reason was that PHP thought the string was an integer!
$reference = $base + $userid;
.. looping commands ..
$chartohandle = $reference{$last_char - $i};
Above doesn't work. Reason: last operation with $reference is to store a product of an addition -> integer variable. $reference .=""; (string catenation) had to be added before I got it to work:
$reference = $base + $userid;
$reference .= "";
.. looping commands ..
$chartohandle = $reference{$last_char - $i};
Et voilá! Nice stream of single characters.
