supersan
supersan

Reputation: 6141

How to open a URL in the default browser from a PHP CLI app (asynchronously + cross platform)?

I'm creating a CLI app in PHP and I want to open the help page in the default web browser. It's similar to what git does when you run git help <command> where it opens the relevant URL in the default browser.

On python there is the webbrowser.open function which takes care of it, but I couldn't find any package for PHP.

This is my approach so far but I'm not able to test it properly (i.e. Windows 7, Debian, MacOS, etc) so it is kind of hacky:

<?php

$uname = strtolower(php_uname());
$os    = (strpos($uname, "darwin") !== false) ? 'osx' : ((strpos($uname, "win") !== false) ? 'win32' : 'linux');
$end   = $os == 'win32' ? '' : '&';
$cmd1 = sprintf("%s $url $end", $os == 'win32' ? 'start ""' : ($os == 'osx' ? 'open' : 'xdg-open'));
pclose(popen($cmd1, "r"));

My questions are:

Upvotes: 1

Views: 1622

Answers (2)

Lucas Bustamante
Lucas Bustamante

Reputation: 17238

function open_in_browser( string $url ): void {
    $url = filter_var( $url, FILTER_SANITIZE_URL );

    // We only open URLs.
    // We can also optionally allow FILTER_VALIDATE_IP as well.
    if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
        return;
    }

    // We only accept HTTP(s) protocol.
    if ( ! preg_match( '#^https?://#i', $url ) ) {
        return;
    }

    switch ( PHP_OS ) {
        case 'Darwin':
            // Mac.
            $command = 'open';
            $redirect_output = '2>/dev/null';
            break;
        case 'WINNT':
            // Windows. The double quotes are required, as the first parameter of "start" is the title, which we leave empty.
            $command = 'start ""';
            $redirect_output = '2> nul';
            break;
        default:
            // Portable command across most Linux distros.
            $command = 'xdg-open';
            $redirect_output = '2>/dev/null';
    }

    @exec( sprintf( '%s %s %s', $command, escapeshellarg( $url ), $redirect_output ) );  
}

Usage:

open_in_browser( 'https://example.com' );

Behavior in different OS:

  • Manjaro Linux with KDE and Brave browser: Works.
  • Windows 11: Works.
  • Mac: Can someone please confirm this works in Mac?
  • Ubuntu: Can someone please confirm this works in Ubuntu?
  • Other linux distros?

Additionally, if you want to be sure that the user will be able to visit the URL, you can also echo it before the exec:

echo "Please open this URL in the browser, it it hasn't opened already: $url\n";

In all approaches above, the operating systems will try to "execute" the URL. Since it has the HTTP(s) protocol, the default browser will be assigned to handle it and will open the URL.

This function does a good job at sanitizing, but better be safe than sorry. Since it executes a command in the host machine, you have to be extra careful. Do not pass a $url that you don't control.

Upvotes: 0

pjcdawkins
pjcdawkins

Reputation: 1266

Here are two small libraries that offer this functionality:

It looks to me like the latter is more fully featured.

Upvotes: 1

Related Questions