在開始之前,必須知道的事情
PHP Class 和 call by reference
- PHP Class 泛指了類別(classes), 介面(interfaces), 函數(functions) 和常數(constants).
- PHP "objects are passed by references by default". 請注意物件屬性的值會在你不注意的地方被更新到了。
- PHP Class property 宣告沒有像 Objective-C 提供 immutale or mutale type. 或是像 Java 的
final
property. 但你可以用const
去保護你的物件屬性。 - PHP7.1 之後,可以加上
public
orprivate
的可視性描述(visibily modifiers
)針對物件的屬性。 - 除非你很清楚你在做什麼,不然千萬不要直接對 function input的 variable做修改. Never change the input variables to a function directly.
- 但是 PHP Array
=
(assign)要小心處理, 如果是存的內容為 scalar type,行為是 copy by value
一些常搞混的字詞和用法
require_once vs require
盡量使用 require_once,尤其是靜態的設定檔,給PHP好的效率。
require vs include
include找不到檔案只會有 warnning。 require 找不到檔案會 fatal error. 強烈建議使用require及早在開發階段發現錯誤。
字串 Single Quoted and Double
- Single Quoted 的字串,PHP並不會去嘗試解義(evalute)
變數
和相關的跳脫符號Escaped characters
例如:\n
- 一般來說,如果不需要變數解義和跳脫,建議使用 Single Quoted。有文件指出這樣的效能比較好。
PHP String 有四種表示方法,建議閱讀PHP String官方文件:
- Single Quoted
- Double Quoted
- Heredoc
- Nowdoc
Heredoc syntax 用
<<<
接著換行,結束一定要在 NewLine的最前面。
<?php
$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;
- 請參考範例有關 Single quoted和Double的差別:
<?php
echo 'single quote\n' . "\n";
echo "double quote\n";
$var1 = 'Hello';
$var2 = 'World!';
echo '$var1 $var2' . "\n";
echo "$var1 $var2" . "\n";
$var3 = 3;
$var4 = 4;
echo '$var3 + $var4 = ' . "$var3 + $var4 = " , $var3 + $var4, "\n";
Output:
scalar types 值量型別
- PHP scalar types : 整數(integer), 浮點數(float), 字串(string) and 布林(boolean).
- Not scalar types : 陣列(array), 物件(object) 和 資源( resource).
is_scalar(mixed $var)
可以幫忙判斷。echo
不能印出非scalar types內容,例如 array 會得到這樣的訊息:PHP Notice: Array to string conversion
。請參考範例
<?php
$var1 = 'This is a string'; // scalar: string
$var2 = 3.14; // scalar: float
$var3 = 5; // scalar: int
$var4 = false; // scalar: boolean
$var5 = array('aaa', 'bbb', 3, 3.14);
function customPrintVar($var)
{
if (is_scalar($var)) {
echo "\n === scalar type ===";
echo $var;
} else {
echo "\n === not scalar type ===";
var_dump($var);
}
}
// Use {} input dynamic variables
for ($i=1; $i < 6; $i++) {
customPrintVar(${'var'.$i});
};
echo() vs print() vs var_dump() vs print_r() vs var_export()
echo() and print()
echo
和print
只支援字串的輸出,echo 和 print 並不是 function,他是PHP原生支援(language construct),所以可以不用()
。echo 和 print 的差別在於 echo 支援多個 inputs 以及回傳型別 echo 回傳 void,print 永遠回傳 1。
請參考範例
<?php
print("Hello World");
print "print() also works without parentheses.";
print "This spans
multiple lines. The newlines will be
output as well.";
echo "echo() also works
multiple lines. The newlines will be
output as well.";
// Strings can either be passed individually as multiple arguments or
// concatenated together and passed as a single argument
echo 'This ', 'string ', 'was ', 'made ', 'with multiple parameters.', chr(10);
echo 'This ' . 'string ' . 'was ' . 'made ' . 'with concatenation.' . "\n";
- 注意: echo 支援多字串的輸入,和單一用點連字串。所以parentheses的使用要注意,例如下面的範例:
echo "======== multiple arguments vs parentheses with concatenated ===== \n";
echo "Sum: ", 1 + 2;
echo "Hello ", isset($name) ? $name : "John Doe", "!";
echo 'Sum: ' . (1 + 2);
echo 'Hello ' . (isset($name) ? $name : 'John Doe') . '!';
注意: 如果 $stringA 和 $stringB 是非常大的字串,
echo $stringA, $stringB
的效能遠超過字串連接。因為用字串連接需要產生額外的記憶體(extra temp memory
)。注意:因為 echo 和 print 並不是 function,所以並不支援 PHP
variable functions
的特性。注意:常用的原生支援(language construct)還包含 echo, print, unset(), isset(), empty(), include, require等等。
注意:因為echo並不是 function,所以不能放在
?: ternary operators
內使用。但是 print 可以。請參考下面範例 DemoOutput
$some_var = 1;
// Because echo does not behave like a function, the following code is invalid.
($some_var) ? echo 'true' : echo 'false';
// However, the following examples will work:
($some_var) ? print 'true' : print 'false'; // print is also a construct, but
// it behaves like a function, so
// it may be used in this context.
echo $some_var ? 'true': 'false'; // changing the statement around
var_dump vs var_export and print_r
var_dump
,print_r
, 和var_export
都是為了 debug 使用。var_dump
會顯示PHP的型別資訊var_export
只會顯示合法的 PHP code。print_r
顯示容易閱讀的結果。
注意:
print_r
的輸出結果,有時會造成空字串
和boolean
的誤判,強烈建議使用 var_dump or var_export。可以參考下列的範例 和 stackoverflow。
$demoArray = array('', false, 42, array('42'));
// var_dump(array('', false, 42, array('42')));
echo "\n ==== var_dump ==== \n";
var_dump($demoArray);
echo "\n ==== var_export ==== \n";
var_export($demoArray);
echo "\n ==== print_r ==== \n";
print_r($demoArray);
var_dump
可以多的變數輸出,其function 回傳值為void
。
$var1 = 1;
$var2 = 2.0;
$var3 = array($var1, $var2, 3.14);
echo "\n ==== var_dump multi-arguments ==== \n";
var_dump($var1, $var2, $var3);
var_export
和print_r
可以將輸出的結果用變數儲存,而不直接 output。var_export
輸出為valid PHP code
,這是意味著輸出可以之後給eval()
執行。 請參考下列的範例 VarExport
<?php
namespace StudyGroup\LanguageFeatures\PHPClass;
class DemoVarExport
{
public $var1;
public $var2;
public static function __set_state($an_array)
{
$obj = new DemoVarExport;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}
$a = new DemoVarExport;
$a->var1 = 5;
$a->var2 = 'TestingString';
echo "\n === var_export === \n";
var_export($a);
echo "\n ==== var_export to a string ==== \n";
$evalStringForClassA = var_export($a, true);
// generate $b use eval string
// Notes: must implement __set_state method in VarExportDemo class. Without that, got the error
// Fatal error: Uncaught Error: Call to undefined method StudyGroup\LanguageFeatures\PHPClass\VarExportDemo::__set_state()
eval('$b = ' . var_export($a, true) . ';');
echo "\n ==== var_dump evaled ClassB ==== \n";
var_dump($b);
//comparison operator (==), object variables are compared in a simple manner, namely: Two object instances are equal if they have the same attributes and values (values are compared with ==), and are instances of the same class.
// Notes: use single quote '' because we want to print $a=$b string.
echo "\n" . '$a==$b' . "\n";
echo $a == $b ? true : false; // output will be true
echo "\n";
注意:上面的例子比較好的方式用
serialize()
和unserialize()
去保存和還原 Objects,更複雜的情況可以搭配 magic methods:__sleep()
和__wakeup()
。注意: eval() 會有安全性的問題,尤其是執行使用者所輸入的資料。記住下面PHP之父的話:
If eval() is the answer, you're almost certainly asking the
wrong question. -- Rasmus Lerdorf, BDFL of PHP
define() vs const 常數定義
如果你嘗試在 class 內 function scope 外使用 define() 你會得到 PHP Parse error: syntax error, unexpected 'define' (T_STRING), expecting function (T_FUNCTION)
的錯誤訊息。
也就是,你不能寫這樣的代碼:
<?php
namespace StudyGroup\LanguageFeatures\PHPClass;
class DemoImmutable
{
define('ANIMALS', array('dog', 'cat', 'bird'));
function myFunction() {
}
}
最主要的原因是底層的不同
define()
是 run-time constants 而const
是 compile-time constants.define()
是 global scope 或者在某個 namespace,所以不能用來定義 class-scope 的常數。define()
可以用在 if() 但const
不能用在 if()
PHP7 array const 可以用 define() or const 來定義。但array的內容只能 scalar data (boolean, integer, float and string)。
可以參考下列的程式碼
<?php
namespace StudyGroup\LanguageFeatures\PHPClass;
const TAIPEI_ID = 1;
define('StudyGroup\LanguageFeatures\PHPClass\TAIWAN_ID', 2);
echo \StudyGroup\LanguageFeatures\PHPClass\TAIPEI_ID . "\n"; // 1
echo \StudyGroup\LanguageFeatures\PHPClass\TAIWAN_ID . "\n"; // 2; note that we used define(), but the namespace is still recognized
// define a constant as a scalar expression
define('TRANSPORT_METHOD_SNEAKING', 1 << 0); // OK!
const TRANSPORT_METHOD_WALKING = 1 << 1; // OK!
// Next, conditional constants.
define('HOBBITS_FRODO_ID', 1);
if (HOBBITS_FRODO_ID==1) {
define('TRANSPORT_METHOD', TRANSPORT_METHOD_SNEAKING); // OK!
echo TRANSPORT_METHOD . "\n"; // 1
// const PARTY_LEADER_ID = HOBBITS_FRODO_ID // Compile error: const can't be used in an if block
}
// Final, Class constant
class DemoImmutable
{
const ANIMALS = array('dog', 'cat', 'bird');
//define('VEHICELS', array('moto', 'bus')); // Error. define can't use in class scope
}
var_dump(DemoImmutable::ANIMALS);
可以參考這篇 和 stackoverflow
- 注意:define宣告不能用
hyphens -
,當需要echo這變數時,會變成字串的減法。請參考範例
<?php
define('VERSION-DESC', 'Version 1.0');
define('VERSION_DESC', 'Version 1.0');
echo "=== define use hyphens ===\n";
echo VERSION-DESC, "\n";
echo "=== define with under score ===\n";
echo VERSION_DESC, "\n";
output
0
Version 1.0
Variable variables 和 Variable functions
final, static, and const
- 作用範圍
Scope | final | static | const |
---|---|---|---|
Class | X | ||
Methods | X | X | |
Properties | X | X | |
Variables | X |
PHP Operators
這邊列出PHP特有的 Operators,是在其他語言比較少見到的:
- arrow operator
->
- Scope Resolution Operator or double colon
::
- Spaceship
<=>
- Type operator
instanceof
一個好的 if (To be if free)
不要回傳 null,應該要回傳一個空的 list object
[]
。Never return a null, instead return a Null Object, i.e an empty list.
不要傳 error codes,應該要用 Exception。
Don't return error codes, instead throw an Exception (Runtime please!)