The Open-Source Classroom

The Family Dashboard in PHP

Shawn Powers

Issue #272, December 2016

Tired of explaining how to log in over the phone? Make a dashboard!

I've written a little about PHP before, because I think it's a great utility language for writing quick things you need to do. Plus, it allows you to use a web browser as your interface, and everyone has a web browser. That makes it very convenient for my family, because I can make simple web interfaces for the various things I normally have to do from the command line. (This is extremely useful when I'm gone to a conference and the Plex server needs to be rebooted, or any of a dozen other things need to be done that are hard to explain over the phone.)

My “Family Dashboard” will look different from yours, but the concept is pretty simple. PHP allows you to execute local functions on the server, and so as long as you can create a bash script that does what you need it to do, it can be launched from the “dashboard” you create for your family. Here's a sample dashboard file I've created, so you can see how simple it is to create a custom page that does what you need it to do (see Figure 1 for a screenshot of the dashboard in action):

<html><head><title>My Dashboard</title></head>
<body>
<h3>You need to enter some commands and possibly options, 
 ↪or just press a button:<br />
<button onclick="window.location='lj.php?command=weather&
↪option=houston'">Weather</button>
<button onclick="window.location='lj.php?command=bing'">Bing 
 ↪Photo</button>
<button onclick="window.location='lj.php?command=uname'">Kernel 
 ↪Name</button>
<button onclick="window.location='lj.php?command=time'">Unix 
 ↪Time</button>
</h3>

<?php

$command = $_GET['command'];
$option = $_GET['option'];

switch ($command)
{
    case "weather":
        echo file_get_contents("http://wttr.in/$option");
        break;
    case "time":
        echo time() . "  <-- that's how I read time! I'm a robot!";
        break;
    case "bing":
        $json = json_decode(file_get_contents("http://www.bing.com/
↪HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US"), TRUE);
        $url = "http://bing.com" . $json['images']['0']['url'];
        echo "Here is the image of the day:\n";
        echo "<img src=$url />";
        break;
    case "uname":
        echo shell_exec("uname -a");
        break;
    default:
        echo "<h1>Press a button!</h1>";

}

?>
</body></html>

Figure 1. My dashboard is simple, but it's just a front end for the code beneath.

First off, copy and paste that code into a file called lj.php and save it onto your local web server. The server needs to have PHP active, but I'll leave that as an exercise for the reader to set up. I've written about installing a LAMP stack before, so it shouldn't be too challenging to get a web server running with PHP support (see my article “PHP for Non-Developers” in the December 2014 issue or at www.linuxjournal.com/content/php-non-developers). Also, naming the file “lj.php” is only important because if you look at the code, it references itself. If you name it something different, just change the references in the HTML/PHP code.

Before learning how the code works, test it out and watch it work. If you can't host the file yourself, but want to see it in action, you can use my server for testing. Just head over to snar.co/php-dashboard, and it should redirect you to a hosted version of this file. Click the buttons, and see if you can figure out what's going on. Can you get the local forecast for your area?

What's with the GET and Switch Stuff?

It's possible to create a separate PHP file for every action you need to accomplish. That is a lot of PHP files, however, and it still doesn't give you the ability to receive input to use in the PHP file itself. I want my family to have a single URL, and I want all my code in a single file. It's just easier that way. First I'll explain what the $_GET variable does.

As you click the buttons on the page, you should look at the address bar on your browser. When you click on the weather button, for instance, you should see this in the address bar: http://your.server.here/lj.php?command=weather&option=houston.

That stuff at the end is how you tell the PHP script what information you want it to display. All the variables you assign are put into an array called $_GET. So in the weather example above, I've assigned two variables. To reference them inside the PHP script, you use the $_GET array. So in the URL above, these two variables are assigned:

$_GET['command'] = "weather";
$_GET['option'] = "houston";

And, you can use those variables in your PHP code. Notice that I've actually assigned those two variables to standard variable names, so that it's easier to reference them later. You can change what variables are sent to the PHP script by changing the information in the URL. That allows the script to be dynamic and provide output based on the input you give it. In fact, the only reason pressing those buttons works is that it loads the page with the arguments already in place! See if you can get your local weather now by changing the “option” variable in the URL and loading the page. Cool, huh?

More Than Just Weather

Since you're able to send your PHP script variables via the URL, that means your dashboard can do much more than just show the weather. Based on the variables, you can call different commands with the switch construct in PHP. It's like a CASE statement in other languages, and the logic is pretty straightforward.

You run the switch statement on the $command variable assigned from the $_GET array. If the variable matches any of the options listed as a “case”, it executes the code in that section, then you break; out of the switch construct. If the $command variable doesn't match any of the case options, the switch executes the default: section at the end. In this example, it's a message to press a button.

Let's look at each section to see what's going on when you press a button (or manually enter the command in the URL).

The Part before the PHP

If you put standard HTML into a PHP file, and don't enclose it between <?PHP ?> tags, it just sends it to the web browser as HTML code. So the top of the lj.php file is just plain HTML. The text is shown in <h3> tags, and the buttons are created with a little bit of JavaScript that allows them to load the URL specified. If the buttons and JavaScript make you uncomfortable, it's okay to make standard text links that point where you want them. I just like buttons because they look cool.

It's important to realize that the buttons aren't doing anything other than loading the page with $_GET variables assigned in the URL. The buttons themselves don't execute code, and aren't anything fancy. You can type the URL out by hand and achieve the same thing. Your family will appreciate it if you make them links or buttons though, because clicking is much easier than typing long, complicated URLs!

Weather

If you click the weather button, or enter the URL by hand to send the $_GET['command'] and $_GET['option'] variables to the script with weather as the command, the switch statement will execute the code inside the case "weather": section.

This is a really simple command that just echoes (prints on the screen) the results from fetching the web page. The file_get_contents function in PHP will get the contents of a local file or a file on the internet. In this instance, you create the URL with your $option variable. If you clicked the button, you'll notice $option is set to “houston”, but you can change the URL by hand in order to get your local weather. It will accept city names, ZIP codes and even airport codes.

The weather section of the script is the only one that looks at the $option variable, but it's possible to assign as many variables as you want from the URL. If you assign a variable and it isn't used, there's no harm, it's just ignored.

The Time?

The “time” section doesn't return what you'd expect for a time button to return. In fact, I labeled the button that loads that page “Unix Time”, because I used the time() function in PHP, which displays the number of seconds that have elapsed since January 1, 1970. That might not seem like a terribly useful number, but it's very convenient when programming, because you don't have to parse out hours, minutes and so on. You can click (or refresh) the page a few times, and you should see the number increment.

UNIX time (sometimes called Epoch Time) is fun to play with, and although this example isn't terribly useful, I wanted to include it so you could see how the time() command works, along with the echo command. If you look, there is a single period after the time() function. That concatenates the two items into a single string and displays it all together. If you click the button, you'll see what I mean.

Bing? How Dare You Load a Microsoft Page!

The Bing photograph of the day is always awesome (Figure 2). Really, Microsoft does a great job of procuring incredible photos, and I love to see them. Since the URL is always different, this was a great way to show how to load JSON into a variable and then extract an array element. Don't let the scary looking code intimidate you; JSON is really cool. Basically, you load the JSON from that long Bing URL and put it into a PHP array. Then, you form the URL for the photo from the contents of that array. Here's a snippet of code you can use to see the array in a more readable form:

<?php

$json = json_decode(file_get_contents("http://www.bing.com/
↪HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US"), TRUE);

echo "<pre>";
print_r($json);
echo "</pre>";

?>

Figure 2. The Bing photos are always so cool.

If you don't have a server, head over to snar.co/php-json to see the results of the PHP file. You can see where I got the information to build the URL for the image, and in the switch statement, you can see it just loads the image based on that URL. Isn't JSON cool?

Local Scripts

This part of the switch statement is powerful, but also a little scary. If you click on the “Kernel Name” button, you can see it executes the code in the uname section of the switch statement. Using the shell_exec command, you can execute a file on the local server and show the results in the browser window. This is powerful because it means you can have your family execute local bash scripts by clicking on a button. But it's a little scary, because you're executing local commands on your server by clicking a button!

The script is executed with the permission of the web browser, so, for example, in Ubuntu running Apache, the www-data user would be executing the command. If that user doesn't have permission to do something in the script, the script will fail. This is one of those “with great power comes great responsibility” things. It can be incredibly useful, but also incredibly dangerous, especially if your server is exposed to the internet!

Troubleshooting

Whenever I write PHP code, I make mistakes. Usually it's a forgotten semicolon or a mismatched bracket. It can be very annoying when you load the page, and it's suddenly just blank instead of showing you an error. In the last article I wrote about PHP, I showed how to turn on PHP errors so you could see in the web browser what's going wrong. I don't do that anymore, because it's annoying to see PHP warnings when things are working fine. So what I do now is run php from the command line. If the code is broken, it will show errors on your command line, and you won't have to worry about turning error logging on and off in your web browser. For example, in the example lj.php file, just go to the folder where it's stored and type:

php lj.php

And the server will dump the HTML to your command line as if it were a web browser. If there's an error, it will tell you what you did wrong. I like that method of error checking much more than getting error notifications in my web browser, but if you prefer to see them on the browser, look back to my PHP article from the December 2014 issue and see how to activate error logging.

Just like last time, I'm giving you only a taste of the sorts of things you can accomplish with PHP and a little ingenuity. If you come up with an interesting dashboard of your own, I'd love to see it, even if it's just a screenshot. (Don't expose your dashboard to the internet, especially if it controls your local server with shell_exec statements!) Feel free to email me at info@linuxjournal.com, but be sure to put “DASHBOARD” in the subject line, or I might assume it's spam. I get so much darn spam!

Shawn Powers is the Associate Editor for Linux Journal. He's also the Gadget Guy for LinuxJournal.com, and he has an interesting collection of vintage Garfield coffee mugs. Don't let his silly hairdo fool you, he's a pretty ordinary guy and can be reached via e-mail at info@linuxjournal.com. Or, swing by the #linuxjournal IRC channel on Freenode.net.