PHP stands for PHP HyperText Processor (it’s what’s called a recursive acronym). PHP is an open source scripting language widely used for server-side web development.

Install the PHP SQLSRV Driver on Linux

Rejoice! Microsoft actually does provide a PHP Linux driver for Microsoft SQL Server. The bad news is, it can be a real pain to get it working.  I went through this experience tonight while setting up a utility I wrote for a client. I ran into two separate issues. This article provides some assistance with the issues I ran into when I tried to Install the PHP SQLSRV driver on Linux.

How to Install PHP SQLSRV Driver on Linux

The instructions in the repository’s readme.md are actually pretty good. Check out the official Github repository for the driver for the latest version and installation information. I recommend you follow their instructions first. When you hit a roadblock, come back to this article for help.

PECL Building with Wrong PHP Version

The final step in the installation is installing the base driver and the PDO variant withpecl install. PECL runs a build process on your machine and it uses a tool called phpize to execute the build. The version of this tool needs to match your PHP version. Otherwise, the build will succeed, but the extension file it generates won’t be compatible with the version of PHP you’re running. You’ll know pretty quickly if this is the case if you get “can’t load extension” errors after you build and execute PHP.

To solve the problem, install the version of phpize that matches your PHP version. For example, if you are running PHP 7.1, you would run:

sudo apt-get install phpize7.1

Microsoft ODBC Client is Missing

After I fixed the problem above, I ran my PHP script and the database connection failed. The PDO SQL Server driver reported an error message that it could not execute because it required the Microsoft ODBC Client. Installing the client is actually part of the steps in the instructions provided on Github. But for me, the installation failed and I didn’t notice. I went back and repeated this step and found that there was a missing dependency that would not install. Once I manually installed it and re-ran the client installation steps, then the PDO driver started working.

The Github repository below contains the official drivers from Microsoft. Check out the repository for the latest version information and installation instructions.

Subnet Calculator in 9 Lines of PHP

I’ve been spending a lot of time studying for my Microsoft 70-642 exam, an important part of which is subnetting.As an intellectual exercise I wrote a subnet calculator. Enjoy:

1
2
3
4
5
6
7
8
9
 function subnet($hosts)
 {
	$bits       = decbin($hosts) + 2; // Add 2 for Network ID and Broadcast
	$hostBits   = strlen($bits); // find how many bits it takes to represent it
	$cidr       = 32 - $hostBits; // Find slash-notation
	$binaryMask = str_repeat('1', $cidr) . str_repeat('0', $hostBits); // Subnet in binary
	$subnet     = implode('.', array_map('bindec', str_split($binaryMask, 8))); // Subnet in dotted-decimal
	return array('hosts' => $hosts, 'hostBits' => $hostBits, 'cidr' => '/' . $cidr, 'binaryMask' => $binaryMask, 'subnet' => $subnet);
 }

Use a Frame-Busting Redirect To Authorize Facebook Applications

Here’s a trick I picked up during development of my new Facebook application, My Wishlist. I picked this one up at Stack Overflow.

When you begin developing for Facebook, one of the first trick’s that you’ll learn is how to check for a Facebook session and how to redirect the user to the Facebook login page if they aren’t logged in or haven’t authorized your application.  Usually that code looks something like this:

<?php
$fb = new Facebook(array(
    'appId' =&gt; 'XXXXXXXXXXXXXXXXX',
    'secret' =&gt; 'XXXXXXXXXXXXXXXXXXX',
    'cookie' =&gt; true
));
 
$session = $fb-&gt;getSession();
 
if($session)
{
    // TODO Show your application's canvas.
}
else
{
    // Redirect the user:
    header('Location: ' . $fb-&gt;getLoginUrl(array(
        'next'   =&gt; $_SERVER['PHP_SELF'],
        'canvas' =&gt; 1,
        'display' =&gt; 'page'
    )));
}

If you’re developing an Iframe-based Facebook application (soon to be the only option since FBML has been deprecated), you’ve got a real problem: The redirect will happen within your application’s IFrame, with the actual login page content hidden within the frame. You’ll recognize the problem because it will look a little something like this:

This is what happens when you redirect to the login page within a Canvas-based Facebook application.

This is what happens when you redirect to the login page within a Canvas-based Facebook application.

The solution to this problem is to use what I call a Frame-Busting Redirect using JavaScript:

