PHP Classes

PHP Non Blocking CLI: Implement CLI scripts that do not block the output

Recommend this page to a friend!
  Info   View files Example   View files View files (4)   DownloadInstall with Composer Download .zip   Reputation   Support forum   Blog    
Last Updated Ratings Unique User Downloads Download Rankings
2023-09-20 (5 months ago) RSS 2.0 feedNot enough user ratingsTotal: 43 This week: 1All time: 10,745 This week: 82Up
Version License PHP version Categories
nb_cli 1.0BSD License8Console, PHP 8
Description 

Author

This package can implement CLI scripts that do not block the output.

It provides a class that can be extended to implement console-based command line interface (CLI) scripts to implement applications that do not block when they need to write the output or read the script's input.

This class can process the CLI parameters passed by the user to the script and call functions of plugin classes to process the parameters to execute the actions that need to be done to implement the parts of the hand.

Developers may write plugin classes that implement the actions for different events and own custom CLI scripts.

Internally, this class has a main loop that runs at a set speed. Each plugin can run at its speed within the speed of the main loop.

The input and output of the current script can be set to non-blocking, so the hand does not wait for the console to read data from the user input nor wait for the output to be displayed in the console.

Innovation Award
PHP Programming Innovation award nominee
September 2023
Number 4
PHP can run scripts from the command line interface (CLI). This possibility allows PHP to develop scripts that system administrators or automation scripts can use regularly to perform maintenance tasks.

More advanced PHP scripts can be developed to use the console to output information and read the user input. By default, the PHP functions to read and write to the console block until the input is fully read or the output is entirely written.

The blocking mode can slow the PHP scripts and make it hard to develop programs that interact quickly with the users.

This package provides a solution that makes console-based PHP programs work like event-driven programs. It implements event loops and callback handlers to process several console-based events.

This way, developers can use plugin classes to implement programs that interact with users in a faster way and output information to the console in a way that is faster than using the blocking mode to read and write data to the console.

Manuel Lemos
Picture of JImmy Bo
  Performance   Level  
Name: JImmy Bo is available for providing paid consulting. Contact JImmy Bo .
Classes: 14 packages by
Country: United States United States
Age: ???
All time rank: 1214173 in United States United States
Week rank: 21 Up4 in United States United States Up
Innovation award
Innovation award
Nominee: 8x

Winner: 1x

Example

<?php

   
include_once('class.nb_cli_1.0.php');

   
# An example test plugin that would be the part added by the user to create their program
   
class my_plugin extends nb_plugin {
        private
$stdin;
        private
$stdout;

       
// so we can give this plugin some loop independence (run on their own timers)
       
private $next_run = []; // when a loop should run // An array so we can have multiple loops.
       
private $loop_running = []; // so we don't engage another loop until the other is finished processing

       
public function __construct() {
           
// Set non-blocking mode for STDOUT
           
stream_set_blocking(STDOUT, false);

           
// Set non-blocking mode for STDIN
           
stream_set_blocking(STDIN, false);

           
$this->stdin = fopen('php://stdin', 'r');
           
$this->stdout = fopen('php://stdout', 'w');

           
$this->welcome();
        }

        public function
out($msg) {
           
fwrite($this->stdout, $msg);
        }

        public function
handleCommand($command) {
           
// process commands from user when they press enter
           
switch ($command) {
                case
'test':
                   
$help = "Test command\n";
                   
// fwrite($this->stdout, $help);
                   
$this->out($help);
                    break;

                case
'help':
                case
'h':
                   
$help = "---\n";
                   
$help .= "Showing help for *TestPlugin*\n";
                   
$help .= "Available commands:\n";
                   
$help .= " test - Test command\n";
                   
$help .= "---\n\n";

                   
$this->out($help);
                    break;
            }
        }

        public function
welcome() {
           
// triggered by main loop when code requests a welcome
           
$welcome = "-- NonBlockingCLI test server --\n";
           
$welcome .= "Welcome to the NonBlockingCLI test server.\n";
           
$welcome .= "Type 'h' or 'help' for a list of commands.\n";
           
$welcome .= "Type 'quit' to exit.\n";
           
$welcome .= "\n\n";

           
$this->out($welcome);
        }

        public function
run() {
           
// this loop runs at main class speed
           
$this->run_loop_1(); // output current time every second
            // .. can add other loops. Use run_loop_1 as an example.
       
}

        public function
run_loop_1() {
           
$loop_key = 1; // for $this->next_run and $this->loop_running

            // we want to take a slot in next_run in case we have other loops.
           
if (!isset($this->next_run[$loop_key])) {
               
$this->next_run[$loop_key] = 0.0; // initialize // example of potential values: 1 second = 1.0, 1.5 seconds = 1.5, etc.
               
$this->loop_running[$loop_key] = false;
            }
           
           
// check if we should run this time
            // $this->next_run = microseconds
           
if ($this->loop_running[$loop_key] || microtime(true) < $this->next_run[$loop_key]) {
                return;
            }

           
// set loop as running
           
$this->loop_running[$loop_key] = true;

           
$output = "Current time: " . date('Y-m-d H:i:s') . "\n";
           
$this->out($output);
           
           
// set pace of plugin loop (runs independent of main loop)
            // store our next run time in a variable
           
$this->next_run[$loop_key] = microtime(true) + 1.0; // 1 second = 1.0, 1.5 seconds = 1.5, etc.

            // set loop as not running
           
$this->loop_running[$loop_key] = false;
        }
    }

   
## EXAMPLE: ##
    // create plugins
   
$plugin_a = new my_plugin();
   
$plugin_b = new my_plugin();

   
// create main object that controls the plugins
   
$cli = new nb_cli();

   
// add plugins to main controller
   
$cli->add_plugin($plugin_a);
   
$cli->add_plugin($plugin_b);

   
// run our main controller which will run the plugins welcome() functions
   
$cli->welcome();

   
// run our main controller which will run the plugins run() functions in a loop
    // maximum speed is set in main controller, but each plugin can time their own runs
   
$cli->run();

?>


  Files folder image Files  
File Role Description
Plain text file class.nb_cli_1.0.php Class PHP NonBlocking CLI - Plugin based non-blocking CLI class for PHP console programs
Accessible without login Plain text file test-cli.example.game.php Example RPG MUD-like dungeon adventure game example with NPCs and Entities
Accessible without login Plain text file test-cli.example.php Example Basic Example
Accessible without login Plain text file test-cli.example.sockets.php Example example multi user chat server using sockets running multiple chat servers at same time on different ports

 Version Control Unique User Downloads Download Rankings  
 0%
Total:43
This week:1
All time:10,745
This week:82Up