靈活的字元串。
因為$表達的靈活性,我們可以用“映射”的方法,調出字元串或者函數。
<?php
$a = 'b';
$b = '123';
echo $$a; // 這可以輸出123。不過比較好的習慣是echo ${$a},這樣更清楚明了。
$c = 'd';
echo $c();
function d() {return '321';} // $c()調用的是d函數
?>
php的字元串和javascript和python類似,在單引号中不用把雙引号寫成\",在雙引号中也不用轉義單引号。但是,因為php中有有趣的$存在,是以雙引号要複雜一些。看例子。
<?php
$aa = 'abc';
echo "'$aa'";
echo "\{$aa}"; // 這樣寫 PHP5.1.1以前後會顯示不同的結果
echo "\\{{$aa}}"; // 這樣寫就沒問題
//另外如果我們因為php配置的原因而不能使用extract函數,也有替代的方法。
$data['a'] = 'a';
$data['b'] = 'b';
// 下面的代碼相當于 extract($data);
foreach ($data as $key=>$v)
{
${$key} = $v;
}
?>
雙引号中可以有變量,可以用"$a"或"{$a}"形式來表現,個人建議大家多用後面的寫法,第一編輯器會高亮,第二能寫更複雜的式子。要注意,雖然"'{$a}'"的結果和"'".$a."'"的結果一樣,但是{并非'"的簡寫,echo "'{__FILE__}'"和echo "'".__FILE__."'"結果是不同的。因為雙引号中的封閉區間是以 {$xxxx} 這種結構及${xxxx}結構。是以可以寫{$this->func()},不能寫{self::func()},或{常量}。
不過${xxxx}結構和雙引号外面的結構不一樣,我不太喜歡。但是在有的模版裡,如phpcms,你這樣寫<?php echo "{$a}"; ?>就會有問題,寫在<?php echo "${a}"; ?>就沒事了。
<?php
function demo() {return 'abc';}
function abc() {return '123';}
$func = function() {return 'function';}; // 需要php5.3以上版本
$abc = 'abc';
$abc1 = 'abc--one::';
echo ${demo().'1'};
echo ${demo('}}')}();
echo "\{{${demo()}()}:::{$func()}\}{\$";
$test = 'Test';
echo ":::<br/>{$test::func()}:::";
class Test
{
static public function func()
{
return 'static func';
}
}
?>
雖然php的雙引号很強大,但很多場合并不太需要, 要生成頁面,很多時候可以這樣寫:
$form .= '<input type="hidden" name="'.$name.'" value="'.form_prep($value, $name).'" />'."\n";
這個是CI架構中form_helper.php的form_hidden的一行代碼。
要輸出的單引号多時,用雙引号括字元串。反之用機關引号。單引号和雙引号相比,用來括字元串效率并不會高多少,雖然單引号隻需要轉義\\和\',雙引号的有
Sequence | Meaning |
\n | 換行 (LF or 0x0A (10) in ASCII) |
\r | 回車 (CR or 0x0D (13) in ASCII) |
\t | 水準方向的 tab(HT or 0x09 (9) in ASCII) |
\v | 豎直方向的 tab (VT or 0x0B (11) in ASCII) (since PHP 5.2.5) |
\f | 換頁 (FF or 0x0C (12) in ASCII) (since PHP 5.2.5) |
\\ | 反斜線 |
\$ | 美金dollar标記 |
\" | 雙引号 |
\[0-7]{1,3} | 符合該表達式順序的字元串是一個八進制的字元 |
\x[0-9A-Fa-f]{1,2} | 符合該表達式順序的字元串是一個十六進制的字元 |
這麼多要轉義,但我想程式在周遊每一個字元時,實際上它最初隻需要判斷 \ " $ ,可能還有 {。
那麼雙引号和單引号一樣多時應該怎麼輸出呢?我們先看一下别的語言的解決方案。
Python 可以用 ''' 或者 """ 來閉合字元串,這之中并不需轉義"和',有需要的話,可以寫成這樣 '''這樣'''+"'''"。
因為php是一個模版語言,是以想直接輸出的話(最好寫大引用的模版檔案裡),直接寫html就可以了。
如果不想直接輸出的話,有兩種方法。
方法一: 控制緩沖法。
<?php
$test_ob = '測試ob';
ob_start();
?>
直接寫的html碼<?php echo $test_ob; ?> ----
<?php
$buffer = ob_get_contents();
@ob_end_clean();
echo '這是後頭才輸出的:',$buffer;
/* test_ob.php */
具體方法見手冊:輸出緩沖控制。下面方法要直接些。
方法二: heredoc文法結構和nowdoc(文法結構自PHP 5.3.0以後) 。
Heredoc是以 <<<xxxx 開頭, 以 xxxx; 結尾;Nowdoc,是以 <<<'xxxx' 開頭, 以 xxxx;結尾。注意xxxx;結尾要在回車後且和回車語句之間不能有别的字元。
<?php
$a = 'abc';
$b = 'html';
$c = <<<html
'{$b}'
html;
$d = "'{$b}'
";
if ($c === $d)
{
echo <<<abc
\$c === \$d:::'{$a}' {$c}
abc<br/>
abc;
echo <<<'test'
\$c === \$d:::'{$a}' {$c}
'test'
test<br/>
test;
}
?>
Javascript沒有原生的方法,但是依靠html,還是可以解決問題。
下面寫個iframe異步送出的例子。
<?php
/* iframe_test.php */
if (isset($_POST['cmd']))
{
// 正規的寫法是引用模版檔案。
?>
<!--使用textarea是為了防止引号破壞表單-->
<textarea id="show-div"><?php
echo $_POST['textarea'];
?></textarea>
<script>
var a = document.getElementById("show-div").value;
parent.show(document.getElementById("show-div").value);
</script>
<?php
}
?>
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<title>Welcome to CodeIgniter</title>
</head>
<body>
<iframe name="iframe_show" width="0" height="0" scrolling="no" style="display:none">
</iframe>
<h1>js在檔案後面!</h1>
<form name="mainform" target="iframe_show" method="post" enctype="multipart/form-data">
<textarea name="textarea">abc<script>alert(123)</script>123</textarea>
<input type="submit" name="cmd" value="送出" />
<input type="reset" value="撤消" />
</form>
<div id="show">Hello World</div>
</body>
<style type="text/css">
</style>
<script>
//<![CDATA[
function show(str) {
alert(str);
document.getElementById("show").innerHTML = str;
}
//]]>
</script>
</html><?php /* iframe_test.php */
作為數組的鍵的字元串:
php的數組的鍵隻有兩種類型,整數和字元串,'0'~'9'會被認是整數或轉成整數。見下例。
<?php
$arr_type = array(
0x34 => '0x34',
1 => '1',
'1' => "'1'",
1.99 => '1.99',
true => 'true',
0 => '0',
false => 'false',
'0' => "'0'",
0.0 => '0.0',
0.01 => '0.01',
.99 => '0.99',
-1 => '-1',
'1.99' => "''1.99'
'",
);
var_dump($arr_type, json_encode($arr_type), json_encode($arr_type));
if (1 !== true)
{
echo count($arr_type),'<br/>';
echo $arr_type[1.99],'<br/>';
echo $arr_type[false],'<br/>';
echo $arr_type['1.99'],'<br/>';
echo $arr_type[-1],'<br/>';
echo $arr_type[0x34],'<br/>';
}
?>
上例的數組隻有五行,多少可以預見,但下面的echo 卻能用false 1.99這樣的非整數鍵正常輸出。程式設計是一種嚴格的事,我們不希望出現許多意外的結果;而且這種轉義一定程度上影響效率。别的語言的這種資料結構,會有嚴格模式和寬松模式,比如lisp有這兩種模式,python隻有嚴格模式(如hash={'1': 1}; print(hash[1]);#這個會報錯——話說python雖然說是腳本語言,但是最開始設計時,比别的腳本語言要嚴格的多,是以測試性比别的腳本語言好。如果你哪天想設計一個自己的語言,先要向嚴格方向設計,以後留個ini讓别人配置;寫好了的程式,由嚴格向寬松轉容易,寬松轉到嚴格模式,很多時候完全地不可能或目測上不可能)。但php的數組,隻有這種寬松模式,希望php5.6能出點新東西。
Javascript也差不多,不過鍵都是字元串。寫的代碼如果鍵是負數,不會轉成字元串。ture和flase會被轉成'true'和'flase'.。
<script>
var arr = {
a: '47a',
'b': 12,
1: '1',
/* -1: '-1', */
1.99: '1.99',
'-1': '-1',
false: 'false',
0: '0',
'0': 'char0',
};
var i;
var str = '';
for (i in arr) {
str += typeof(i)+': '+i+' => '+arr[i]+'\n';
}
if (1 !== true) {
alert([
arr['1'],
arr[1.99],
arr[-1],
arr['a'],
arr[false],
arr[0],
arr['0'],
str,
]);
}
</script>
Dart和Javascript差不多,也是隻能用字元串作鍵,但是并不會轉義。下面例子會報錯。個人并不看好dart的前景,隻是寫東西時一時興起,拿來測測看下。果然語言不同,便有各種微差别,想到自己很多時候php用多了,用js時便想當然以為也如此,便好笑了。下面的Dart代碼會報錯
void main() {
print("Hello, World!");
var a = {'1': 1};
var b = {1: 1}; // 報錯原因
print(a['1']);
print(a[1]); // 報錯原因
}
在有的配置下,php能這樣寫,$arr = array('key' => 'val'); echo $arr[key]; 但是這種寫法,php會首先看key是不是常量(php自帶的常量都有上千個),如果不是常量,就作字元串。是以這種寫法效率很低下,比$arr['key']慢幾倍(常量多的項目,還要更慢)。echo "$arr[key]"則和echo "{$arr['key']}的效率差不多,因為雙引号中不需要考慮常量。一般來說$arr[key]這種寫法少打字又清晰,但多打兩個' 會使你的程式環保一些,通用一些,也是不難做到的。
如果php的常量像變量一樣,前面有個字首,如#,反正有//代替#。一般寫$arr[key]就不用考慮常量,效率高又友善程式員。寫$arr[#key]的情況不多,有需要時寫成$arr['#key']。
當然,php這樣搞的話會明顯地讓程式和過去的項目不相容,那麼學erlang的(我比較不喜歡erlang那種從prolog那繼承的文法, 更習慣看c或lisp那種文法),使“變量”隻能使用大寫和下劃線命名,非純大寫和下劃線用于“原子”的命名;php自帶的常量都是大寫的,我見過的php項目,常量都是用大寫字母和下劃線命名,可能有極少不是,而表單的name值在大部分項目中都是小寫,這樣多數數組就隻用非純大寫和下劃線就可以了->>
//寫成像下面這樣
$arr[abc];
$arr[aBc];
$arr[BASEPATH];
$arr[AB_C];
$arr['AB_C'];
如果5.6能出個讓php隻認隻有大寫和下劃線組成的常量的功能,且用改個ini就實作的話,多數公司的php新項目,估計都會用這個功能。