導航:首頁 > 編程語言 > php非同步回調

php非同步回調

發布時間:2022-07-07 08:00:08

php 框架 怎麼使用回調函數

前言
最近在開發一個PHP系統,為了提高系統的擴展性,我想在系統中加入類似Javascript的事件處理機制,例如:我想在一篇新聞被添加以後,我想記錄一下日誌,用類似Javascript的代碼,應該是這樣寫的:
function fnCallBack( $news )
{
//將$news的信息記錄到日誌中
writeLog( $news->getTitle().' has been added successfully!');
}
$newsEventManager->addEventListener( 'add' , fnCallBack );
其中,fnCallBack函數是回調函數,addEventListener表示監聽newsEventManager的add事件。當一篇news被add以後,系統就會調用fnCallBack函數,從而完成writeLog的動作。
但是,PHP中的函數傳遞方法和Javascript有很大的不同。在Javascript中,函數也是對象,它可以很方便的當作參數傳遞,但是PHP不行。
$newsEventManager->addEventListener( 'add' , fnCallBack );
上面這行代碼中的fnCallBack,看上去好像是那個函數的句柄,但實質上它是一個字元串,並不是我們所要的函數。
為了實現我們的事件模型,有必要研究一下PHP的回調函數的實現方法。
全局函數的回調
這里的全局函數的意思,是直接使用function定義的函數,它不包含在任何對象或類之中。請看下面的例子
示例代碼
function fnCallBack( $msg1 , $msg2 )
{
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
call_user_func_array( $fnName , $params );
代碼說明:
這里使用了PHP內置的函數call_user_func_array來進行調用。call_user_func_array有兩個參數,第1個參數是一個字元串,表示要調用的函數名,第2個參數是一個數組,表示參數列表,按照順序依次會傳遞給要調用的函數。
效果如下:
類的靜態方法的回調
如果我們要回調的方法,是一個類的靜態方法,那怎麼辦呢?我們依然可以利用PHP內置的call_user_func_array方法來進行調用,請看示例:
示例代碼:
class MyClass
{
public static function fnCallBack( $msg1 , $msg2 )
{
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$className = 'MyClass';
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
call_user_func_array( array( $className , $fnName ) , $params );
代碼說明:
這段代碼和第1種方法的代碼很相似,我們將類名(MyClass)也作為call_user_func_array的第1個參數傳遞進去,就可以實現類的靜態方法的回調了。注意,這時call_user_func_array的第1個參數是一個數組了,數組的第1個元素是類名,第二個元素是要調用的函數名
運行結果:
(其實和第1種方法的結果是一樣的 ^_^ )
繼續研究
如果我用這種方法調用一個類的非靜態方法(也就是把static去掉),會出現什麼結果呢?請看下面代碼
class MyClass
{
public function fnCallBack( $msg1 , $msg2 )
{
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$className = 'MyClass';
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
call_user_func_array( array( $className , $fnName ) , $params );
運行結果
和前面的結果還是一樣的。。。
現在我為這個類添加一點屬性,並在方法中引用
class MyClass
{
private $name = 'abc';
public function fnCallBack( $msg1 , $msg2 )
{
echo 'object name:'.$this->name;
echo "<br />\n";
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$className = 'MyClass';
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
call_user_func_array( array( $className , $fnName ) , $params );
運行結果
出現解析錯誤,提示$this沒有在對象環境下出現,說明這個方法不能用類來調用,而是要用對象來調用。那我們就修改一下代碼,創建一個對象:
class MyClass
{
public function fnCallBack( $msg1 , $msg2 )
{
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$myobj = new MyClass();
$className = 'myobj';
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
call_user_func_array( array( $className , $fnName ) , $params );
運行結果:
提示call_user_func_array的第1個參數非法,也就是說,調用失敗。看來我們不能用call_user_func_array方法來回調一個對象的方法了,那麼如何實現對象方法的回調的?
對象的方法的回調
我先用最原始的字元串形式的調用方法嘗試了一下,如下所示:
class MyClass
{
private $name = 'abc';
public function fnCallBack( $msg1 = 'default msg1' , $msg2 = 'default msg2' )
{
echo 'object name:'.$this->name;
echo "<br />\n";
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$myobj = new MyClass();
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
$myobj->$fnName();
成功了,輸出結果
調用是成功了,不過如何把參數params傳給這個方法呢,如果把params直接傳進去,那麼它會作為1個參數,怎麼把params拆開來傳進去呢?
查了下PHP手冊,找到了create_function函數,這個方法可以用字元串來創建一個匿名函數,好,有思路了,可以創建一個匿名的函數,在這個匿名函數中,調用我們的回調函數,並把參數傳進去。
我先手動創建一個匿名函數anonymous,在這個函數中,用前面試出來的方法調用回調函數,如下所示:
class MyClass
{
private $name = 'abc';
public function fnCallBack( $msg1 = 'default msg1' , $msg2 = 'default msg2' )
{
echo 'object name:'.$this->name;
echo "<br />\n";
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$myobj = new MyClass();
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
function anonymous()
{
global $myobj;
global $fnName;
global $params;
$myobj->$fnName( $params[0] , $params[1] );
}
anonymous();
成功了,可以看到,對象的屬性name也輸出來了
然後,我用create_function來創建這個匿名函數,同時,代碼中的params[0],params[1]應該是動態生成的,代碼如下:
$strParams = '';
$strCode = 'global $myobj;global $fnName;global $params;$myobj->$fnName(';
for ( $i = 0 ; $i < count( $params ) ; $i ++ )
{
$strParams .= ( '$params['.$i.']' );
if ( $i != count( $params )-1 )
{
$strParams .= ',';
}
}
$strCode = $strCode.$strParams.");";
$anonymous = create_function( '' , $strCode);
$anonymous();
這段代碼可以定義一個匿名函數,並保存在$anonymous變數中,最後調用這個$anonymous,實現了方法的回調,如圖
PHP事件模型(觀察者模式)的實現思路
至此,PHP中的3種常見的函數類型(全局函數,類靜態函數,對象的方法)都可以回調了,可以實現文章一開始說的事件模型了 :)
事件模型模仿Firefox的Javascript實現,有3個方法,分別是
addEventListener:注冊一個事件上的響應回調函數
removeEventListener:刪除一個事件上的響應回調函數
fire:觸發一個事件,也就是循環調用所有響應這個事件的回調函數
不過,由於第2、第3種方法需要傳遞上下文(也就是類名和對象名),所以addEventListener和removeEventListener應該有3個參數,我是這樣設計的:
function addEventListener( $evtName , $handler , $scope = null )
第1個參數表示事件名,字元串類型
第2個參數表示回調函數名,字元串類型
第3個參數$scope是上下文環境,一共有3種類型,null表示傳入的handler函數是一個全局函數,字元串類型表示傳入的handler函數是scope類的靜態函數,對象類型表示傳入的scope是一個對象,handler函數是對象的一個方法。
function fire( $evtName , $params = null )
這個方法內,會讀取出所有響應evtName的handler,然後判斷它對應的scope,如果是null,則用本文第1種方法回調,如果是字元串,則用本文第2種方法回調,如果是對象,則用本文第3種方法回調。這樣,一個PHP的事件模型就可以實現了,而且可以將回調函數放在某個對象中。

Ⅱ PHP中的回調函數是怎麼實現的

第一種, 常規的php全局函數

function test($echo)
{
echo $echo, "\n";
}

$param = array("www.zeroplace.cn");

call_user_func_array(test, $param);
call_user_func_array("test", $param);

輸出:

www.zeroplace.cn www.zeroplace.cn

兩種調用方式都可以成功調用, 說明call_user_func_array調用常規php局函數時的第一個參數可以為函數本身,也可以為表示函數名的字元串。

第二種, 類的靜態方法
class TestC
{
static function test($echo)
{
echo $echo, "\n";
}
}

$param = array("www.zeroplace.cn");

call_user_func_array(array(TestC, "test"), $param);
call_user_func_array(array("TestC", "test"), $param);

輸出:

www.zeroplace.cn www.zeroplace.cn

這時傳第一個參數的時候傳了一個數據。數組的第一個元素可以為類本身,也可以為類名的一個字元串。第二個元素則是一個表示方法名的字元串。

第三種,對象的方法
class TestC
{
protected $_a = "hello word";

function test($echo)
{
$this->_a = $echo;
}

function show()
{
echo $this->_a, "\n";
}
}

$param = array("www.zeroplace.cn");
$obj = new TestC();
call_user_func_array(array($obj, "test"), $param);
$obj->show();
$obj->test("WEB應用開發");
$obj->show();

輸出:
www.zeroplace.cn WEB應用開發
這里是調用一個對象的方法。從test方法中設置對象的_a成員,然後通過show方法將它顯示出來,以驗證call_user_func_array調用方法時可以正確等到$this指針。這里輸出的結果表明已經上面的方法是奏效的。其實回調對象的方法還有一種更加簡單的方法,直接$obj->{$method}()就可以調用,只要{$method}是存在的。

Ⅲ php回調函數是什麼樣子的靠什麼原理運行

回調函數就是那些自己寫的,但是不是自己來調,而是給別人來掉的函數。
就像下面的odd()和even()函數一樣。
<?php
function odd($var)
{
return($var % 2 == 1);
}

function even($var)
{
return($var % 2 == 0);
}

$array1 = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);
$array2 = array(6, 7, 8, 9, 10, 11, 12);

echo "Odd :\n";
print_r(array_filter($array1, "odd"));//這里把array1的值依次傳入到odd這個函數裡面,這種方式就稱為回調
echo "Even:\n";
print_r(array_filter($array2, "even"));

?>

下面這個例子實現函數的回調
<?
function fnCallBack($msg1, $msg2)
{
echo 'msg1:'.$msg1;
echo '<br/>';
echo 'msg2:'.$msg2;
}
$fnName = 'fnCallBack';//函數名
$params = array('hello', 'world');//將要傳入到函數裡面的參數
call_user_func_array($fnName, $params);
?>

Ⅳ PHP中的回調函數是怎麼實現的

第一種,
常規的php全局函數
function
test($echo)
{
echo
$echo,
"\n";
}
$param
=
array("www.zeroplace.cn");
call_user_func_array(test,
$param);
call_user_func_array("test",
$param);
輸出:
www.zeroplace.cn
www.zeroplace.cn
兩種調用方式都可以成功調用,
說明call_user_func_array調用常規php局函數時的第一個參數可以為函數本身,也可以為表示函數名的字元串。
第二種,
類的靜態方法
class
TestC
{
static
function
test($echo)
{
echo
$echo,
"\n";
}
}
$param
=
array("www.zeroplace.cn");
call_user_func_array(array(TestC,
"test"),
$param);
call_user_func_array(array("TestC",
"test"),
$param);
輸出:
www.zeroplace.cn
www.zeroplace.cn
這時傳第一個參數的時候傳了一個數據。數組的第一個元素可以為類本身,也可以為類名的一個字元串。第二個元素則是一個表示方法名的字元串。
第三種,對象的方法
class
TestC
{
protected
$_a
=
"hello
word";
function
test($echo)
{
$this->_a
=
$echo;
}
function
show()
{
echo
$this->_a,
"\n";
}
}
$param
=
array("www.zeroplace.cn");
$obj
=
new
TestC();
call_user_func_array(array($obj,
"test"),
$param);
$obj->show();
$obj->test("WEB應用開發");
$obj->show();
輸出:
www.zeroplace.cn
WEB應用開發
這里是調用一個對象的方法。從test方法中設置對象的_a成員,然後通過show方法將它顯示出來,以驗證call_user_func_array調用方法時可以正確等到$this指針。這里輸出的結果表明已經上面的方法是奏效的。其實回調對象的方法還有一種更加簡單的方法,直接$obj->{$method}()就可以調用,只要{$method}是存在的。

Ⅳ php支付寶手機網站支付,非同步回調和同步回調裡面應該怎麼寫

你在支付寶商戶中心申請到相應的介面,例如大多數網站對接支付寶用的「即時轉賬介面」,申請到之後在支付寶商戶中心能夠找到相應的介面demo下載,裡面就有php的demo,參考裡面的非同步回調和同步回調的寫法即可

Ⅵ PHP回調函數到底是個啥

當做一個變數去理解比較容易,比如$a=function(){echo "aaa";};$aa();或者function a(){};將函數名作為一個變數去賦值;$b="a"; $b();一個是匿名函數作為變數去調用,另一個是函數名作為變數去調用,這就是回調函數常用的方式,簡單來說,就這把這樣調用函數的方式叫做回調函數,個人經驗分享而已,O(∩_∩)O哈哈~

Ⅶ php中的回調函數

回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響應。
php提供了兩個內置函數call_user_func()和call_user_func_array()提供對回調函數的支持。這兩個函數的區別是call_user_func_array是以數組的形式接收回調函數的參數的,看它的原型就知道了:mixed call_user_func_array ( callable $callback,array$param_arr ),它只有兩個參數。而call_user_func($callback,參數1,參數2,…)的參數個數根據回調函數的參數來確定的。

Ⅷ php裡面怎麼為數組的每個元素應用回調函數

具體看是想對元素如何操作,比如 array_filter():用回調函數過濾數組中的單元,可以使用回調函數對數組中元素進行篩選剔除元素;
如果是針對每個元素,使用其他函數的話,array_map :數組的每個元素應用回調函數,使用示例:
為數組每個元素執行+5計算;
$arr = [1,2,3,4,5];
#匿名函數操作
$res=array_map(function($item){return $item*2; },$arr);
array_map("函數名", 數組);支持使用 函數名+數據變數 使用。

Ⅸ 請教PHP的非同步處理,pcntl

client:
<?php
$client=newGearmanClient();
$client->addServer('127.0.0.1', 4730);//本機可以直接addServer(),默認伺服器端使用4730埠
$client->setCompleteCallback('completeCallBack');//先綁定才有效

$result1=$client->do('say','do');//do是同步進行,進行處理並返回處理結果。
$result2=$client->doBackground('say','doBackground');//非同步進行,只返回處理句柄。
$result3=$client->addTask('say','addTask');//添加任務到隊列,同步進行?通過添加task可以設置回調函數。
$result4=$client->addTaskBackground('say','addTaskBackground');//添加後台任務到隊列,非同步進行?
$client->runTasks();//運行隊列中的任務,只是do系列不需要runTask()。

echo'result1:';
var_mp($result1);
echo'<br/>';

echo'result2:';
var_mp($result2);
echo'<br/>';

echo'result3:';
var_mp($result3);
echo'<br/>';

echo'result4:';
var_mp($result4);
echo'<br/>';

//綁定回調函數,只對addTask有效
functioncompleteCallBack($task)
{
echo'CompleteCallback!handle result:'.$task->data().'<br/>';
}

worker:
<?php
$worker=newGearmanWorker();
$worker->addServer();
$worker->addFunction('say',function(GearmanJob$job){
$workload=$job->workload();//接收client傳遞的數據
echo'receive data:'.$workload.PHP_EOL;
returnstrrev($workload);//僅作反轉處理
});

//無際循環運行,gearman內部已有處理,不會出現佔用過高死掉的情況
while($worker->work()){
if($worker->returnCode() !== GEARMAN_SUCCESS){
echo'error'.PHP_EOL;
}
}

以上client輸出:
CompleteCallback!handle result:ksaTdda
result1:string(2) 「od」
result2:string(17) 「H:iZ943bixttyZ:87″
result3:object(GearmanTask)#2 (0) { }
result4:object(GearmanTask)#3 (0) { }
worker輸出:
receive data:do
receive data:doBackground
receive data:addTaskBackground
receive data:addTask

閱讀全文

與php非同步回調相關的資料

熱點內容
自己購買雲主伺服器推薦 瀏覽:419
個人所得稅java 瀏覽:759
多餘的伺服器滑道還有什麼用 瀏覽:189
pdf劈開合並 瀏覽:26
不能修改的pdf 瀏覽:750
同城公眾源碼 瀏覽:488
一個伺服器2個埠怎麼映射 瀏覽:297
java字元串ascii碼 瀏覽:78
台灣雲伺服器怎麼租伺服器 瀏覽:475
旅遊手機網站源碼 瀏覽:332
android關聯表 瀏覽:945
安卓導航無聲音怎麼維修 瀏覽:332
app怎麼裝視頻 瀏覽:430
安卓系統下的軟體怎麼移到桌面 瀏覽:96
windows拷貝到linux 瀏覽:772
mdr軟體解壓和別人不一樣 瀏覽:904
單片機串列通信有什麼好處 瀏覽:340
游戲開發程序員書籍 瀏覽:860
pdf中圖片修改 瀏覽:288
匯編編譯後 瀏覽:491