Part 1 Grammer
尽管PHP的语法已经很松散,写起来很“爽”。但是对于学过 Java 的“完全面向对象程序员“来说,PHP程序设计语言里,还是有一些的坑的。下面请让我来盘点一下。
Parse error: syntax error, unexpected T_STRING, expecting T_FUNCTION in......
错误原因:在PHP语法中,声明任何函数,函数名的前面需要 function 关键字。
<?php //错误代码如下 class Test{ __construct(){ echo 'I am construction!'; } }
正确示例:每一次声明函数(方法),都要写上“function”这个关键字。无论您想声明的是 __construct()这类魔术方法,还是自定义函数,都逃不出 function 的手掌心。
<?php class Test{ //正确代码如下 function __construct(){ echo 'I am construction!'; } }
PHP Fatal error: Class Service_Page_Statistic_ZhiziBase contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Service_Page_Statistic_ZhiziBase::executeHook) in /home/map/odp_wmaudit/app/wmaudit/models/service/page/statistic/ZhiziBase.php on line 18
Fatal error: Access to undeclared static property: ......
错误原因:self::只能指向静态属性,而指向非静态属性只能用 $this->。
<?php //错误代码 class Person{ function __construct($name){ self::$name = $name; } private $name; } $paul = new Person('paul');
正确方法:self::指向静态属性,$this->指向非静态属性。
<?php //正确代码 $this class Person{ function __construct($name){ $this->$name = $name; } private $name; } $paul = new Person('paul');
<?php //正确代码 self:: class Person{ function setBirthday($date){ self::$birthday = $date; } static private $birthday; } $paul = new Person(); $paul->setBirthday('1990-01-01');
Fatal error: Cannot redeclare A::__construct() in......
错误原因:PHP不支持函数重载
解决方法:使用PHP内置函数 func_num_args() 、func_get_arg() 、func_get_args()来模拟实现OOP的函数重载
<?php class Test{ function __construct(){ switch(func_num_args()){ case 0: echo 'no argument'; default: echo 'the number of arguments is '.func_num_args(). '<br />'; $argumentArray = func_get_args(); //遍历方法一 foreach($argumentArray as $key => $value){ echo 'the No'. $key. ' argument is '. $value. '<br />'; } echo '<br />'; //遍历方法二 for($i=0; $i<func_num_args(); $i++){ echo 'the No'. $i. ' argument is '. func_get_arg($i). '<br />'; } } echo '<hr />'; } } new Test(); new Test(1); new Test(1,2,3);
Warning: file_get_contents(0): failed to open stream: No such file or directory in
错误原因:字符串相加结果“意外”等于“0”。
解决方法1:“点”操作符(.)连接字符串。
<?php $url = "http://op.juhe.cn/onebox/train/query?"; $param = "name=Tank&age=22"; $data = file_get_contents( $url. $param );
解决方法2:使用PHP内置函数 implode() 将数组连接成字符串。
<?php $url = "http://op.juhe.cn/onebox/train/query?"; $param = "name=Tank&age=22"; $url = implode('', array($url, $param)); $data = file_get_contents( $url );
PHP Fatal error: Class ...... contains 1 abstract method and must therefore be declared abstract or implement the remaining methods ([类名]::[方法名]) in /home/....../xxx.php on line 18
错误原因:该类也需要是抽象类。如果一个普通类包含了抽象方法,那么该类被实现了怎么办?被实现的时候,类中的抽象方法还没有被定义,这一定是不安全的。另外,PHP 中的抽象方法都是完全抽象的。
解决方法:使声明了抽象方法的类都定义为抽象类。
Part 2 语言本身
变量的引用
PHP 引用有毒。PHP 的引用和 C++ 类似,但是不完全一样,使用不当会引入bug。
foreach($data as &$val) { &val = 1; }
数组插入顺序
PHP 数组是基于 HashTable 实现的,但不同于 C++ STL 的 std::map(如下定义)。PHP 的 key 是不排序的,其遍历顺序会遵从“插入时的顺序”。
template< class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator<std::pair<const Key, T> > > class map;
下面这段关于 std::map keys 排序的介绍,很好地诠释了std::map 是如何运作的。以辅助理解 PHP 的数组。
std::map
is a sorted associative container that contains key-value pairs with unique keys. Keys are sorted by using the comparison function Compare
.