Storing singleton objects in PHP sessions

A friend of mine, who is working on a sick little diet and exercise tracking application, asked me today if PHP allowed singleton objects to be stored in a session. My first reaction was absolutely they can be so long as you follow the normal rules of unserializing objects in PHP… namely, making sure the class is in scope before attempting to create an object from it OR having an autoloader that does that for you. But as I thought about it more I began to think that maybe this might not work as expected since singletons generally have no public access to their constructors. However, when an object is unserialized, it is instantiated, for lack of a better term, and populated with the data that was exposed from the serialization process.

Note: for those of you that are unfamiliar with the way PHP handles session data or are just wondering why I am using serialization so much in my examples, the basics are you start a session and PHP assigns a random MD5 hash to it as an id. You write data to the session via the $_SESSION superglobal array and when the script terminates or you call session_write_close(), PHP serializes the $_SESSION array and writes that serialized string to the file system for retrieval on subsequent requests so long as the session time limit has not expired. I really did not want to run this entire session process and inspect what was being written to my file system so I decided to mock that interaction myself by creating an arbitrary array, serializing it, grabbing the serialized string and unserializing it.

As I began to dig into this I started playing with PHP’s magic __sleep() and __wakeup() methods. Those seemed to do what I wanted them to do except in the case of protected and private properties of my class. As soon as I added those in my serialization took a crap all over itself, even when I cloned the singleton object and got the public properties exposed through get_object_vars(). So, thanks to the PHP manual – the most awesome tool in any PHP developer’s arsenal – I discovered the PHP Serializable interface.

This interface defines two methods: serialize() and unserialize(). These methods override the default behavior of __destruct() and __construct() so if you are using these you should keep that in mind and either put your __destruct() and __construct() code into these methods or allow for calls to __destruct() and __construct() from within these methods. Your homework is to decide which is the better implementation. 🙂

Now, back to the lesson at hand… the following object – let’s say it is saved to a file named dummy.php – is a super simple implementation of a basic singleton pattern. It includes both a serialize() and unserialize() method to allow it to be serialized for storage.

<?php
class DummySingleton implements Serializable {
    /**
     * Test properties of various visibility
     * @var string
     */
    public $dProp;
    public $dPropX = 'Nothing to see here folks';
    private $_prop = 'y u try see dis?';
 
    /**
     * Instance holder for this singleton
     * 
     * @var DummySingleton
     */
    private static $_instance = null;
 
    /**
     * Private singleton constructor, simply sets a property
     */
    final private function __construct() {
        $this->dProp = 'I was finally built';
    }
 
    /**
     * Singleton instance getter
     * 
     * @return DummySingleton
     */
    public static function getInstance() {
        if (self::$_instance === null) {
            self::$_instance = new DummySingleton();
        }
 
        return self::$_instance;
    }
 
    /**
     * Implementation of the Serializable interface, called automatically just 
     * before this object is serialized. This will override any calls to a
     * __destruct method, so if you have a destructor you should call it from
     * here.
     * 
     * @return string
     */
    public function serialize() {
        return serialize(get_object_vars($this));
    }
 
    /**
     * When this object is created from an unserialization this method is called. 
     * It implements the Serializable interface and uses the data from the 
     * serialize() method herein. Since this method overrides the __construct
     * method you should make any accomodations for constructing your object
     * in this method.
     */
    public function unserialize($data) {
        // "Instantiate" our singleton
        self::getInstance();
 
        // Set our values
        if (is_array($data)) {
            foreach ($data as $k => $v) {
                $this->$k = $v;
            }
        }
    }
}
?>

If you build up this object then serialize it, then rebuild it from the serialization, you can see that it remains in tact. Let’s test this by simulating the session array, first creating an array then adding the DummySingleton object to that array, then serializing it:

<?php
// Grab the class
include 'dummy.php';
 
// Get our instance
$o = DummySingleton::getInstance();
 
// Set something into it for testing
$o->setFromOutside = 'What the hell is this madness?';
 
// Make an array of stuff
$a = array();
$a['name'] = 'Robert';
$a['id'] = 23;
 
// Add the singleton
$a['dummy'] = $o;
 
// Serialize it
$s = serialize($a);
?>

The serialized output from this yields:

