为啥 $handler 在回调中得到不同的值?

Posted

技术标签:

【中文标题】为啥 $handler 在回调中得到不同的值?【英文标题】:Why $handler is getting different value inside callback?为什么 $handler 在回调中得到不同的值? 【发布时间】:2016-02-22 17:33:36 【问题描述】:

每当我在回调中打印处理程序的客户端时,即使添加了几个客户端,它也会显示为空。

我对 php 很幼稚,似乎每次我调用回调函数时都会传递处理程序的新对象。


    <?php

    $handler=new Handler();

    $server = ioserver::factory(
       new HttpServer(
           new WsServer(
            $handler
           )
       ),
       9090   
    );
    $callback = function($msg) 
    echo " [x] Received ", $msg->body, "\n";
    echo $handler->test."\n";
    ;
    $pid=pcntl_fork(); 
    if ( $pid == -1 )        
        echo "server start fork failed";
        exit(1);
     else if ( $pid ) 
        $server->run();
     


    $connection = new AMQPStreamConnection('localhost', 5672, 'guest',     'guest');
    $channel = $connection->channel();
    $channel->queue_declare('hello', false, false, false, false);
    $channel->basic_consume('hello', '', false, true, false, false, $callback);
    while(count($channel->callbacks)) 
       $channel->wait();
    echo count($channel->callbacks);
    

    ?>

下面是处理程序文件


    <?php
    namespace MyApp;
    use Ratchet\MessageComponentInterface;
    use Ratchet\ConnectionInterface;
    class Handler implements MessageComponentInterface 

    public $clients;  
    public $test="Test";

    private $handler;
    public function __construct() 
        
        $this->clients = new \SplObjectStorage;
    

    public function onOpen(ConnectionInterface $conn) 
    
        "echo  added";
        $this->clients->attach($conn);
    

    public function onMessage(ConnectionInterface $from, $msg) 
                
        $this->test="onMessage";

        foreach ($this->clients as $client) 
            if ($from !== $client) 
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            
        
    
    public function sendAll($msg) 
                

        $this->test="sendAll";
        foreach ($this->clients as $client) 
            $client->send($msg);        
        
    

    public function onClose(ConnectionInterface $conn) 
    
        $this->clients->detach($conn);
    

    public function onError(ConnectionInterface $conn, \Exception $e) 
         
        $conn->close();
    
    public function getInstance()
        if(empty($this->handler))
        
            $this->handler=new Handler();
        
        return $this->handler;
    

     

    ?>

【问题讨论】:

$handler 将超出您的回调范围....$callback = function($msg) use($handler) echo " [x] Received ", $msg-&gt;body, "\n"; echo $handler-&gt;test."\n"; ; 也许 我已经尝试过你的方法但没有用,我还尝试使用 $GLOBAL 来保存处理程序并在回调中使用它。看起来当我们将对象传递给 WsServer 时,它被克隆了,现在我们有 2 个处理程序副本,这就是为什么我们为“测试”变量获得相同的值,为了消除这个错误,我还尝试将引用传递给 WsServer,但仍然无法正常工作。 【参考方案1】:

使用单例。

不是这个:

// class Handler... 
private $handler;
...
public function getInstance()
    if(empty($this->handler))
    
        $this->handler=new Handler();
    
    return $this->handler;

$handler=new Handler();

但是这个:

// Changed class Handler... 
private static $handler;
...
public static function getInstance()
    if(empty(self::$handler))
    
        self::$handler=new Handler();
    
    return self::$handler;

$handler=Handler::getInstance();

[edit] Handler::getInstance() 当前不是静态的,在我写完答案后发现了这一点。

【讨论】:

以上是关于为啥 $handler 在回调中得到不同的值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥用 viewLifecycleOwner 观察到的 LiveData 在 onDestroyView 之后会得到回调?

为啥我的音频队列输入回调中的数据包编号会有所不同?

为啥 cProfile 会导致函数返回不同的值?

Javascript:为啥不能在回调函数中获取变量?

为啥我的 iOS 录音回调中的音频缓冲区未满?

为啥 Chrome 和 Firefox 以不同方式处理 jQuery ajax() 回调中设置的 javascript 变量?