Wednesday, July 21, 2010

Series pt. 3: Cool things you can do with PHP

Did you know: You can handle files the cool way using a bunch of SPL hot served classes - no dir(), glob() or anything of that.

Ok, lets talk about some every-day-work. Directory iteration, file access, file information, etc. PHP has some functions to cope with those tasks quite well ... But! We want to write OOP code, so why don't we use objects to handle those tasks? The answer is ... again ... use the SPL! You can find a short overview of the SPL's file related classes at http://php.net/manual/en/spl.files.php. In addition to that, the DirectoryIterator class brings some exciting methods for iterating directories. I've assembled a small example that combines most of the possible workflow, but it covers only an itch of what those classes are capable of.

$sMyDirectory = '/tmp/somedir';
$oDirIterator = new DirectoryIterator($sMyDirectory);

foreach ($oDirIterator as $oIterItem) {

 // $oIterItem is an instance of DirectoryIterator
 if ($oIterItem->isFile()) {
  //DirectoryIterator::getPathname() returns the full path
  $oFile = new SplFileInfo($oIterItem->getPathname());

  /*
   * If it is a symlink, resolve it
   * You can use getRealPath() for resolving
   * symlinks in the path structure
   */
  if ($oFile->isLink()) {
   $oFile = new SplFileInfo($oFile->getLinkTarget());
  }

  if ($oFile->isWritable()) {
   // We get an SplFileObject
   $oOpenFile = $oFile->openFile("wb");
   $oOpenFile->fwrite('Some Text, maybe even some UTF-8 Stuff? A €uro sign?');
   // close the opened file the hard way, if you really need
   // anyway, you can skip that, PHP does it for you.
   unset($oOpenFile);
  }
  else {
   throw new RuntimeException(
      "Requested file is not writable!");
  }
 }
}

Tuesday, July 20, 2010

Exception Translator Pattern

The exception translator pattern is mostly unknown in the PHP world (the missing usage of exceptions may explain this), but is quite well known in the Java world. The Springframework makes heavy usage of the pattern on their transaction engine. The pattern solves mostly a problem of modular projects with tons of exceptions and it's background must be explained:
Java knows two types of exceptions: checked and unchecked. The checked exceptions are those, which we have to announce to the compiler (by using the "throws" keyword). The unchecked ones are those which inherit from the parent class "RuntimeException". These are the bad guys ;) As a basic rule you can say:

  • checked exceptions for technical problems like validation or a missing database connection
  • unchecked exceptions for the real trouble 
The problem that we have to deal with is the very very different API situation. What if you have a transparent DAO with no idea where it gets the data from? 
You emit a call with a malformed id that simply does not exist. The webservice will answer with a myWebserviceDoesNotLikeYourIDException, the database may even ignore the problem and return null (and later on throw a NullPointerException) or another database may throw an EmptyResultSetException... But the only thing I (as the one who uses the DAO) want to know is "data? Yes : No"

The weapon of choice to clear things up may be the exception translator. It takes all the logic exceptions into account, brings them into a hierarchy and makes them accessible as unchecked children of RuntimeExceptions.  This makes it possible to break down the handling code for the exceptions to a minimum. In Java Spring manages this work for you - I've not seen any implementation in PHP. If anybody finds one, drop me a line ;). 

Monday, July 19, 2010

Series pt. 2: Cool things you can do with PHP

Did you know: There are native exceptions that are delivered with the SPL, why not use them?

You may know the "old times" in PHP 4 and lower, when we did not even have exceptions to throw around. This changed with PHP 5 and in addition to that the SPL gives you plenty of exceptions to categorize your application exceptions very well. You can find a class hierarchy diagram on helly's personal space on php.net. I want to pick one of the logic exception to give you an example how you can enhance your PHP code with the SPL exceptions.

Here is a simple class that has a magic __call method for accessing indexes of an array via a method.
class Foo {
 private $aValues = array();

 public function __construct(array $aValues) {
  $this->aValues = $aValues;
 }

 public function __call($sCallName, array $aArgs) {
  if (!(substr($sCallName, 0, 3) == 'get')) {
   throw new BadMethodCallException(
    'This class only supports methods '.
    'starting with "get".', 500);
  }
  // getMyIndex() -> myindex
  $sArrayIndex = strotolower(substr($sCallName, 4));

  if (!array_key_exists($sArrayIndex, $this->aValues)) {
   throw new BadMethodCallException(
    'You called for the wrong key!', 500);
  }
  
  return $this->aValues[$sArrayIndex];
 }
}

Hope this helps to understand a possible use of those type of exceptions. The big advantage of using those exceptions lies in the standardization of error reporting from your application.

