skip to Main Content

Here my code:

<?php 
require('vendor/autoload.php');
use PhpMqttClientMqttClient;
use PhpMqttClientConnectionSettings;

$temperature = array();

$server   = '<address>';
$port     = 1883;
$clientId = 'id';

$connectionSettings = (new ConnectionSettings)
  ->setKeepAliveInterval(60)
  ->setLastWillQualityOfService(1);

  $mqtt = new MqttClient($server, $port, $clientId, MqttClient::MQTT_3_1);
  $mqtt->connect($connectionSettings, true);

$mqtt->subscribe('foo', function ($topic, $message) use ($temperature) {
    printf("Received message on topic [%s]: %sn", $topic, $message);
    $obj = json_decode($message);

    array_push($temperature, floatval($obj->temp));
    echo count($temperature);
}, 0);

$mqtt->loop(true);

I run this snipped with:

php mqtt_recv.php

then I send several message to the above topic, and the output is:

Received message on topic [foo]: {"temp":"20.0"}
1
Received message on topic [foo]: {"temp":"20.2"}
1
Received message on topic [foo]: {"temp":"20.4"}
1
Received message on topic [foo]: {"temp":"20.6"}
1

why on each call the parent variable $temperature is cleared?

I’m pretty sure it depends from the use of use because doing the same at root level leads to the expected behavior. Reading the docs I understand the "Inherited variable’s value is from when the function is defined, not when called" but after the first call, should not the variable keep the new values?

2

Answers


  1. By default, anonymous functions in PHP inherit by value, not by reference. So when you’re modifying the $temperature-variable, you’re only changing the local value. To pass a value by reference, you need to prefix it with an ampersand (&). The example below demonstrates this behavior and is taken from example #3 in the documentation page you linked.

    // Inherit by-reference
    $message = 'hello';
    $example = function () use (&$message) {
        var_dump($message);
    };
    $example(); // 'hello'
    
    // The changed value in the parent scope
    // is reflected inside the function call
    $message = 'world';
    $example(); // 'world'
    
    Login or Signup to reply.
  2. use is early binding. That means the variable values are COPIED upon DEFINING the closure. So modifying $temperature inside the closure has no external effect, unless it is a pointer, like an object is.
    To fix it, you need to pass $temperature variable as reference(&$temperature).

    $mqtt->subscribe('foo', function ($topic, $message) use (&$temperature) {
    printf("Received message on topic [%s]: %sn", $topic, $message);
    $obj = json_decode($message);
    
    array_push($temperature, floatval($obj->temp));
    echo count($temperature);
    }, 0);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search