Looking for the code to connect to Mosquitto broker from your PHP code ? Here’s a simple example with step by step instructions. The complete functional code can be downloaded here.

Before starting off, you need to have php, Mosquitto broker and Mosquitto library for php installed. If you need guidance on installing Mosquitto library for PHP, do refer my instructions here.

The Basic PHP page

Let’s start from a simple PHP web page. Our page has only two buttons – one to publish and one to subscribe.

Below php file is saved as “mqtt-test.php”, in the web server’s root directory. If you are using Apache web-server, the default web root (also known as document root) will be /var/www/html.

<?php
echo '<form action="/mqtt-test.php" method="post">';
echo '<input type="submit" name="btn1" value="PUBLISH">';
echo '<input type="submit" name="btn2" value="SUBSCRIBE">';
echo '</form>';
?>

PHP page with Publish and Subscribe buttons

A little about the php code:

When we click on either of the buttons, an html POST request will be sent to the web server from the browser.

To submit data to the server, we need to place the buttons within an html <form> tag. The form tag has to have an action value. The form action tells the web server, which php file has to process the POST request. In our case, we are going to add the code to handle publish and subscribe action to our very mqtt-test.php itself. So, our form action will be “/mqtt-test.php”.

Now open a browser and type “localhost/mqtt-test.php” in the address bar. You should see a plain web page having “PUBLISH” and “SUBSCRIBE” buttons.

Nothing will happen if you click on the button though. So, how do we publish a message to a topic when we click on “PUBLISH” button ?

The Publish Logic

Now add the following code right after the ‘</form>’ statement in the php file.

if ($_POST["btn1"] == "PUBLISH")
	{
    publish_message('MESSAGE1', 'PUBTOPIC', 'localhost', 1883, 5);				    
	}

function publish_message($msg, $topic, $server, $port, $keepalive) {
	$client = new Mosquitto\Client();
	$client->onConnect('connect');
	$client->onDisconnect('disconnect');
	$client->onPublish('publish');
	$client->connect($server, $port, $keepalive);
	
	try {
		$client->loop();
		$mid = $client->publish($topic, $msg);
		$client->loop();
		}catch(Mosquitto\Exception $e){
				echo 'Exception';          
				return;
			}
    $client->disconnect();
    unset($client);					    
}

Let me explain the code above.

When we click on the PUBLISH button, the browser will send an html POST request with value “PUBLISH” for variable “btn1”. We test if the value for btn1 is PUBLISH and then try to publish a message.

Next we call publish_message(…) function. The function takes a message as a string, the topic name, MQTT server, port and the keepalive time.

Right now, my MQTT broker is running on the same machine, and hence I am using localhost as the server. 1883 is the default Mosquitto port.

Now let’s see the publish_message(…) function.

A client object is created using Mosquitto\Client library. This library must be already installed before you can try out this example. You can refer this earlier post by me to configure the library.

Once the client object is created, we then setup the callback functions for connect, disconnect and publish events. We have to code these functions to take some action during connect, disconnect and publish events. Sample code is given below.

Once the callbacks are set up, we connect to the broker.

The try…catch block that follows, attempts to publish a message using $client->publish(…). The $client->loop() function allows the library to wait for the action to complete.

// Call back functions required for publish function
function connect($r) {
		if($r == 0) echo "{$r}-CONX-OK|";
		if($r == 1) echo "{$r}-Connection refused (unacceptable protocol version)|";
		if($r == 2) echo "{$r}-Connection refused (identifier rejected)|";
		if($r == 3) echo "{$r}-Connection refused (broker unavailable )|";        
}
 
function publish() {
        global $client;
        echo "Message published:";
}
 
function disconnect() {
        echo "Disconnected|";
}

Now, if you refresh the page on the browser and then click on PUBLISH button, it should publish “MESSAGE1” to the topic “PUBTOPIC”. To test this, we need to open a terminal and then subscribe to the topic using Mosquitto_sub client.

Publish example

The Subscribe Logic

Now that the message is published, let’s see how we can subscribe to a topic and read messages from it. We shall implement the logic for “SUBSCRIBE” button.

Add the below code to the php file. Don’t worry if you are getting confused about where to add this code. You can download the complete php file from the download link on this page.

$statusmsg = "";
$rcv_message = "";

if ($_POST["btn2"] == "SUBSCRIBE")
	{
	$statusmsg = "";	
	$rcv_message = "";
	
	read_topic('SUBTOPIC', 'localhost', 1883, 60, 5);	
	
	if(!empty($rcv_message) )
		{
		echo $statusmsg."RCVD|" . $rcv_message ;	
		}
	else
		{
		echo $statusmsg."TIMEDOUT"; 	
		}		
	}

function read_topic($topic, $server, $port, $keepalive, $timeout) {
	$client = new Mosquitto\Client();
	$client->onConnect('connect');
	$client->onDisconnect('disconnect');
	$client->onSubscribe('subscribe');
	$client->onMessage('message');
	$client->connect($server, $port, $keepalive);
	$client->subscribe($topic, 1);
	
	$date1 = time();
	$GLOBALS['rcv_message'] = '';
	while (true) {
			$client->loop();
			sleep(1);
			$date2 = time();
			if (($date2 - $date1) > $timeout) break;
			if(!empty($GLOBALS['rcv_message'])) break;
	}
	 
	$client->disconnect();
	unset($client);						
} 

Similar to the publish function, in addition to the connect, publish and disconnect, we set up call back functions for subscribe and message events.

The subscribe function is called when the library connects to the broker and message function is called when a message is received.

The read_topic(…) function has to wait until a message arrives on the topic “SUBTOPIC” to exit from the while loop. This means, when you press the SUBSCRIBE button, the browser sends a POST request and then waits indefinitely for the page to refresh. This does not sound great. So, I added a timeout for the infinite while loop. The $timeout value can be any number of seconds. Right now, I’m using a 5 second timeout. If any message is received on the topic within 5 seconds, it will come out of the loop and print the message. Otherwise, it will wait for full 5 seconds and then print “TIMEDOUT”.

//Additional callback functions required for subscribe
function subscribe() {
                       //**Store the status to a global variable - debug purposes
		$GLOBALS['statusmsg'] = $GLOBALS['statusmsg'] . "SUB-OK|";
}

function message($message) {
                       //**Store the status to a global variable  - debug purposes
		$GLOBALS['statusmsg']  = "RX-OK|";

                       //**Store the received message to a global variable
		$GLOBALS['rcv_message'] =  $message->payload;
}

To test this out, after pressing the SUBSCRIBE button, within 5 seconds, you need to publish a message to the topic “SUBTOPIC”.

Subscribe Example

Download the complete code from this link.

Do let me know what you think. If you have any queries, please post a comment below and I’ll try my best to answer them.

Mosquitto PHP library on RaspberryPi - Installation
Connecting a Relay Module with NodeMCU

Written by Justin Jose

He is a post graduate in computers and has more than 14 years of industry experience with some of the leading Information Technology companies in India. Data-centric computing, ranging from data architecture to analytics is his area of interest.

This Post Has 3 Comments

  1. mohan

    hi
    if we are have server and client in different systems how can we test?
    i am using server with public ip and my client i am using raspberry pi how we use above code?

  2. mohan

    please can you help on this.
    if we use broker and webpage in different devices where to modify code.

    • Justin Jose

      You can try replacing “localhost” with your public server’s IP address or the server’s domain name. Let me know if this worked