<?php
$fb = new Facebook(array(
    'appId' =&gt; 'XXXXXXXXXXXXXXXXX',
    'secret' =&gt; 'XXXXXXXXXXXXXXXXXXX',
    'cookie' =&gt; true
));
 
$session = $fb-&gt;getSession();
 
if($session)
{
    // TODO Show your application's canvas.
}
else
{
    // Redirect the user:
    echo "<script>\n";
    printf("top.location.href= \"%s\";\n", $_SERVER['PHP_SELF']);
    echo '</script>';
}

Making the PHP Curl Extension Work on Windows

Earlier tonight I was setting up some development tools on my new laptop and ran across a problem that I had never seen before.  When I began testing an application that uses the Facebook API (which depends on the CURL library), PHP insisted that the CURL extension was not loaded.  I checked and double-checked that my php.ini file was correct (it was) and that the rest of my extensions were loading (they were).

Finally after looking at the installation documentation for the CURL module I realized my mistake: I had forgotten to put PHP on the system path. According to php.net:

In order to enable this module on a Windows environment, libeay32.dll and ssleay32.dll must be present in your PATH. You don’t need libcurl.dll from the cURL site.

In other words, you either need to adjust your PATH environment variable to contain C:\PHP or you need to copy these two files from that directory to a directory that is on the path, such as C:\windows\system32. Either solution should resolve the problem.

Removing Keys from an Array in PHP

Removing one or more keys from an array in PHP seems like something that should be easy to do. Yet out of the 70+ array functions in PHP, there is no single function to do it. But here’s the easy way:

Use array_diff_key()

PHP has a function called array_diff_key($array1, $array2) that returns an array with all of the keys (and their values) from $array1 that don’t also occur in $array2. We can use this to quickly cobble together a solution:

<?php
 
function array_remove_keys($array, $keys) {
 
    // array_diff_key() expected an associative array.
    $assocKeys = array();
    foreach($keys as $key) {
        $assocKeys[$key] = true;
    }
 
    return array_diff_key($array, $assocKeys);
}
 
// Example:
$data = array(
    'name' => 'Brian',
    'address1' => '98 Market St.',
    'address2' => 'N/A'
);
 
// Output before array_remove_keys()
var_dump($data);
 
// Remove address2 key.
$data = array_remove_keys($data, array('address2'));
 
// Output after array_remove_keys()
var_dump($data);
 
/* Output:
 
array(3) {
  ["name"]=>
  string(5) "Brian"
  ["address1"]=>
  string(13) "98 Market St."
  ["address2"]=>
  string(3) "N/A"
}
array(2) {
  ["name"]=>
  string(5) "Brian"
  ["address1"]=>
  string(13) "98 Market St."
}
*/

Works great! But it’s not quite complete. There is absolutely no error checking, and passing an array as the second parameter isn’t the most convenient way to operate. Let’s give the caller the option of passing either an array, or a comma-separated list of keys to delete.

<?php
 
function array_remove_keys($array, $keys = array()) {
 
	// If array is empty or not an array at all, don't bother
	// doing anything else.
	if(empty($array) || (! is_array($array))) {
		return $array;
	}
 
	// If $keys is a comma-separated list, convert to an array.
	if(is_string($keys)) {
		$keys = explode(',', $keys);
	}
 
	// At this point if $keys is not an array, we can't do anything with it.
	if(! is_array($keys)) {
		return $array;
	}
 
    // array_diff_key() expected an associative array.
    $assocKeys = array();
    foreach($keys as $key) {
        $assocKeys[$key] = true;
    }
 
    return array_diff_key($array, $assocKeys);
}
 
// Example:
$data = array(
    'name' => 'Brian',
    'address1' => '98 Market St.',
    'address2' => 'N/A'
);
 
// Output before array_remove_keys()
var_dump($data);
 
// Remove address2 key.
$data = array_remove_keys($data, 'address2');
 
// Output after array_remove_keys()
var_dump($data);
 
/* Output:
 
array(3) {
  ["name"]=>
  string(5) "Brian"
  ["address1"]=>
  string(13) "98 Market St."
  ["address2"]=>
  string(3) "N/A"
}
array(2) {
  ["name"]=>
  string(5) "Brian"
  ["address1"]=>
  string(13) "98 Market St."
}
*/