Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Mastering Facebook application development with PHP, IBM Rational Application Developer, IBM WebSphere Application Server, and DB2, Part 2: Using Java and PHP in parallel

Jake Miles (jacob.miles@gmail.com), Freelance writer, Conde Nast
Author photo
Jake Miles is a senior developer at Conde Nast, currently working with Facebook, Myspace, and OpenSocial applications, using Java, PHP, Adobe Flex and Javascript. He has been working as a professional developer for 10 years and has been an avid student and tinkerer since he was 10. He also teaches on a volunteer basis, and believes that anyone can learn anything if taught clearly enough.

Summary:  Part 2 of this tutorial series covers the details involved for developing the Facebook application that you started in Part 1. Build a Facebook interface for an existing stock brokerage firm that enables online portfolio management. Learn one approach for dividing an application's functionality between PHP and Java components, and use the Spring framework to apply a standard MVC architecture to the Java™ code. This tutorial series steps you through the process of developing a fully functioning Facebook application using WebSphere® Application Server, Rational® Application Developer, Zend Core for IBM, PHP 5, and DB2®.

View more content in this series

Date:  02 Jun 2008
Level:  Intermediate PDF:  A4 and Letter (554 KB | 42 pages)Get Adobe® Reader®

Activity:  24110 views
Comments:  

Connecting to the database in PHP

Now you'll connect to the same DB2 database from PHP running in Zend Core For IBM, and create a controller and view that test that connection. To maintain a similar abstraction to that of the DataSource on the Java side, you'll create a class Db2DataSource that's responsible for maintaining the connection to DB2 and for transactions against that connection, and that uses the Properties object for its connection/login values. You'll also use a StocksDao class as you did in Java, that uses a Db2DataSource to access the application's tables. Using a common structure in the Java and PHP halves of the application will allow you to move between them more easily, allowing you to implement features of your Facebook application in whichever technology is more appropriate without concern for compromising the code.

Communicating with DB2

First write Db2DataSource to encapsulate DB2 access. In the lib sub-directory, create Db2Database.php as in Listing 20.


Listing 20. Class Db2DataSource (PHP)
                    
class Db2DataSource extends Injectable {

  private $connection;

  public function __construct($properties, $persist=true) {
    parent::__construct($properties);
    $this->connect ($persist);
  }

  private function connect ($persist=true) {

    $connectionString = 
      "DRIVER={IBM DB2 ODBC DRIVER};" .
      "DATABASE=$this->database;" .
      "HOSTNAME=$this->hostname;" . 
      "PORT=$this->port;" . 
      "PROTOCOL=TCPIP;" . 
      "UID=$this->username;" . 
      "PWD=$this->password;";

    if ($persist) {
      $this->connection = db2_pconnect($connectionString, '', '');
    } else {
      $this->connection = db2_connect($connectionString, '', '');    
    }
    
    if (! $this->connection) {
      throw new Exception ("Db2DataSource -- couldn't connect to DB2: " . 
               db2_conn_errormsg());
    } 
  }

  public function close() {
    if ($this->connection) {
      db2_close($this->connection);
    }
  }
}

The constructor takes a Properties object because it's an Injectable, and a $persist flag specifying whether to create a persistent database connection that survives between requests or one that is created anew each time. connect() creates the standard DB2 connection string containing the driver, protocol, and connection information for the specific database. The close() method closes the connection if a valid one exists. Note that connect() refers to these values as instance variables, though they are actually specified in a properties file (shown below); the Injectable subclass insulates Db2DataSource from this detail other than the need to accept a Properties object in its constructor.

Now that you can connect to DB2, you can query it and write data to it.

Start with a generic executeQuery() method that wraps the call to db2_exec() and throws an Exception reporting any error msg obtained through db2_stmt_errormsg() if the query fails (see Listing 21).


Listing 21. Db2DataSource.executeQuery()
                    