a:3:{s:4:"name";s:6:"Robert";s:2:"id";i:23;s:5:"dummy";C:14:"DummySingleton":187:{a:4:{s:5:"dProp";s:19:"I was finally built";s:6:"dPropX";s:25:"Nothing to see here folks";s:5:"_prop";s:16:"y u try see dis?";s:14:"setFromOutside";s:30:"What the hell is this madness?";}}}

If you take that string and subsequently load it and unserialize it then inspect it, you’ll see that the singleton object has been restored along with all private properties of it:

<?php
// $s is our serialized string from above
$o = unserialize($s);
var_dump($o);
?>

Output:

array(3) {
  ["name"]=>
  string(6) "Robert"
  ["id"]=>
  int(23)
  ["dummy"]=>
  object(DummySingleton)#1 (3) {
    ["dProp"]=>
    NULL
    ["dPropX"]=>
    string(25) "Nothing to see here folks"
    ["_prop":"DummySingleton":private]=>
    string(16) "y u try see dis?"
  }
}

Since this is, in essence, the process that PHP follows for its default session management it’s safe to say that you can, indeed, store singleton objects in a PHP session. Now onto to bigger and better questions, like…

Why would you ever want to store a singleton object instance in a PHP session?

Simple PHP table maker

A little while ago I was in need of a way to take tab separated data sets and make HTML tables out of them cleanly. Mostly this was from data copied from a spreadsheet, but sometimes copying from web pages or even text documents has brought this need up for me. So in keeping with my mantra of “Why not write a program to do that?” I decided to write a simple HTML table maker that will take in tab separated, structured data and return an HTML table from it, complete with column headings, a caption and a summary (sidenote: I know that table summaries are being deprecated… still, I included it because at the moment they are still in use for pre-HTML5 markup).

So without further ado, I bring you my simple HTML table maker. It isn’t the most robust thing in the world, but it is still pretty neat. Plus? It totally serves my purpose to the tee. So if you don’t like it, why not gank the code for it and make it better?

Simple PHP Class generator

Someone on the Professional PHP Group asked the question yesterday about whether Dreamweaver has a utility to write setters and getters to your PHP classes for you. I know that ZendStudio has this feature and I am pretty sure that NetBeans has it as well.

But as I thought about this, I thought “How cool would it be to be able to take a list of PHP properties and build a class out of that list complete with your getters and setters?”. That’s when my inner nerd took over and I created a very simple PHP Class Generator.

It is not the most robust tool in the world, but if you are looking for a quick way to build out a class of getters and setters from a simple list of variables, this little tool might be right up your alley. I’d encourage you to play with it and see if it can help you. If it does, tell me about it in the comments.

Oh yeah, a major thank you goes out to Jason Memory of Full Throttle Web Solutions for his help and wizardry in all things regex.

Handling multiple MySQL results in PHP

Back in the day (June of 2007 to be a little more exact) I posted a little snippet about using PHP to hand multiple MySQL query results with the MySQLi extension. At the time it was something I was using just to see what was coming back from the database when I called a stored procedure that happened to have multiple results in it. Skip to how this really works…

Since then I have improved my little handler, added some library code to actually handle queries and results (and timers and requests and… dude, so much). The new code, which is much fatter (not necessarily better, just fatter in that it has a lot more features in it), now encapsulates much of what the original, simple script was doing. Unfortunately, the script is no longer as simple as I wanted it to be. However, it does now come in several files which might be of use to you in some of your own code.

Because of the change that I made to the way this code works, I have decided to package it into a little zip file for your downloading pleasure. The zip file includes:

  • index.php (the actual procedure/result tester)
  • A lib directory, which contains:
    • memorystats.php (A memory use and reporting object)
    • mysql.php (The database connection and query object)
    • mysqlresult.php (The database result object)
    • request.php (The HTTP request object)
    • timer.php (The process timer object)

It should be ready to use right out of the box, with the exception of making sure to add your own username, password and database name to the $db->connect() call (at about line 85 in index.php). I’m sure you could expand it to be more of what you want in a tester (like adding a database chooser to it – right now I have a database server chooser, but not a database chooser within a server) but overall it is a very nice little script that does pretty much what it was built to do: run a query/procedure and return all of the results in it.

