1. 程式人生 > 實用技巧 >PHP可回撥型別

PHP可回撥型別

一些函式如usort和call_user_func()可以作為使用者自對應函式做為回撥引數,回撥函式不止是簡單的函式,還可以是物件的方法(類方法),包括靜態方法。

使用者自定義函式作為回撥函式的引數,PHP將函式以string形式傳遞的。可以使用任何內建或者使用者自定義函式,除了PHP的語言結構如:array(), echo, empty(), eval(), exit(), isset(), list(), print或者unset()。

1,用usort()函式傳遞使用者自定義函式對美國日期進行排序:

 1 <?php
 2 /*
 3     用usort()函式對美國日期進行排序;
4 */ 5 6 #定義日期,美國格式,是月日年,一般的格式是日月年或者年月日;現在要將它排序為以年月日的格式從大到小或者從小到大排序 7 $dates = array('10-10-2011', '2-17-2010', '2-16-2011', '1-01-2013', '10-10-2012'); 8 9 #使用sort()函式對日期進行從小到大排序 10 echo "<p>Sorting the \$dates using the function sort().</p>"; 11 sort($dates); 12 print_r($dates); #列印輸出:Array ( [0] => 1-01-2013 [1] => 10-10-2011 [2] => 10-10-2012 [3] => 2-16-2011 [4] => 2-17-2010 )
13 14 #使用natsort()函式對人類認為的自然排序; 15 echo "<p>Sorting the \$dates using the function natsort().</p>"; 16 natsort($dates); 17 print_r($dates); #列印輸出:Array ( [0] => 1-01-2013 [3] => 2-16-2011 [4] => 2-17-2010 [1] => 10-10-2011 [2] => 10-10-2012 ) 18 19 #前兩種都不符合預期,試用usort()函式對$dates進行排序;
20 function sortDate($a,$b){ 21 if ($a == $b){ 22 return 0; 23 }else{ 24 #將日期進行分割,對應的月日年分別賦值給對應的month,day,year。 25 list($amonth, $aday, $ayear) = explode("-", $a); 26 list($bmonth, $bday, $byear) = explode("-", $b); 27 28 #呼叫str_pad()函式對月份字串進行填充。如果月份有兩位則不填充,如果不夠兩位就在其左側填充0; 29 $amonth = str_pad($amonth, 2, "0", STR_PAD_LEFT); 30 $bmonth = str_pad($bmonth, 2, "0", STR_PAD_LEFT); 31 32 #呼叫str_pad()函式對日期的字串進行填充。如果日期有兩位數則不填充,如果不夠兩位就在其左側填充0; 33 $aday = str_pad($aday, 2, "0", STR_PAD_LEFT); 34 $bday = str_pad($bday, 2, "0", STR_PAD_LEFT); 35 36 #由於年份是四位,就不需要進行填充了,練手的話可以寫一下 37 #ayear = str_pad($ayear, 4, "0", STR_PAD_LEFT); 38 #byear = str_pad($byear, 4, "0", STR_PAD_LEFT); 39 40 #對日期進行重組,按年月日的人類習慣進行重組 41 $a = $ayear . $amonth . $aday; 42 $b = $byear . $bmonth . $bday; 43 44 #返回值進行比較 45 return ($a > $b) ? 1: -1; //升序排序 46 #return ($a < $b) ? 1 : -1; //降序排列 47 } 48 } 49 50 echo "<p>Sorting the \$dates using the function usort().</p>"; 51 usort($dates, "sortDate"); #函式回撥,usort()函式回撥自定義函式sortDate(),以字串的形式作為引數傳遞到usort()。 52 print_r($dates); #列印輸出:Array ( [0] => 2-17-2010 [1] => 2-16-2011 [2] => 10-10-2011 [3] => 10-10-2012 [4] => 1-01-2013 ) 53 ?>

2,call_user_func()呼叫自定義函式:

1 <?php
2 #定義函式
3 function myCallBackFunction(){
4     echo "Hello, I am a PHPer!";
5 }
6 //將自定義函式myCallBackFunction以字串的形式作為值傳遞給回撥函式call_user_func();
7 call_user_func('myCallBackFunction'); #輸出Hello, I am a PHPer!
8 ?>

回到函式類與物件的應用:

  一個已被例項化的object的方法被作為array傳遞,下表0包含該object,下表1包含方法名。在同一個類裡可以訪問protected和private方法。

1,簡單呼叫:

 1 <?php
 2 class myClass{
 3     static function myCallBackMethod(){
 4         echo "Hello, I am PHPer.\n";
 5     }
 6     public function anotherCallBackMethod(){
 7         echo "Trump is a bad guy. His brain owned shit.";
 8     }
 9     protected function protectedMethod(){
10         echo "Secret garden 1.";
11     }
12     private function privateMethod(){
13         echo "Secret garden 2.";
14     }
15 }
16 
17 $newclass = new myClass(); #例項化類得到一個$newclass物件
18 //呼叫靜態方法
19 #物件myClass作為陣列下標0以及類方法myCallBackMethod作為陣列下標1,並且整體作為實參傳遞給回撥函式call_user_func()
20 call_user_func(array('myClass', 'myCallBackMethod')); #輸出:Hello, I am PHPer.
21 
22 #例項化的物件$newclass作為陣列下標0以及類方法myCallBackMethod作為陣列下標1,並且整體作為實參傳遞給回撥函式call_user_func()
23 call_user_func(array($newclass, 'myCallBackMethod')); #輸出:Hello, I am PHPer.
24 
25 #也可以這樣呼叫
26 call_user_func("myClass::myCallBackMethod"); #::是呼叫靜態方法的
27 
28 #呼叫常規方法
29 call_user_func(array('myClass', 'anotherCallBackMethod')); #會報錯,但是輸出:Trump is a bad guy. His brain owned shit.
30 call_user_func(array($newclass, 'anotherCallBackMethod')); #輸出:Trump is a bad guy. His brain owned shit.
31 call_user_func('myClass::anotherCallBackMethod'); #::是呼叫靜態方法的,不過這樣子呼叫好像只會出現一個:Strict standards的錯誤。輸出:Trump is a bad guy. His brain owned shit.
32 
33 #呼叫私有方法和受保護的方法報錯;
34 call_user_func(array($newclass, 'protectedMethod')); #不能訪問,cannot access protected method
35 call_user_func(array($newclass, 'privateMethod')); #不能訪問:cannot access private method
36 ?>

2,父子呼叫:

 1 <?php
 2 /*
 3     call_user_func()的父子呼叫
 4 */
 5 //定義父類A
 6 class A {
 7     public static function whoa(){
 8         echo "I am A\n";
 9     }
10     public function anotherMethodForCall(){
11         echo "Trump is a bad guy, his brain owned wholly shit.";
12     }
13     protected function MethodProtected(){
14         echo "Secret Garden.";
15     }
16     private function MethodPrivate(){
17         echo "Another secret Garden.";
18     }
19 }
20 
21 #定義類B並且繼承父類A
22 class B extends A {
23     public static function whob(){
24         echo "I am B\n";
25     }
26 }
27 $newa = new A();
28 $newb = new B(); #例項化子類B,得到物件$newb
29 
30 //呼叫靜態方法
31 call_user_func(array('B', 'whob')); #輸出I am B;
32 call_user_func(array($newb, 'whob')); #輸出I am B;
33 call_user_func(array('B','parent::whoa')); #呼叫類B的父類方法whoa,輸出I am A;
34 
35 //呼叫常規方法
36 call_user_func(array('A', 'anotherMethodForCall')); #報錯但是依舊輸出:Trump is a bad guy, his brain owned wholly shit.
37 call_user_func(array($newa, 'anotherMethodForCall')); #不報錯輸出:Trump is a bad guy, his brain owned wholly shit.Hello, PHP
38 call_user_func(array('B', 'anotherMethodForCall')); #報錯輸出:Trump is a bad guy, his brain owned wholly shit.
39 call_user_func(array($newb, 'anotherMethodForCall')); #不報錯輸出Trump is a bad guy, his brain owned wholly shit
40 
41 call_user_func(array('B', 'parent::anotherMethodForCall')); #報錯輸出:Trump is a bad guy, his brain owned wholly shit.
42 call_user_func(array($newb, 'parent::anotherMethodForCall')); #不報錯輸出:Trump is a bad guy, his brain owned wholly shit.
43 
44 call_user_func(array($newb, 'parent::MethodProtected')); #報錯 cannot access protected method
45 call_user_func(array($newb, 'parent::MethodPrivate'));  #報錯cannot access private method A
46 #先記下,以後再說
47 class C {
48     public function __invoke($name){
49         echo "Hello, " .$name. "\n";
50     }
51 }
52 $classc = new C();
53 call_user_func($classc, 'PHP'); #輸出:Hello, PHP
54 ?>