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 . '"';
}
?>
문자열
string은 일련의 문자들이다. PHP에서 문자는 바이트와 같다. 즉 정확히 서로다른 256개의 문자를 사용할수 있다. 또한 PHP는 기본적으로 유니코드 지원을 갖지않는다. 유니코드에 대한 지원은 utf8_encode()과 utf8_decode()함수를 참고
Note: 문자열이 아무 문제없이 매우 커질수 있다. PHP에서 사용되는 문자열은 실질적으로 범위제한을 갖지 않는다. 그래서 긴 문자열에 대해서 걱정할 이유가 전혀 없다.
문법
문자열 리터럴은 3가지 다른 방식으로 표현될수 있다.
작은 따옴표
단순한 문자열을 표현하는 가장 간단한 방법이 작은 따옴표 (문자 ')로 문자열을 둘러싸면 된다.
작은따옴표를 리터럴로 표현하려면 역슬래쉬(\)로 회피할 필요가 있다. 다른 많은 언어에서도 이와같은 방식을 사용한다. 작은 따옴표 앞이나 문자열의 끝에서 역슬래쉬가 있을필요가 있으면, 이것은 중복사용할 필요가 있다. 다른 모든 문자를 회피하려하면 역슬래쉬가 출력되어야 할것이란 것에 주의하라! 그래서 보통은 역슬래쉬 자체를 회피할 필요가 없다.
Note: PHP 3에서 이와 같은 일이 발생하면 E_NOTICE레벨의 경고가 출력될것이다.
Note: 이외 다른 두가지 문법과는 달리 작은 따옴표로 둘러싸인 문자열에서 변수와 특별한 문자를 위한 회피는 전개되지 못한다.
<?php
echo 'this is a simple string';
echo 'You can also have embedded newlines in
strings this way as it is
okay to do';
// Outputs: Arnold once said: "I'll be back"
echo 'Arnold once said: "I\'ll be back"';
// Outputs: You deleted C:\*.*?
echo 'You deleted C:\\*.*?';
// Outputs: You deleted C:\*.*?
echo 'You deleted C:\*.*?';
// Outputs: This will not expand: \n a newline
echo 'This will not expand: \n a newline';
// Outputs: Variables do not $expand $either
echo 'Variables do not $expand $either';
?>
큰 따옴표
문자열이 큰따옴표(")로 둘러싸이면, PHP는 특별한 문자의 회피를 더 잘 이해한다.
| sequence | meaning |
|---|---|
| \n | linefeed (LF or 0x0A (10) in ASCII) |
| \r | carriage return (CR or 0x0D (13) in ASCII) |
| \t | horizontal tab (HT or 0x09 (9) in ASCII) |
| \\ | backslash |
| \$ | dollar sign |
| \" | double-quote |
| \[0-7]{1,3} | 이 정규표현식은 8진표기법의 일련의 문자이다. |
| \x[0-9A-Fa-f]{1,2} | 이 정규표현식은 16진표기법의 일련의 문자이다. |
다시 얘기하면, 다른 어떤 문자를 회피하려한다면, 역슬래쉬도 출력될것이다!
그러나 큰따옴표로 둘러싸인 문자열의 가장 중요한 특징은 변수명이 전개될것이란 사실이다. 더 자세한 사항은 문자열 해석을 참고.
히어닥 문법
문자열을 구분하는 다른 방법은 히어닥 문법("<<<")을 사용하는것이다. <<<이후에 식별자가 와야 하고 그다음에 문자열, 그다음에 인용을 닫는 어떤 식별자가 와야 한다.
닫기 식별자는 그 줄의 첫번째 컬럼에서 시작되어야 한다. 또한, 식별자는 PHP의 다른 라벨과 같은 명명규칙을 따라야 한다: 오직 알파벳 숫자와 밑줄을 포함하고 숫자가 아닌 문자나 밑줄로 시작되어야 한다.
닫기 식별자를 갖는 줄은 가능한 세미콜른(;)를 제외하고 다른 문자를 포함하지 않는다는것에 주의해야 한다. 이말은 특별히 식별자가 줄맞춤이 되지 않을 것이고 어떤 공백이나 탭문자도 세미콜른의 앞이나 뒤에 있지 않을것이란 것이다. 닫기 식별자 전의 첫 문자는 운영체제에서 정의된 새줄이 되어야 한다는 것을 인식해야 한다. 예를 들면 매킨토시에서는 \r이 된다.
이 규칙을 깨고 닫기 식별자가 "확실"하지 않으면, 닫기 식별자로 인식되지 않으며 PHP는 다른 식별자를 계속 찾게 될것이다. 그래서 적절한 닫기 식별자가 발견되지 않으면 스크립트 끝의 줄번호로 해석 에러가 출력될것이다.
히어닥 텍스트는 큰따옴표가 없지만 큰따옴표로 둘러싸인 문자열처럼 동작한다. 히어닥에서는 따옴표를 회피할 필요가 없다는 의미를 갖는다. 그러나 여전히 위에서 열거한 회피 코드를 사용할수 있다. 문자가 전개되면, 히어닥 안의 복합 변수를 문자열로 표현할때 같은 주의가 필요하다.
Example#1 히어닥 문자열 인용 예
<?php
$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;
/* More complex example, with variables. */
class foo
{
var $foo;
var $bar;
function foo()
{
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
$name = 'MyName';
echo <<<EOT
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should print a capital 'A': \x41
EOT;
?>
Note: 히어닥 지원은 PHP 4에서 추가되었다.
변수 해석
문자열이 큰따옴표나 히어닥으로 표현되면 변수는 그 안에서 해석된다.
두가지 형태의 문법이 존재한다: 단순문법과 복합문법이다. 단순 문법은 가장 일반적이고 가장 편하다. 이 문법은 변수나 array값, object속성을 해석하는 방법을 제공한다.
복합 문법은 PHP 4에서부터 지원되고, 중괄호로 둘러싸는 표현으로 인식된다.
단순 문법
달러사인($)과 만나면, 해석기는 가능한 많은 토큰을 취해서 유효한 변수명을 형성하게 된다. 중괄호로 변수명을 둘러싸면 이름의 끝을 명시적으로 표시하려는 것이다.
<?php
$beer = 'Heineken';
echo "$beer's taste is great"; // works, "'" is an invalid character for varnames
echo "He drank some $beers"; // won't work, 's' is a valid character for varnames
echo "He drank some ${beer}s"; // works
echo "He drank some {$beer}s"; // works
?>
비슷하게, array 인덱스나 해석된 object특성을 보유할수 있다. 배열 인덱스로 닫음 대괄호 (])는 인덱스의 끝을 표시한다. 객체 속성은 변수를 갖는 트릭이 존재하지 않지만, 객체 특성에 대해서 단순한 변수에 적용되는 규칙과 같다.
<?php
// These examples are specific to using arrays inside of strings.
// When outside of a string, always quote your array string keys
// and do not use {braces} when outside of strings either.
// Let's show all errors
error_reporting(E_ALL);
$fruits = array('strawberry' => 'red', 'banana' => 'yellow');
// Works but note that this works differently outside string-quotes
echo "A banana is $fruits[banana].";
// Works
echo "A banana is {$fruits['banana']}.";
// Works but PHP looks for a constant named banana first
// as described below.
echo "A banana is {$fruits[banana]}.";
// Won't work, use braces. This results in a parse error.
echo "A banana is $fruits['banana'].";
// Works
echo "A banana is " . $fruits['banana'] . ".";
// Works
echo "This square is $square->width meters broad.";
// Won't work. For a solution, see the complex syntax.
echo "This square is $square->width00 centimeters broad.";
?>
좀더 복잡한 변수에 대해서, 복합 문법을 사용해야 한다.
복합(curly) 문법
이 방법은 문법이 복합적이라서 복합이라고 부르는것이 아니다. 대신에 이 방법으로 복합 표현식을 포함할수 있기 때문이다.
사실, 이 문법으로 문자열의 네임스페이스에 존재하는 어떤변수 도 포함할수 있다. 단순히 문자열을 드러내는 방법과 동일한 표현식을 쓸수 있다. 그리고 { 과 } 안에 그것을 포함한다. '{'를 회피할 수 없기 때문에 이 문법은 $가 즉시 {뒤에 올때만 인식된다. ("{$" 리터럴을 쓰려면 "{\$" 이나 "\{$" 을 사용하라). 몇가지 예를 보고 위 설명을 이해해보자:
<?php
// 모든 에러를 보여줍니다.
error_reporting(E_ALL);
$great = 'fantastic';
// 작동하지 않습니다, 출력: This is { fantastic}
echo "This is { $great}";
// 작동합니다, 출력: This is fantastic
echo "This is {$great}";
echo "This is ${great}";
// 작동합니다.
echo "This square is {$square->width}00 centimeters broad.";
// 작동합니다.
echo "This works: {$arr[4][3]}";
// $foo[bar]가 문자열 밖에서 유효하지 않은 것과 마찬가지로,
// 잘못되었습니다. 즉, 이는 작동하지만 PHP는 먼저 상수 이름
// foo를 찾고, E_NOTICE 레벨의 오류(정의되지 않은 상수)를
// 발생합니다.
echo "This is wrong: {$arr[foo][3]}";
// 작동합니다. 문자열 안에서 다차원 배열을 사용할 때는,
// 항상 배열 주위를 중괄호로 감싸주십시오.
echo "This works: {$arr['foo'][3]}";
// 작동합니다.
echo "This works: " . $arr['foo'][3];
echo "You can even write {$obj->values[3]->name}";
echo "This is the value of the var named $name: {${$name}}";
?>
문자열의 문자에 접근 및 변경
문자열 내의 문자들 중 원하는 문자를 중괄호안에 0을 기준으로 한 위치를 표기하여 접근하고, 변경할 수 있습니다.
Note: 하위 버전과의 호환을 위해, 같은 목적으로 대괄호를 사용할 수 있습니다. 하지만, 이 문법은 PHP 4에서 배제되었습니다.
Example#2 몇 가지 문자열 예
<?php
// Get the first character of a string
$str = 'This is a test.';
$first = $str{0};
// Get the third character of a string
$third = $str{2};
// Get the last character of a string.
$str = 'This is still a test.';
$last = $str{strlen($str)-1};
// 문자열의 마지막 문자를 변경.
$str = 'Look at the sea';
$str{strlen($str)-1} = 'e';
?>
유용한 함수와 연산자
문자열들은 '.' (점) 연산자를 사용하여 합칠수 있다. '+' (덧셈) 연산자는 이 목적에 부합되지 않는다는 것에 주의해야 한다. 자세한 정보는 문자열 연산자를 참고
문자열 조작을 위한 많은 유용한 함수가 지원된다.
일반적인 기능을 대해서는 문자열 함수 섹션을 참고하고, 향상된 find&replace 기능을 위해 정규표현식 함수를 참고 (두가지 중 선택할수 있다: Perl과 POSIX extended).
URL-문자열을 위한 함수와 문자열을 encrypt/decrypt하는 함수도 지원된다. (mcrypt과 mhash).
그래도 원하는 기능을 찾을수 없다면, 문자 타입 함수로 참고.
문자열로 변환
(string)이나 strval()함수를 사용하여 값을 문자열로 변환할수 있다. 문자열 변환은 문자열이 필요한 표현식의 유효영역 내에서 자동적으로 이루어진다.이런 일은 echo()나 print()함수를 쓸때, 또는 변수값을 문자열과 비교할때 발생한다. 타입과 타입 저글링 매뉴얼 섹션을 읽음으로써 다음에서 설명하는 것을 더욱 명확하게 이해하게 될것이다. settype()함수도 참고.
boolean TRUE값은 문자열 "1"로 변환된다. FALSE 값은 "" (빈 문자열)로 표현된다. 이 원리로 논리값과 문자열값 사이에서 어느 방향으로든 변환이 가능하다.
integer나 부동소수점(float)은 각 자리의 숫자를 문자열로 변환할수 있다 (부동소수점수에 대한 지수부를 포함함).
배열은 항상 문자열 "Array"로 변환된다. 그래서 배열 안에 무엇이 들었는지 보기 위해 echo()나 print()를 쓴다고 해서 array의 내용을 덤프할수 없다. 한 요소를 보기 위해서는 echo $arr['foo']와 같이 써줘야 한다. 전체 내용물을 덤프/보기 위한 팁을 아래글에서 볼수 있다.
객체는 항상 문자열 "Object"로 변환된다. 만약 디버깅 목적으로 object의 멤버 변수를 모두 출력하고 싶으면, 아래 단락을 보라. 특정 객체를 만들어내는 클래스명을 확인하려한다면, get_class()를 사용하라.
자원은 항상 구조체 "Resource id #1"를 갖는 문자열로 변환된다. 1은 실행기간동안 PHP에 의해 설정되는 resource의 유일한 수이다. 자원의 타입을 얻고자 하면, get_resource_type()함수를 사용하라.
NULL 은 항상 빈 문자열로 변환된다.
위글에서 볼수 있듯이, 배열, 객체 또는 자원을 출력하는 것은 배열자체에 대한 어떤 유용한 정보도 제공해주지 않는다. 디버깅을 위해 그 값들을 출력하는 가장 좋은 방법인 print_r()과 var_dump() 함수를 참고할것.
PHP 값을 지속적으로 저장하기 위해 문자열로 변환할수 있다. 이런 방법을 직렬화(serialization)라고 한다. 함수 serialize()를 사용하면 된다. PHP 값을 XML 구조체로 직렬화할수도 있다. PHP 설정시 WDDX 지원 옵션을 추가하면 된다.
문자열을 숫자로 변환하기
문자열을 숫자값으로 취급할때, 결과값과 타입은 다음과 같이 결정된다.
그 값이 '.', 'e', 'E' 중에 어느것이든 포함하고 있으면 float으로 취급될것이다. 그렇지 않으면, 정수로 취급할것이다.
그 값은 문자열의 시작부분에 의해 주어진다. 문자열이 유효한 숫자 데이터로 시작되면, 이것이 사용되는 값이 될것이다. 그렇지 않으면 그 값은 0(zero)로 된다. 유효한 숫자 데이터는 선택적인 부호, 한자리 이상(선택적인 십진 포인트를 포함)의 수, 선택적인 지수가 될수있다. 지수는 한자리 이상의 수가 'e' 이나 'E'의 뒤에 오면 된다.
<?php
$foo = 1 + "10.5"; // $foo is float (11.5)
$foo = 1 + "-1.3e3"; // $foo is float (-1299)
$foo = 1 + "bob-1.3e3"; // $foo is integer (1)
$foo = 1 + "bob3"; // $foo is integer (1)
$foo = 1 + "10 Small Pigs"; // $foo is integer (11)
$foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2)
$foo = "10.0 pigs " + 1; // $foo is float (11)
$foo = "10.0 pigs " + 1.0; // $foo is float (11)
?>
이런 종류의 변환에 대한 더 많은 정보는 strtod(3)의 유닉스 매뉴얼 페이지에서 볼수 있다.
이 섹션의 어떤 예제를 테스트하려면, 예제를 복사해서 붙여넣으면 되고 무슨일이 일어나는지 확인하기 위해 다음 줄을 삽입할수 있다.
<?php
echo "\$foo==$foo; type is " . gettype ($foo) . "<br />\n";
?>
정수로 변환하여 한 문자의 코드를 얻을수 있다고 기대하지 마시오 (예를 들면 C에서 하는 것처럼). 캐릭터코드와 문자 사이의 변환을 위해서는 ord()와 chr()함수를 사용할수 있다.
문자열
30-Sep-2008 01:33
11-Sep-2008 08: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 03: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 12: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 12:46
<?php
$F = "F";
function F($s) { return $s; }
$filename = '<some code>';
echo "{$F(htmlspecialchars($filename))}";
?>
31-Mar-2008 07: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 07: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 01: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"
*/
?>
06-Feb-2008 10: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 08: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.
22-Jan-2008 06: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 09: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 04: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 12: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 12: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 02: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";
31-May-2007 08: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 05: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 10: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 08: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 12: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 10: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 12: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 08: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 08: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 12: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 12: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 07: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 03: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 03: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 05: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 05: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.
22-Jul-2002 11:26
PHP's double-quoted strings are inherently ill-featured - they will be a problem especially with computed code like in /e-evals with preg_replace.
bash and perl follow the widely accepted rule that all backslashes will escape the nextfollowing char, and nonalpha-chars will always get printed there as themselves whereas (the unescaped chars might have special meaning in regex). Anyway, it is a great way to just escape all nonalpha chars that you uncertain about whether they have special meaning in some places, and ye'll be sure they will get printed literal.
Furthermore, note that \{ sequence is not mentioned in the escape-char table! You'll get to know about it only "complex (curly) syntax". This can even more be a problem with evals, as they behave rather flaky like it _cannot_ be accomodated for computed code. Try all variants of `echo "hello \{\$world}"` removing one or more of the chars in the \{\$ part - have fun!