Please note: This is seriously not something that you should think to use in a production environment. The farthest this has ever made in any of my architectures is the dev machine. Not that the code is not good. It is just that putting something that has free form access to your database onto a production machine is, in my opinion, a remarkable stupid thing to do and I would hate to have my name associated with code that was used to exploit your business because you chose to put a huge gaping hole into your network through a simple little test script. Just sayin’.

Under the hood
Before diving into that mash of code I included in the zip file, it might be a good idea to see just the relevant code so you can, if you want to, just tap into the multiple result set handling of MySQL results in PHP. Without further ado…

<?php
// Set a query
$sql = "SHOW TABLES FROM `mysql`; SELECT VERSION() AS `version`; SELECT NOW() AS `date`;";
 
// Change the params to you own here...
$mysql = new mysqli('HOSTNAME', 'USERNAME', 'PASSWORD', 'DATABASE');
 
if (mysqli_connect_errno()) {
	die(printf('MySQL Server connection failed: %s', mysqli_connect_error()));
}
 
// Initialize our result set array
$results = array();
 
/** 
 * Check our query results
 * 
 * This is where the magic happens, and it must be this way anytime you use a
 * stored procedure. The reason for that is the MySQL server always sends a 
 * status return with any query, even a select query. That means that even a
 * single result set select query will return two results. Those results will
 * not necessarily make it to your application (I think the client handles 
 * that) but in my experience I have always had to use multi_query to get this
 * to work.
 */
if ($mysql->multi_query($sql)) {
	do {
		// Create the records array
		$records = array();
 
		// Lets work with the first result set
		if ($result = $mysql->use_result()) {
			// Loop the first result set, reading the records into an array
			while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
				$records[] = $row;
			}
 
			// Close the record set
			$result->close();
		}
 
		// Add this record set into the results array
		$results[] = $records;
	} while ($mysql->next_result());
}
 
// Close the connection
$mysql->close();
 
// Set our output type
header('Content-Type: text/plain');
 
// What do we have
print_r($results);

And there you have it. Nice, simple, clean and easy to use all by itself.

Scope? Nope. Dope!

Today I made a classic blunder in PHP programming. It is one that many make and certainly one I have made before. But the frustrating thing about this issue is it probably would have been caught by a simple unit test or, in lieu of that, something as simple as trying to capture output of my script from the go.

I was working on the command line (something I have been spending a lot more time doing) building a background processing application that will be triggered by the web. The process is expected to take between 45 minutes and an hour each time it is ran and will be ran one time a month at the discretion of an administrator (hence the reason it is not set as a cron job).

One of the very first lines of the CLI script looks like this:

<?php
// Define our path for all includes and file writes
define('APPPATH', realpath('.'));
?>

It would seem simple enough, right? Basically that little line of code defines a constant called APPPATH that would essentially describe the path to the location of the file that is setting the constant. At least that is what I thought. And every test I ran led me to believe that I had indeed made the right choice to set the path the way I did.

I ran the script, and even other scripts that derived code from the script, from the command line on my local Ubuntu machine, from the command line on our Fedora dev machine and from the command line on our Ubuntu production server. I have similar snippets that are working on all of our machines, and these snippets work interactively, through cron and through the web.

But today something happened that I did not intend. As I attempted to run my last process test of this long running script through the web I found myself in a place where my script would not run. It was being triggered properly. It was just not actually doing anything.

After an hour of trying to figure out what I was doing wrong I solicited the wisdom and advice of two of my colleagues who are seasoned Unix professionals and after a couple of minutes I was able to begin to see what was wrong. Can you guess what it was?

That’s right… PHP, on the web, was applying its scope to the CLI script that it was calling. The reason it had worked in all cases prior to triggering it by the web was that I was logged in as me and calling the script as a CLI script interactively, through the prompt. That means that the setting of the APPPATH constant was happening as expected and to what I expected.

However, from the web, when PHP runs as an apache module, it calls the CLI script from the scope of the web server. That means that the use of realpath() on the location ‘.’ (current working directory) was assuming the working directory was the web server root, not the location of where the script actually resided.

That’s right folks, I lost track of the scope in which I was working. Like a dope.

The simple solution to this problem was to change where the script looks to set its own directory. Can you think of what I could have used, instead of ‘.’ as the location to pass to realpath() so that it knows, without a doubt, what its own path is?

<?php
// Get the real path to the current directory location OF THIS FILE
define('APPPATH', realpath(dirname(__FILE__)));/
?>