In one of the articles I will write something about the exception translator pattern - a pattern that helps you integrate legacy or foreign code into your application. Using standard exceptions prevent a lot of the extra work!

Sunday, July 18, 2010

Series pt. 1: Cool things you can do with PHP

This series intends to focus on doing things based on mostly unknown features or behaviors in PHP. This is the first part and I want to talk about the visibility of class members.

Did you know: You can access private or protected members of instances within the context of its own class?

Let me show you an example to make things clear. This is our basic class:
class Foo {
 private $iInstanceId;
 private static $iInstanceCounter = 0;

 public static function factory() {
  $oObj = new self();
  $oObj->iInstanceId = ++self::$iInstanceCounter;
  return $oObj;
 }

 public function getInstanceId() {
  return $this->iInstanceId;
 }
}

The class is quite simple. We have a static member for "generating" the id and a instance bound property to save the id of the actual instance. The factory method creates a new object and modifies the private property $iInstanceId with the incremented value from the static class property.

The use of this class shows it:
$oFoo1 = Foo::factory();
print $oFoo1->getInstanceId() . PHP_EOL;

$oFoo2 = Foo::factory();
print $oFoo2->getInstanceId();
prints out (surprise, surprise)
1
2
The way this fact helps you to build e.x. good factories or accomplish other design pattern is up to your fantasy. If you have good examples for me, post a comment.

Must I do, because I can?

Many of you may know this situation. Fighting small birds with big cannons. I started to develop an URL shortener in Java to test some Java <-> MongoDB interaction. While working on the entities I encountered the question "shall I make it a user centric application or just an URL shortener?".

Beside the fact, that this question contains a lot of work to be done (or not to be done), it contains a highly philosophical manner.

Should I always go the "make it work" way, mostly because the customer pays it, or may I think it over and should I go for the longer but more extensible or feature-rich version? What can I present to my project manager without getting ripped my head off? (ok,ok the last one was moreover less a bad joke.)

I want to hear your version of the story. How much do you take extensibility into account when you look at the architecture of a project? Just make it work or do you look what might come afterwards? Feel free to drop a comment.

Saturday, July 17, 2010

Code QA is useless when critics are forbidden

You might know the situation: A bug crashed the build (or even the production system) because somebody did something wrong (without saying that he/she did it consciously). Mostly you get the message: "It does not matter who did it wrong. We have to fix it asap!"

I see this approach being totaly wrong for raising the quality of the team and it's members. Speaking for myself, I want to know what I did wrong and maybe getting an advice to make it better on the next occasion.

The consequence of not talking about mistakes leads to quite cruel social results in the team. Rumors raise and talking behind the back takes place in the daily communication an soon you will see that some people are "more liked" than others.

For all you team leaders and team members out there: talk, talk, talk ... and not only the brave-boy/-girl style.

Thursday, July 15, 2010

Writing a CSV export for Admidio

Admidio is a small CRM tool for sport clubs. The data is saved to a mysql database in a cruel way, if you see it from "let me change the system" point of view. The user related fields are extensible and saved in one table. The real user data is scaled vertically in another table. You get tuples like (entry_id, user_id, field_id, value). This is a horror to export in a horizontal scaled format like CSV! But! Here is a solution, written in python:

# -*- coding: utf-8 -*-
def main():
    import MySQLdb
    conn = MySQLdb.connect (host="localhost", user="root", passwd="", db="crm")
    cursor = conn.cursor ()
    cursor.execute ("SELECT usf_id, usf_name FROM adm_user_fields")
    aNameRows = cursor.fetchall()
    kvMapNames = {}
    for aNameRow in aNameRows:
        kvMapNames[aNameRow[0]] = aNameRow[1]

    headline = ",".join(kvMapNames.values()) + "\n"

    cursor.execute("SELECT DISTINCT usd_usr_id FROM adm_user_data")
    aUserData = cursor.fetchall()

    aCSVRows = []
    for row in aUserData:
        cursor.execute("SELECT * FROM adm_user_data WHERE usd_usr_id=%d ORDER BY usd_usf_id" % row[0])
        aData = cursor.fetchall()
        aDataPresent = {}

        for urow in aData:
            print urow
            aDataPresent[urow[2]] = urow[3]

        for missingKey in [k for k in kvMapNames.keys() if k not in aDataPresent.keys()]:
            aDataPresent[missingKey] = ""

        aCSVRows.append(",".join(aDataPresent.values()) + "\n")

    print headline
    print "".join(aCSVRows)
    f = open ("out.csv", "w")
    f.write(headline)
    f.write("".join(aCSVRows))
    f.close()


if __name__ == '__main__':
    main()