天天看點

php入門第六天

    靈活的字元串。

   因為$表達的靈活性,我們可以用“映射”的方法,調出字元串或者函數。

<?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新項目,估計都會用這個功能。