I hate it when something this simple causes such deep pain and suffering, needlessly.

Getting books details by ISBN in PHP

Sometimes I love being a geek. Today, as I set out to inventory my collection of almost 500 books or so, I wanted to find a fast way to get the information on the book I wanted based on the books ISBN. This was because I was already getting tired of typing five books into the inventory (yes, I am that lazy) and I really did not want to keep typing out the authors name, the title and the subtitle for each book.

So I went to ISBNdb.com and entered an ISBN thinking I would be able to just copy and paste the book information from the output. That turned out to be overwhelmingly difficult since their output of the search is really convoluted. I knew what I wanted to get and they didn’t offer that.

But they did offer an API and, after reading their docs, I realized that I could write a script that would take an ISBN and return to me the information I was looking for in a way that I could just copy and paste it. Remarkably, it was faster and easier than I thought it would be. I actually developed this little snippet, freely available for you here, in about 5 minutes. Hope it helps you in some way, if you are looking for such a thing.

NOTE: Before using this code make sure to sign up for your own API key. In order to do that you will need to register for an account with ISBNdb.com and then create a key. But as soon as you do you will have immediate access to their API. The API is simple, responding to the request with a simple XML output. Anyhow, without further ado, here is the little script I put together to fetch me the data I was looking for the way I wanted it.

<?php
/**
 * Set this value to your own API key
 */
$apikey = '12345678';
 
/**
 * Initialize this var for use when forms are not posted
 */
$isbn = null;
 
/**
 * Initialize the result set var
 */
$rs = null;
 
/**
 * See if the form is posted
 */
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  /**
   * Get the ISBN from the form
   * 
   * No, there is no validation on this. This 
   * was for me and I knew I would not be at
   * all trying to trick my own script. USE 
   * THIS AS IS AT YOUR OWN PERIL.
   */
  $isbn = $_POST['isbn'];
 
  /**
   * Get the result as a SimpleXML object
   */
  $rs = simplexml_load_file("http://isbndb.com/api/books.xml?access_key=$apikey&index1=isbn&value1=$isbn");
}
?>
<html>
<head><title>ISBN Check</title></head>
<body>
<form method="post" action="<?php echo basename(__FILE__) ?>">
  <p>
    Enter an ISBN:<br />
    <input type="text" size="40" name="isbn" id="isbn" value="<?php echo $isbn ?>" />
  </p>
  <p>
    <input type="submit" name="submit" value="Search ISBN" />
  </p>
</form>
<?php
/**
 * Only output more stuff if there is a result
 */
if ($rs) : ?>
<hr />
Results for ISBN: <?php echo $isbn ?>:
<?php 
/**
 * Results for a book are in $rs->BookList->BookData
 * 
 * You can see this using var_dump($rs);
 */ 
$book = $rs->BookList->BookData;
?>
<p>
  <strong><?php echo $book->Title; ?></strong><br />
  <?php echo !empty($book->TitleLong) ? $book->TitleLong . '<br />' : null; ?>
  <?php echo $book->AuthorsText; ?><br />
  <?php echo $book->PublisherText; ?><br />
  <?php echo $isbn; ?>
</p>
<?php endif; ?>
</body>
</html>

Typical output might look like (from one of the books I was checking on):


Results for ISBN: 0316116955:

The day the universe changed
James Burke
Boston : Little, Brown, c1985.
0316116955


I hope you enjoy this, if you happen to be looking for an ISBN search tool that you can run on your own. 😉

Coding clean should be a lifestyle

Dear rookie PHP coders/script kiddies/n00Bs: if you plan to use a variable or array index please remember to initialize them first or I will hunt you down and gut you like a pig. Kthnxbai.

I am in the middle of a redevelopment project right now that is pissing me off beyond imagination. The main reason is because the original developer of the codebase decided that initializing variables, checking existence of variables and checking existence of common array indexes was not necessary. And it got me thinking… coding clean should not just be a high priority, it should be a way of life for developers.

For those of you that may just be getting started in the big scary world of PHP development I want to offer a suggestion: before you even think of using a variable or array index either initialize it or check its existence.

What is initializing a variable or array index you ask? Simple. Declare it with a value. Like this:

<?php
// Initialize a variable
$myVar = null;
 
// Initialize a variable as an array
$myArray = array();
 
// Initialize an index
$myArray['myIndex'] = null;
?>

That isn’t that hard, is it? Now lets that this a step further and make sure that before we use something it is actually available to us, shall we?

<?php
if (isset($myVar)) {
  // Do something based on $myVar being set
}
 
if (empty($myArray)) {
  // Do something based on $myArray being either not 
  // set or set to a value equal to (boolean) false
}
?>

Using empty() and isset() are two things you can do before using a variable. This allows you to not only check if a variable has been set but also allows you to check a specific empty value.

Something to take note of here is that isset() will still return false if you check a variable that has be assigned a value of ‘null’. However, because it has been declared you can use the variable in conditionals and other expressions without worry of generating an undefined variable notice.

<?php
$myVar = null;
 
if (!$myVar) {
  // So something if $myVar evaluates to (boolean) false
  // And you don't have to worry about throwing errors now
}
?>

If you plan on using a constant, which is not a variable, then you would use defined().

<?php
define('ROBERTROCKS', true);
 
if (defined('ROBERTROCKS') && ROBERTROCKS) {
  echo 'Man, Robert must rock';
}
?>

Moving into an area that is a tad more useful, there are times when your code is going to enter a loop or other construct (like a switch for example) and something done inside of that construct will set a variable that you will use after the construct closes. When this happens, make sure to initialize your var outside the construct so that if the construct never opens or is never entered you can still use the variable after the construct closes.

<?php
/**
 * Make sure we have clean access to the variable 
 * regardless of whether the construct is used
 */
$myVar = '';
 
while (loopRuns()) {
  $myVar .= getLoopVal();
}
 
/** 
 * Since we made this variable before entering
 * the construct we can be sure we can use it 
 * without issue even if the loop never happens.
 */
echo $myVar;
?>

So to close this out let me point out a few things that you should never see in your code. Ever.

<?php
/**
 * This is crap. Don't ever do this. If a request is made
 * to this page without a querystring then $_GET['id']
 * will not be set and you will look like an ass for not
 * knowing how to code cleanly.
 */
$id = $_GET['id'];
 
/**
 * This is another stupid. How do you know if the session
 * variable has been set? You don't, and if it isn't set you
 * will be notified.
 */
if ($_SESSION['hasVar']) $hasSessionVar = $_SESSION['hasVar'];
 
/**
 * Last example of what not to do... never build a var
 * inside a construct for use outside the construct without
 * initializing it.
 */
switch ($myVar) {
  case 'crap':
    $newVar = 'This is crap';
    break;
 
  case 'bull':
    $newVar = 'This is bull';
    break;
}
 
echo $newVar;
?>

I hope this helps someone learn to code a little cleaner. And perhaps save you all sorts of curses and negativity by developers that might have to try to work on your code long after you stopped working on it.

PHP operators: double and single arrow

Someone recently asked a question on the Professional PHP Programmers Google Group that I thought was interesting. This question interested me for a few reasons:

  1. The PHP manual is a very good manual and usually covers things like this; and,
  2. I remember asking this very question when I first started developing.

Hi all, I’m new to the mailing list, and new to php, and new on programming.

Here I go:

I have a question but I was unable to find an answer for this on the web. Because I have no Idea how to ask this on a search engine.

What’s the meaning of -> and => on php?

As good as the PHP manual is, and as well documented as the operators in PHP are, the documentation on these two operators is lacking severely. Even naming is horribly lacking for these two operators, as a recent Twitter chat shows:

More on the operators used in PHP can be found at http://us3.php.net/manual/en/language.operators.php. Unfortunately, these operators will not be found there. So to assist in explaining what these operators are and what they do, lets dig a little deeper in the world of cryptic symbols that remain unnamed in PHP. Shall we?

The double arrow operator, “=>”, is used as an access mechanism for arrays. This means that what is on the left side of it will have a corresponding value of what is on the right side of it in array context. This can be used to set values of any acceptable type into a corresponding index of an array. The index can be associative (string based) or numeric. So if I have an array like:

<?php
$myArray = array('Big', 'Small', 'Up', 'Down');
?>

Then in effect the code is saying:

<?php
$myArray = array(
  0 => 'Big',
  1 => 'Small',
  2 => 'Up',
  3 => 'Down'
);
?>

This is not a real surprise seeing as arrays in PHP are numerically indexed, zero-based arrays by default. But what if you wanted a hash of keys and values? Like when passing something as a form or in a querystring or reading results from a database? Well then, you would want to associate a key to a value in the array, or something like:

<?php
$myArray = array(
  'Robert' => 'Big',
  'Bobby' => 'Smart',
  'PHP' => 'Rocks'
);
?>

Now you have a hash of values assigned to indeces using the double arrow, or array value assignment, operator (“=>”).

The object operator, “->”, is used in object scope to access methods and properties of an object. It’s meaning is to say that what is on the right of the operator is a member of the object instantiated into the variable on the left side of the operator. Instantiated is the key term here. We’ll talk about that a little more in just a bit.

If you come from a background in object oriented programming then you know that every object has a way to access the methods and properties of the instantiated object. In most languages that is the dot operator (“.”). In PHP the dot operator has completely different meaning (it is used to concatenate strings) so don’t use that for object scope resolution. Instead, after instantiating an object, access its methods and properties using the object operator, like this:

<?php
$obj = new MyObject(); // Create a new instance of MyObject into $obj
$obj->thisProperty = 'Fred'; // Set a property in the $obj object called thisProperty
$obj->getProperty(); // Call a method of the $obj object named getProperty
?>

Now, getting back to object basics, remember I said that instantiated was a key term? The reason for that term is because there is another operator related to scope resolution than can be used but it is neither an arrow nor can it be used on objects. It can only be used on classes (this is as of PHP 5 – since PHP4 has already been fed to the dogs we are only going to talk about PHP 5). Class scope resolution is identified by the Paamayim Nekudotayim, or double colon, operator (“::”).

If you use a static class or static methods or properties within a class, you would not use the object operator (“->”) but would instead use the scope resolution, or double colon, operator, like so:

<?php
MyClass::$staticProperty = 'Fred'; // Sets a values into the static class
MyClass::getStaticProperty(); // Gets a value from a static method
?>

Now that you have the power of operators at your fingertips, even if in a very basic sense, you can get busy with assigning and accessing goodies in arrays, objects and classes. And remember as you use these that nothing at all can replace the learning you would get from trying them out, especially when you try to use them the wrong way (error messages can be quite educational).

If I could leave you with one bit of advice it would be to get your hands dirty on some of them and see what the parser tells you when it chokes on one (or more) of them.

And have fun. Stepping in to object oriented programming can be a frustrating, painful experience for some. But it is definitely a rewarding one.

Handling multiple Sybase result sets in PHP on Ubuntu 8.10

A long time ago I was tasked with creating a PHP application that would talk to our Sybase database that drives our entire enterprise at work. This is not normally a big thing to do as one can simply enable the Sybase extension for PHP and have a database connection generally within minutes. However there was one thing that was an absolute necessity in this application that made it significantly more difficult to get it working: some parts of the application would be reliant upon stored procedures that returned multiple result sets.

First off let me say that any time you have the option to build stored procedures for your database quieries, do it. They are faster, safer, compiled and centralized and they keep your code from being littered with query builders all over the place. That said, this is neither the time nor the place to talk about the merits of stored procedures in application development. Just know that where I work there are no direct queries ever allowed to touch our database servers.

Knowing that I had to work under the requirement of handling multiple Sybase result sets I set out to find out how to do it and what I found was alarming. Few database extensions in PHP handle multiple result sets. In fact, as I was looking around it seemed that only the MySQLi extension and the SQL Server extension handled multiple result sets. But after a little searching around I found something called the “PHP Sybase CT driver enhancements” project on Sourceforge that essentially provided prepared statement handling and multiple result set handling for the PHP Sybase Extension. However, after trying to install it it became evident that the extension, as it was written, was still not usable in the state it was offered up for download in.

Not to worry, I have modified the package for compiling within a PHP 5 environment and have made a few changes to it that should allow it to be used as is. The source code archive file can be downloaded (in tar.gz format) by clicking here.

Please read the notes on this source code before installing it!

Before installation

Before we get started we need to cover a few assumptions:

  • You have a licensed copy of Sybase Adaptive Server
    I have not tried this against any Sybase database server other than Adaptive server.
  • You have the Sybase client installed or at the very least have the installer available
    For this exercise we are using a Red Hat RPM of the Sybase 12.5 client. Yes, we are installing on Ubuntu, which is essentially Debian and therefore does not use RPM files, but we will burn that bridge when we come to it.
  • You are comfortable building PHP extensions from source
    There is no way around this. In order to get this to work you will need to be able to build from source.
  • You have the php-devel package installed on the machine you building this extension for
    If you don’t have it, a quick sudo apt-get install php5-dev should do the trick. This will be necessary to build the Sybase extension from source.

Installation instructions

Ok, these are the steps I took in order to build the enhanced Sybase extension for PHP on my Ubuntu 8.10 desktop machine starting with Sybase ASE client and common packages in Red Hat RPM format.

  • Convert the Sybase 12.5 OpenClient and Sybase 12.5 Common RPM archives to DEB packages and install them
    To do this I used the alien package converter tool and, while inside the directory where the RPMs were living, issued the following command:
    $ alien -k sybase-common-12.5.0.1de-1.i386.rpm
    $ alien -k sybase-openclient-12.5.0.1esd-1.i386.rpm

    This created two new archives, in the directory I was in, in debian format named

    1. sybase-common-12.5.0.1DE-1_i386.deb
    2. sybase-openclient-12.5.0.1ESD-1_i386.deb

    I then issued the following commands to install them:
    $ sudo dpkg --install sybase-common-12.5.0.1DE-1_i386.deb
    $ sudo dpkg --install sybase-openclient-12.5.0.1ESD-1_i386.deb

    This made a directory named sybase-12.5 in the /opt directory.

  • Prepare your environment to build the extension
    To make things easier (and a little more compatible with the Red Hat way of doing things) I created a link inside of /top called sybase and pointed it to the sybase-12.5 directory.
    $ cd /opt
    $ ln -s -T /opt/sybase-12.5 sybase

    I then had to export some environment vars that are needed by the extension and the web server in order to handle communication with the Sybase server:
    $ export SYBASE=/opt/sybase
    $ export SYBASE_OCS=OCS-12_5
    $ export PATH=/opt/sybase/OCS-12_5/bin:$PATH
    $ export LD_LIBRARY_PATH=/opt/sybase/OCS-12_5/lib:/opt/sybase/OCS-12_5/lib3p:$LD_LIBRARY_PATH
    $ export INCLUDE=/opt/sybase/OCS-12_5/include:$INCLUDE
    $ export LIB=/opt/sybase/OCS-12_5/lib:$LIB

    Yes, I know that each one of these commands could have been placed in a file and sourced, but for some reason source is not available to my installation of Ubuntu so it was in fact easier and faster for me to do it this way. Do this how you will, but remember the values because you will need these later.

  • Build and install the php-sybase-ct extension from source against the Sybase client you just installed
    Remember that package I told you about earlier? The one that I said you could download? If not, get it now and unpack it to a directory somewhere where you have permission to unpack stuff on your system. For me, it was ~/Temp.

    Change to the directory you unpacked the source code to and configure it for make and installation using the php-devel package:
    $ cd ~/Temp
    $ phpize
    $ ./configure --with-sybase-ct=$SYBASE/$SYBASE_OCS
    $ make
    $ sudo make install

    Find out where your extensions directory is on your machine and quickly check it to make sure there is a php_sybase_ct.so file living in it. On my machine the extension directory is /usr/lib/php5/20060613+lfs/. Yours may be different.

    At this point you can safely do a sudo make clean but you might want to hold off on that until it is all working in case you need to rebuild at all. It does happen from time to time. Just sayin’.

  • Configure PHP to use the new extension
    Now we need to tell PHP to use the new extension we just built. To do that we need to create an ini file for the extension and put it inside of the extensions directory where PHP can find it. On my machine PHP looks for ini files to parse in /etc/php5/conf.d/ so naturally that is where I am going to go to to tell PHP to use this extension.

    $ cd /etc/php5/conf.d/

    Now we need to create an ini file and put into a directive to load the extension. You can use whatever editor you like. I prefer to use vim:
    $ sudo vim sybase_ct.ini

    Inside this file place the following two lines:
    ; Enable the sybase extension
    extension=sybase_ct.so

  • Configure your environment to load the correct environment variables whenever the machine starts
    This one caused me fits for a long time in Ubuntu. In order to ensure that you can use the Sybase extension from both the CLI and the web server you will need to take all of the environment variables that exported prior to building the extension and place them in both the /etc/profile startup script AND the web servers environment variable setting script. This caused countless hours of frustration and anger for me and I hope I can save you some angst with this little snippet.

    Add the environment vars to /etc/profile. You can use any editor you like. I like vim:
    $ sudo vim /etc/profile

    At the end of the file add the environment vars:
    export SYBASE=/opt/sybase
    export SYBASE_OCS=OCS-12_5
    export PATH=/opt/sybase/OCS-12_5/bin:$PATH
    export LD_LIBRARY_PATH=/opt/sybase/OCS-12_5/lib:/opt/sybase/OCS-12_5/lib3p:$LD_LIBRARY_PATH
    export INCLUDE=/opt/sybase/OCS-12_5/include:$INCLUDE
    export LIB=/opt/sybase/OCS-12_5/lib:$LIB

    Now add these same entries into your web server’s environment variables. I am using apache and assuming you are to. If not, consult your web server’s documentation for how to do this:
    $ sudo vim /etc/apache2/envvars

    Now add these entries to the end of the file:
    export SYBASE=/opt/sybase
    export SYBASE_OCS=OCS-12_5
    export PATH=/opt/sybase/OCS-12_5/bin:$PATH
    export LD_LIBRARY_PATH=/opt/sybase/OCS-12_5/lib:/opt/sybase/OCS-12_5/lib3p:$LD_LIBRARY_PATH
    export INCLUDE=/opt/sybase/OCS-12_5/include:$INCLUDE
    export LIB=/opt/sybase/OCS-12_5/lib:$LIB

  • Restart your web server
    Like everything that involves a change to the PHP environment or configuration on your machine, restart the web server. I am assuming this is being built upon an apache server. If not, you will need to know how to stop and start your web server or, at the very least, know how to reboot your machine:
    $ sudo apache2ctl stop
    $ sudo apache2ctl start

    Run a PHP info page or CLI call to see if it is loaded:
    $ php -m

    You should see sybase_ct. If not, something went wrong. If so, you are now golden.

At this point you should be able to run queries against your Sybase server AND handle multiple result sets using the sybase_next_result() function. There is no documentation for this function, but a quick read through of the mssql_next_result() function will tell pretty well how to use it.

Enjoy! And if this was at all helpful please leave a comment to let me know.

Notes on the PHP Sybase CT Enhanced extension

Some things to keep in mind when using this extension:

  • This extension is coded in PHP 4 source.
  • When I got my hands on it the code was still much in development phase. Not much has changed about that other than I removed debug output from it.
  • It does not handle connection failure well when the server does not respond. So unwell in fact that internally it causes segmentation faults and results in blank web pages upon failure. I do not know how to fix that.
  • If you know how to program in c or want to make it better, please feel free to do so. I have contacted the original authors of this extension and of the three only one has done any real work on it and none have worked on it in the last five years and really do not intend to. I was given permission to distribute it and modify it. But I really do not know what I am doing in c. Yet. 😉

Security basics – lock the front door

A recent attack on the popular microblogging site Twitter has produced a great deal of buzz around the social mediasphere and the developer community because of the nature of the attacks. Apparently the attack was a pretty basic dictionary attack against the front door of the Twitter site.

Jeff Atwood reports on his blog how the attack was carried out and how you, as a developer, can defend against dictionary attacks.

He provides a lot of information to assist you in protecting your data, or, as is often the case, your users data. One of the things that Jeff mentions is throttling failed login attempts against a wait time to deter the basic repetitive failed login attempt. He also mentions requiring a capcha/recapcha after a certain number of failures to make sure you are dealing with a human as opposed to a bot.

Google employs this principle. I have actually tested this (actually, I have had to use this as I forgot a Google password once). This is perhaps the cleanest validating type of login failure handler as it allows the user to make mistakes without penalizing them for not remembering. Believe it or not, there are some people that forget their passwords and choose to actually try to remember it instead of resetting it. I know, it seems archaic, but it does happen.

Another way to makes things better for your users is to not only allow a mix of numbers, letters – both upper and lower case, and special characters but to actually requre a mix of those types of characters. It may seem inconvenient at the time, it will always be less convenient than a security breach because of a password like “happiness”.

Regardless of what you choose to emply in terms of front door security I would suggest you read Jeff’s article. It has plenty of useful information about security and protecting against dictionary attacks.