public function executeQuery($query) {
    $result = db2_exec($this->connection, $query);
    if ($result == null) {
      throw new Exception("Db2DataSource.executeQuery failed on query [$query], 
DB2 error is " . db2_stmt_errormsg());
    }
    return $result;
  }

Then add a fetchObjects() method that uses executeQuery(), returning an array of PHP objects in response to a SQL query (see listing 22). Note that db2_fetch_object() puts fields on the returned objects in ALL CAPS, e.g., $stock->TICKER, not $stock->ticker.


Listing 22. Db2Database.fetchObjects()
                    
public function fetchObjects($query) {
    $result = $this->executeQuery($query);
    $objects = array();
    while ($rowObject = db2_fetch_object($result)) {
      $objects[] = $rowObject;
    }
    return $objects;
}

Now that you have a generic class for connecting to DB2 and executing DB2 queries, as you did on the Java code side you'll create a StocksDao class that contains application-specific queries.


Class StocksDao

StocksDao will contain all of the actual SQL queries, as it does in the Java code side. First, let's add a method for obtaining all the available stocks (see Listing 23).


Listing 23. StocksDao.php
                    
<?php

class StocksDao {

  private $db;

  public function StocksDao($db) {
    $this->db = $db;
  }
  
  public function fetchAllStocks() {
    return $this->db->fetchObjects('select * from stock');
  }
}

?>

Note that StocksDao holds onto a $db object (a Db2DataSource) that it uses for all database access, and therefore StocksDao will contain almost no code except the specific SQL queries you need.

Figure 7 provides a map of the PHP data access components for comparison with the analogous diagram on the Java code side in Figure 6. The Java data source involved more pieces and required more configuration work, but in return provides more security, scalability and an industry standard.


Figure 7. Accessing the data in PHP
Accessing the data in PHP

Using an abstract controller base class in PHP

Recall that ActionDispatcher will create a PHP controller, give it a Properties object, and call an execute() method on it, expecting back a ModelAndView object to render the view, exactly as on the Java code side. Since you'll want a database connection in all of your controllers, make them all subclasses of a AbstractStockDemoController class, which itself subclasses AbstractController (see Listing 24). All of your application-specific PHP code should go in the app subdirectory of fb_stock_demo.


Listing 24. AbstractStockDemoController class (PHP)
                    
abstract class AbstractStockDemoController extends AbstractController {

  protected $db;
  protected $dao;

  public function __construct() {
    
  }

  public function execute() {
    
    try {
     
      $this->db = new Db2DataSource($this->properties, 'db');    
      
      $this->dao = new StocksDao ($this->db);

      $response = $this->executeSpecific();

      $this->db->close();

      return $response;

    } catch (Exception $e) {     
      $this->db->close();
      throw $e;
    }
  }

  protected abstract function executeSpecific();
}

AbstractStockDemoController implements the execute() method called by ActionDispatcher, connects to the database using the "injected" properties file, specifying db as the prefix to use when looking up database connection properties, creates a StocksDao from it for use by the subclasses, and calls the abstract executeSpecific() method. The subclass implements executeSpecific() to handle the specifics of the request. Execute() also makes sure to close the database connection. Note that because PHP does not provide a finally construct as in Java code, you need to do so both in the try and catch blocks. You provide the empty __construct() so that the subclass can call parent::__construct() (it shouldn't have to know that it doesn't have to for this specific base class).


Testing the PHP data source with a controller and view

With the abstract controller class in place you can create a subclass for testing the database connection, DbTestController, as in Listing 25. Put DbTestController.php in the app sub-directory under fb_stock_demo.


Listing 25. DbTestController PHP class
                    
class DbTestController extends AbstractStockDemoController {
  public function executeSpecific() {
    return new ModelAndView ("dbTestView.php",
                       $this->dao->fetchAllStocks());
  }
}

This probably looks familiar. The executeSpecific() method, called by the base class's execute() method, fetches the stocks and returns the view (dbTestView.php) and model (the array of Stock objects), just as the controller did on the Java code side, and ActionDispatcher will render dbTestView.php using the supplied model of stocks (see Listing 26). Put dbTestView.php in the app directory along with the controller.


Listing 26. dbTestView.php
                    
The result of calling DbTestController was:
<br/><br/>

<?
foreach ($model as $stock):
?>

Stock <?= $stock->ID ?>: <?= $stock->TICKER ?> <br/>

<?
endforeach;
?>

Note that you have to access the returned objects' fields using ALL CAPS, because this is how db2_fetch_object() created the row objects.

You've already created an entry for this controller in .htaccess under the request key phpDbTest to dispatch to the PHP side of the application; now you need to provide a key for ActionDispatcher. Since this key is injected, create an app.properties containing an entry for the new controller (see Listing 27), in a conf subdirectory under fb_stock_demo.


Listing 27. app.properties
                    
ActionDispatcher/dbTest=DbTestController

Finally, to provide the database connection information, create file db.properties next to app.properties, containing the contents of Listing 28.


Listing 28. db.properties
                    
Db2DataSource/database=stocks
Db2DataSource/hostname=localhost
Db2DataSource/port=50000
Db2DataSource/username=[your operating system username]
Db2DataSource/password=[your operating system password]

You could inject any other properties into any other classes you wish by creating similar entries in app.properties (or another file, as long as index.php includes it when creating the Properties object).

To confirm that your lightweight MVC framework and DB2 connection are working on the PHP side, go to http://localhost/fb_stock_demo/phpDbTest in the browser, and you'll see your view populated with stocks from the database.

5 of 9 | Previous | Next

Comments



static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational, WebSphere, Information Management
ArticleID=310576
TutorialTitle=Mastering Facebook application development with PHP, IBM Rational Application Developer, IBM WebSphere Application Server, and DB2, Part 2: Using Java and PHP in parallel
publish-date=06022008
author1-email=jacob.miles@gmail.com
author1-email-cc=troy@backstopmedia.com