Skip to content

Instantly share code, notes, and snippets.

@terremoth
Last active November 14, 2024 03:57
Show Gist options
  • Save terremoth/4d01668e9f59849d863d37e61d2bc062 to your computer and use it in GitHub Desktop.
Save terremoth/4d01668e9f59849d863d37e61d2bc062 to your computer and use it in GitHub Desktop.
How to handle keypress non blocking real time get pressed keys on PHP (Linux only)
<?php
$stdin = fopen('php://stdin', 'r');
system('stty cbreak -echo');
stream_set_blocking($stdin, false);
while (1) {
if ($keypress = fgets($stdin)) {
echo 'Key pressed: ' . $keypress . PHP_EOL;
}
// you can do other stuff here since fgets and the stream won't block
// allowing to do simple command line games or interactive terminal tools like menus
}
@terremoth
Copy link
Author

terremoth commented Nov 13, 2024

A more object oriented approach. I will make a composer installable lib with this and a proper doc, then I will come back here and post the link. The code below I haven't tested yet.

class SimpleKeypress
{
    public $stream;

    public function __construct(string $mode = 'r')
    {
        $this->stream = fopen('php://stdin', $mode);
        system('stty cbreak -echo');
        stream_set_blocking($this->stream, false);
    }
    
    public function getkey() : string
    {
        return fgets($this->stream);
    }
    
    public function restoreTty() : void
    {
        system('stty sane');
    }
    
    public function eventOnKeypress(callable $func, callable|false $breakFunc = false) : void
    {
        while (1) {
            if ($key = $this->getKey()) {
                $func($key);
            
                if (is_callable($breakFunc)) {
                    if ($breakFunc($key)) {
                        break;
                    }
               }
           }
        }

    }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment