Drupal7 APIs, Objects and the Trees from the Forest

David G - DrupalDrupal can sometimes seem complicated to use. There are many sub-systems within Drupal and provide many programming mechanisms and Core APIs to adapt Drupal to your needs. One such sub-system of Drupal is the Database Abstraction Layer which is a wrapper to the php PDO library — adding useful functions and facilities to support multiple database vendors in a unified API.

In addition to the default PDO query interfaces, Drupal supports an Object Oriented Query Builder API to build reusable, extensible dynamic queries. In practice these are SQL queries that other modules could interact with and change during the execution of a page request. SQL Select queries also support the concept of “Extenders” that allow modification of how queries are executed at runtime.

So when creating something like an Extender it can seem really really complicated. There seems to be sooo much pre-requisite knowledge, and the Drupal subsystems can be intimidating!

I was recently shown a method of a custom Extender class and the issue that sometimes it returned NULL as opposed to an empty DatabaseStatementBase object as expected — and in this thread the author of the questions and others argued over technical jargon. But this Class and logic is still just PHP and SQL. The fix need not be complex!

The custom code I was shown was:

public function execute() {
$sql = $this->sql;
switch ($this->function) {
  case 'db_query':
    if ($this->args) {
      $args = $this->args;
      uksort($args,"si_stats_sort_by_length");
      foreach($args as $name => $value) {
        $sql = str_replace("{" . $name . "}",$value,$sql);
        if (is_array($value)) {
          $sql = str_replace($name,"('" . implode("', '",$value) . "')",$sql);
        } else {
          $sql = str_replace($name,"'" . str_replace("'","''",$value) . "'",$sql);
        }
      }
      try {
        $query = db_query($sql);
      }
      catch (Exception $e) {
        // log the error
        $msg = $e->getMessage() . "\n";
        $msg .= $e->getTraceAsString() . "\n";
        mylog($msg . PHP_EOL . PHP_EOL . $sql, debug_backtrace(), LOG_ERROR);
      }
      return $query;
    } else {
      try {
        $query = db_query($sql);
      }
      catch (Exception $e) {
        // log the error
        $msg = $e->getMessage() . "\n";
        $msg .= $e->getTraceAsString() . "\n";
        mylog($msg . PHP_EOL . PHP_EOL . $sql, debug_backtrace(), LOG_ERROR);
      }
      return $query;
}

The solution I proposed was simply to amend the return statement of the method to check that the return type was the expected object type:

if (is_a($query, 'DatabaseStatementBase')) {
   return $query;
} else {
  return $empty = new DatabaseStatementBase(Database::getConnection());
}

Even though the Drupal API can seem daunting, and appear to require alot of programming expertise oftentimes it’s possible to develop simple solutions if the underlying problem is analyzed you attempt to break it down into it’s simplest and smallest components. My point is that even if you don’t understand allllll those subsystems or Object Oriented style programming — I look at the issue and think the return $query is wrong; how can fix or change that 1 execution statement to be provide the correct business logic. That is a small problem to focus on and amend!

For those interested the issue I was describing was this Drupal StackExchange issue.

Looking for quality web hosting? Look no further than Arvixe Web Hosting!

Tags: , , , , | Posted under Drupal | RSS 2.0

Author Spotlight

David Gurba

I am a web programmer currently employed at UCSB. I have been developing web applications professionally for 8+ years now. For the last 5 years I’ve been actively developing websites primarily in PHP using Drupal. I have experience using LAMP and developing data driven websites for clients in aviation, higher education and e-commerce. If you’d like to contact me I can be reached at david.gurba@arvixe.com

Leave a Reply

Your email address will not be published. Required fields are marked *