Using Xajax in an Object Oriented Environment

December 30th, 2008

The Database

The database, as mentioned above, is named test, with a single table called employees. It looks like this.

CREATE TABLE employees (
employee_id int(11) NOT NULL AUTO_INCREMENT,
employee_firstname varchar(25) NOT NULL,
employee_surname varchar(25) NOT NULL,
employee_dept varchar(25) NOT NULL,
PRIMARY KEY (employee_id)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

INSERT INTO employees VALUES
(1,'Simon','Brown','Janitor'),
(2,'Imran','Green','Programming'),
(3,'Troy','Blew','programmimg'),
(4,'Peter','Smith','Systems Engineering');

Initializing Xajax

To set up xajax within a class a class property needs to be declared to hold the object. Also, as this class uses PDO to conntect to a MySQL database, a class property can be set to hold the database instance also. These properties will be private, which means they can only be accessed from within the employees class.

The javascript that is generated by xajax needs to be public as it will be accessed from outside of the class itself, so a public $xajax_js variable is declared also

<?php

/**
 *
 * @class to define an animal
 *
 */
class employees
{
    /**
     * Database and xajax properties
     */
    private $db, $xajax;

    /**
     *The xajax generated javascript
     */
    public $xajax_js;

With the class properties set to hold the values, the actual initialization, or instantiation of the xajax, and PDO, classes can be made in the constructor. The code will now look like this.

<?php

    /**
     *
     * @class to define an animal
     *
     */
    class employees
    {
        /**
         * Database and xajax properties
         */
        private $db, $xajax;

        /**
         *The xajax generated javascript
         */
        public $xajax_js;

        /**
         *
         * @constructor
         *
         */
        public function __construct()
        {
            /*** set up the database connection ***/
            $this->db = new PDO("mysql:host=localhost;dbname=test", 'username', 'password');

            /*** set up the xajax environment ***/
            include 'xajax/xajax_core/xajax.inc.php';

            /*** a new xajax object ***/
            $this->xajax = new xajax;
        }

There is only a small difference there than to the procedural method. Stepping through the code, the database connection is made, and the resource assigned to the private $db property. Following this, is the actual xajax instantiation. In the procedural method, the xajax instance, was simply assigned to a variable named $xajax. This is much similar and is assignned to the property $xajax. Access to the xajax instance is now via $this->xajax.
Registering Functions

In the previous tutorial, the registering of functions was a simple call to the xajax register method.such as this..

<?php

$rqstButton = $xajax->register(XAJAX_FUNCTION, 'showText');

?>

When within a class, the register function is still used, however, with a few changes to the parameters. Instead of simply accepting the name of a function, an array is given with three elements. Each element does the following..

1. The name of the class method
2. The calling class
3. The name of the class method

With the class methods registered into $this->xajax the processRequest can be run, and the xajax javascript generated.

<?php

/*** register the xajax functions ***/
$this->xajax->register(XAJAX_FUNCTION, array('getEmployees', $this, 'getEmployees') );
$this->xajax->register(XAJAX_FUNCTION, array('getEmployeeData', $this, 'getEmployeeData') );

/*** process the request ***/
$this->xajax->processRequest();

/*** the path is relative to the web root mmmk ***/
$this->xajax_js = $this->xajax->getJavascript('/xajax')

The Object Response

There is no diffence to how the object response is generated within a class, when compared to calling fromsimple function. The same basic syntax applies.

<?php
    $objResponse = new xajaxResponse;
    $objResponse->assign('some_div', 'innerHTML', 'some content');
    return $objResponse;

So the class methods will follow the same. The class methods will look like this…

<?php
    /**
     *
     * @Purpose Get Empoyee data from database
     *
     * @param int employee_id The ID of the employee
     *
     * @return object An xajax object response
     *
     */
    public function getEmployeeData($employee_id)
    {
        /*** a new xajax response object ***/
        $objResponse = new xajaxResponse;

        $html = '<table>';
        /*** get employee info from database ***/
        $stmt = $this->db->prepare("SELECT * FROM employees WHERE employee_id = :employee_id");
        $stmt->bindParam(':employee_id', $employee_id, PDO::PARAM_INT);
        $stmt->execute();
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
        foreach( $result as $data )
        {
            $html .= '<tr><td>ID</td><td>'.$data['employee_id'].'</td><tr>
            <tr><td>Name</td><td>'.$data['employee_firstname'].' '.$data['employee_surname'].'</td></tr>
            <tr><td>Department</td></td>'.$data['employee_dept'].'</td></tr>';
        }
        $html .= '</table>';

        /*** assign to HTML to the innerHTML of the data_div ***/
        $objResponse->assign('data_div', 'innerHTML', $html);

        /*** return the object response ***/
        return $objResponse;
}


    /**
    *
    * @get the emplyees
    *
    * @return array
    *
    */
    public function getEmployees()
    {
        /*** a string to be returned ***/
        $html = '<select name="employees" onchange="xajax_getEmployeeData(this.value); return true;">';
        $html .= '<option value="">Select</option>';
        $stmt = $this->db->prepare("SELECT employee_id, employee_firstname FROM employees");
        $stmt->execute();
        foreach($stmt->fetchAll(PDO::FETCH_ASSOC) as $data)
        {
            $html .= '<option value="'.$data['employee_id'].'">'.$data['employee_firstname'].'</option>';
        }
        $html .= '</select>';

        /*** a new xajax response object ***/
        $objResponse = new xajaxResponse();

        /*** assign the innerHTML attribute to the new $content ***/
        $objResponse->assign("dropdown_div","innerHTML", $html);

        /*** return the object response ***/
        return $objResponse;
    }

The HTML

The HTML is actually just HTML, but within the document head, will be the javascript generated by the employees class. As the getJavascript method is called in the constructor, the xajax_js variable is immediately available and contains the xajax generated code that can be used directly in the HTML head.

This is done very simply but instantiating the employees class, and echo’ing the xajax_js variable.

<?php
    /*** a new employees instance ***/
    $employees = new employees;

    /*** display the xajax javascript ***/
    $xajax_js = $employees->xajax_js;

    /*** display the xajax javascript ***/
    echo $xajax_js;
?>

Putting It All Together

With all the parts in place, the completed script looks like this…

<?php

/**
 *
 * @class to define an animal
 *
 */
class employees
{
    /**
     * Database and xajax properties
     */
    private $db, $xajax;

    /**
     *The xajax generated javascript
     */
    public $xajax_js;

    /**
     *
     * @constructor
     *
     */
    public function __construct()
    {
        /*** set up the database connection ***/
        $this->db = new PDO("mysql:host=localhost;dbname=test", 'username', 'password');

        /*** set up the xajax environment ***/
        include 'xajax/xajax_core/xajax.inc.php';

        /*** a new xajax object ***/
        $this->xajax = new xajax;

        // $this->xajax->setFlag('debug', true);

        /*** register the xajax functions ***/
        $this->xajax->register(XAJAX_FUNCTION, array('getEmployees', $this, 'getEmployees') );
        $this->xajax->register(XAJAX_FUNCTION, array('getEmployeeData', $this, 'getEmployeeData') );

        /*** process the request ***/
        $this->xajax->processRequest();

        /*** the path is relative to the web root mmmk ***/
        $this->xajax_js = $this->xajax->getJavascript('/xajax');
    }

    /**
     *
     * @Purpose Get Empoyee data from database
     *
     * @param int employee_id The ID of the employee
     *
     * @return object An xajax object response
     *
     */
    public function getEmployeeData($employee_id)
    {
        /*** a new xajax response object ***/
        $objResponse = new xajaxResponse;

        $html = '<table>';
        /*** get employee info from database ***/
        $stmt = $this->db->prepare("SELECT * FROM employees WHERE employee_id = :employee_id");
        $stmt->bindParam(':employee_id', $employee_id, PDO::PARAM_INT);
        $stmt->execute();
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
        foreach( $result as $data )
        {
            $html .= '<tr><td>ID</td><td>'.$data['employee_id'].'</td><tr>
                <tr><td>Name</td><td>'.$data['employee_firstname'].' '.$data['employee_surname'].'</td></tr>
                <tr><td>Department</td></td>'.$data['employee_dept'].'</td></tr>';
        }
        $html .= '</table>';


        $objResponse->assign('data_div', 'innerHTML', $html);
        return $objResponse;
    }


    /**
    *
    * @get the emplyees
    *
    * @return array
    *
    */
    public function getEmployees()
    {
        /*** a string to be returned ***/
        $html = '<select name="employees" onchange="xajax_getEmployeeData(this.value); return true;">';
        $html .= '<option value="">Select</option>';
        $stmt = $this->db->prepare("SELECT employee_id, employee_firstname FROM employees");
        $stmt->execute();
        foreach($stmt->fetchAll(PDO::FETCH_ASSOC) as $data)
        {
            $html .= '<option value="'.$data['employee_id'].'">'.$data['employee_firstname'].'</option>';
        }
        $html .= '</select>';

        /*** a new xajax response object ***/
        $objResponse = new xajaxResponse();

        /*** assign the innerHTML attribute to the new $content ***/
        $objResponse->assign("dropdown_div","innerHTML", $html);

        /*** return the object response ***/
        return $objResponse;
    }
} /*** end of employee class ***/


/*** a new employee object ***/
$employees = new employees;

/*** display the xajax javascript ***/
$xajax_js = $employees->xajax_js;

?>

<html>
<body>
<head>
<title>PHPRO.ORG XAJAX</title>
<?php
    /*** display the xajax javascript ***/
    echo $xajax_js;
?>
</head>
<body>

<p id="button"><button type="button" onclick="xajax_getEmployees(); return true;">Show Employees</button></p>
<p id="dropdown_div"></p>
<div id="data_div"></div>

</body>
</html>

Intermediate Scripts, Tutorials

Introduction to XAJAX

December 30th, 2008

Hello World

Like all things, starting at the beginning is best. This script provides the absolute basics to getting Xajax working. The process is quite simply when broken down into smaller chunks. Like any PHP library, the class definition needs to be included. With xajax it is the xajax.inc.php bootstrap file that loads up the xajax environment and makes ready the ajax processes internally.

Xajax generates javascript code and provides a bridge, or callback, to PHP functions. To let Xajax know which functions are to be called, they must first be registered. The simple API of Xajax provides a register() function for this task. In the example below, the showText PHP function is registered.

When the register function is called, the returned object can be used to set parameters. In this example, the object is assigned to a variable named $rqstButton which is used later in the HTML to gene rate the onclick event code.

With the function registered, the requested function can be processed. This means the javascript for required to make a callback to PHP is generated internally and is ready to be retrieved with either the printJavascript() or getJavascript() methods.

The printJavascript() method, as the name suggests, just prints the javascript. However, a little more separation is nice, so the generated javascript can be assigned to a variable with the getJavascript() method. In these examples, the getJavascript() method is used to provide an level of separation between the HTML display code, and the PHP logic.

In the HTML, a simple echo statement is used to display the javascript generated by xajax. A little further down a call is made with javascript onClick event. The value for the onClick event is held in the rqstButton object and is simply echoed and that is really about all the javascript knowledge needed to get started, Xajax will do the rest.

But what of the showText() function itself? This function now becomes the engine room for the process. The content is contain in this function, however, in larger applications, the data may be sourced from external resources such as a database or file. A new response object is created, which will contain the information needed by xajax to perform the required actions. Again, the simple API provides a method to assign the content contained in the $content variable, to the innerHTML property of the target div named “my_div”. The object response is returned and the task is complete.

<?php
    /*** include the xajax bootstrap ***/
    include 'xajax/xajax_core/xajax.inc.php';

    /*** a new xajax object ***/
    $xajax = new xajax();

    /*** register a PHP function with xajax ***/
    $rqstButton = $xajax->register(XAJAX_FUNCTION, 'showText');

    /*** set the request button parameters ***/
    $rqstButton->setParameter(0, XAJAX_JS_VALUE, 0);

    /*** process the request ***/
    $xajax->processRequest();


    function showText()
    {
        /*** the content to assign to the target div ***/
            $content = 'Hello World';

        /*** a new response object ***/
        $objResponse = new xajaxResponse();

        /*** assign the innerHTML attribute to the new $content ***/
        $objResponse->assign("my_div","innerHTML", $content);

        /*** return the object response ***/
        return $objResponse;
    }

    /*** process the request ***/
    $xajax->processRequest();

    /*** the path is relative to the web root mmmk ***/
    $xajax_js = $xajax->getJavascript('/xajax');
?>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>

<head>

<title>PHPRO.ORG</title>
<?php echo $xajax_js; ?>
</head>

<body>
<button type="button" onclick="<?php $rqstButton->printScript(); ?>">Click me</button>
<div id="my_div">New text will happen here</div>
</body>

</html>

Manually Calling Requests

In the above code, the javascript to create the onClick event was generated by an object returned by the register() function. While the registration of the function needs to occur, the assigning of the variable does not, and the call could be made manually in the HTML document.

<?php

    /*** include the xajax bootstrap ***/
    include 'xajax/xajax_core/xajax.inc.php';

    /*** a new xajax object ***/
    $xajax = new xajax();

    /*** register a PHP function with xajax ***/
    $xajax->register(XAJAX_FUNCTION, 'showText');

    /*** process the request ***/
    $xajax->processRequest();


    function showText()
    {
        /*** the content to assign to the target div ***/
        $content = 'Hello World';

        /*** a new response object ***/
        $objResponse = new xajaxResponse();

        /*** assign the innerHTML attribute to the new $content ***/
        $objResponse->assign("my_div","innerHTML", $content);

        /*** return the object response ***/
        return $objResponse;
    }

    /*** process the request ***/
    $xajax->processRequest();

    /*** the path is relative to the web root mmmk ***/
    $xajax_js = $xajax->getJavascript('/xajax');
?>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>

<head>

<title>PHPRO.ORG</title>
<?php echo $xajax_js; ?>
</head>

<body>
<button type="button" onclick="xajax_showText();">Click me</button>
<div id="my_div">New text will happen here</div>
</body>

</html>

Debugging

Perhaps the most important functionality in the Xajax library is the debug option. When set, the debug option sends a print-out of the whole request process. This will prove invaluable when a script is not behaving as expected.

The debug flag is set, in most instances, immediately after the xajax object is instantiated. This means it will look a little like this.

<?php

    /*** include the xajax bootstrap ***/
    include 'xajax/xajax_core/xajax.inc.php';

    /*** a new xajax object ***/
    $xajax = new xajax();

    /*** set the debug flag ***/
    $xajax->setFlag('debug', true);

    /*** rest of script follows ... ***/

?>

Beginner Scripts, Tutorials

Creating Dropdowns with PHP and Xajax

December 30th, 2008

In this short tutorial we will look at putting together some form elements with PHP and Xajax. This will show how to dynamically fill form dropdown select menu’s asynchronisly with data from a MySQL database. The second dropdown select menu will then be populated with data from the database, based on a value from the first dropdown select menu. All this, without a page refresh.

Several elements will be used here, PHP, MySQL, and Xajax. No javascript is used, it is all dynamically generated via the Xajax libraries. We will use an imaginary cart for a PHPRO Bookstore to be the basis of the script.

The Database Schema

The basis for this tutorial is the PHPRO Bookstore. The database is simple with a table of categories and a table of books. Each book belongs to a category and each book(product) has an ID as does each category. Here is the SQL dump. So, create a database named phpro_cart dump this into it.

CREATE TABLE phpro_categories (
category_id int(11) NOT NULL auto_increment,
category_name varchar(30) NOT NULL,
category_description varchar(200) NOT NULL,
PRIMARY KEY (category_id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

INSERT INTO phpro_categories (category_id, category_name, category_description) VALUES
(1, 'romance', 'Mushy stuff'),
(2, 'Thriller', 'Murder Mystery and Mayhem'),
(3, 'Adventure', 'Swash buckling yarns'),
(4, 'Sport', 'Get out and about'),
(5, 'autobiography', 'whos who'),
(6, 'non fiction', 'Get the facts');

CREATE TABLE phpro_products (
product_id int(11) NOT NULL auto_increment,
category_id int(11) NOT NULL,
product_name varchar(30) NOT NULL,
product_price double NOT NULL,
PRIMARY KEY (product_id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

INSERT INTO phpro_products (product_id, category_id, product_name, product_price) VALUES
(1, 1, 'kiss me quick', 23.4),
(2, 1, 'stolen kiss', 58.44),
(3, 1, 'a long road', 12.4),
(4, 1, 'I never touched her', 72.46),
(5, 2, 'She did it', 39.39),
(6, 2, 'No he did', 29.44),
(7, 2, 'Broken alibi', 33.3),
(8, 2, 'The dark shadow', 44.4),
(9, 3, 'A pirates life', 73.2),
(10, 3, 'the mountain climber', 88.22),
(11, 3, 'The deep sea', 55.5),
(12, 3, 'the final frontier', 22.2),
(13, 4, 'Kicking goals', 33),
(14, 4, 'Scoring', 99.99),
(15, 4, 'Mouse Whittling', 55.5),
(16, 6, 'Bible', 22.4),
(17, 6, 'Koran', 22),
(18, 6, 'Bhagavad Gita', 44.3);

Connecting to the Database

With the above tables installed, we can move onto the script itself. Like many PHP script we need to connect to the dataase to collect the information we need. To achieve this a global instance is used of the PDO class. This class is taken directly from the PHPRO Tutorial http://www.phpro.org/tutorials/Introduction-to-PHP-PDO.html tutorial, and is repeat here for convenience.

<?php

/*** database class ***/
class db{

/*** Declare instance ***/
private static $instance = NULL;

/**
*
* the constructor is set to private so
* so nobody can create a new instance using new
*
*/
private function __construct() {
  /*** maybe set the db name here later ***/
}

/**
*
* Return DB instance or create intitial connection
*
* @return object (PDO)
*
* @access public
*
*/
public static function getInstance() {

 $hostname = 'localhost';
 $username = 'username';
 $password = 'password';
if (!self::$instance)
    {
    self::$instance = new PDO("mysql:host=$hostname;dbname=phpro_cart", $username, $password);
    self::$instance-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
return self::$instance;
}

/**
*
* Like the constructor, we make __clone private
* so nobody can clone the instance
*
*/
private function __clone(){
}

} /*** end of class ***/
?>

The Xajax Script

This script contains a few parts where the tasks are broken into several simple functions. The first two to look at are the getCategorData() function and the getProductData function. These do, as the name suggests, get the categories data and the products data from the database. The return value makes use of a small snippet that can be found here on PHPRO at http://www.phpro.org/examples/PDO-to-Array.html which formats the PDO result sets into a format we can use with the Xajax functions. Lets have a look at this section first, comments though-out the code will help guide you through. Note that we also include the xajax libraries here.

<?php

 /*** include the xajax libraries ***/
 include '/www/xajax/xajax_core/xajax.inc.php';


/**
 *
 * @convert pdo multi-d array to single d
 *
 * @param array $result
 *
 * @return $array
 *
 */
function pdo2array($result){
$new=array();
foreach ( $result as $val )
    {
    $keys = array_keys($val);
    $new[$val[$keys[0]]] = $val[$keys[1]];
    }
return $new;
}


/**
 *
 * @getCategoryData
 *
 * @return array
 *
 */
function getCategoryData()
 {
    /*** database instance ***/
    $db=db::getInstance();
    /*** the SQL query ***/
        $sql="SELECT category_id, category_name from phpro_categories";
    /*** always user prepared statements ***/
    $stmt = $db->prepare($sql);
    /*** execute the query ***/
    $stmt->execute();
    /*** use pdo2Array function to flatten out the array ***/
    return pdo2Array($stmt->fetchAll(PDO::FETCH_ASSOC));
 }

 /**
 *
 * @fetch data from products table
 *
 * @param INT $category_id
 *
 * @return array
 *
 */
 function getProductData($category_id)
 {
    /*** a new db instance ***/
    $db=db::getInstance();
    /*** the SQL query ***/
        $sql="SELECT product_id, product_name FROM phpro_products WHERE category_id=:category_id";
    /*** always user prepared statements ***/
    $stmt = $db->prepare($sql);
    /*** bind the category_id ***/
    $stmt->bindParam(':category_id', $category_id);
    /*** execute the query ***/
    $stmt->execute();
    /*** use pdo2Array function to flatten out the array ***/
    return pdo2Array($stmt->fetchAll(PDO::FETCH_ASSOC));
 }
?>

In the code above we fetch data from the phpro_categories table and the phpro_products table. the difference between the two is that the getProductsData function requires a single paramenter, the category_id. This is called when the first dropdown value is selected, and the category_id is passed from the Xajax to the PHP function, which, in turn, fetches all the books(products) from the respective category.
The Xajax Response

Here we see the functions that contain the Xajax goodness. As you can see they are simple PHP functions that return a value. These values are used by Xajax to generate the javascript needed to update the dropdown select menu’s.

<?php

 /**
 *
 * fetch categories into response object
 *
 * @return obj
 *
 */
 function getCategories()
 {
    /*** a new xajax response object ***/
    $objResponse=new xajaxResponse();
    $objResponse->script("clearOption('categories');");

    /*** get the categories from the database ***/
    $OL=array();
    $OL=getCategoryData();

    /*** a return value ***/
    $ret = '';

    /*** loop of the database results ***/
    foreach ($OL as $value => $text)
    {
        /*** set the option names and values ***/
        $ret .= '<option value="'.$value.'">'.$text.'</option>';
    }
    /*** assign the response to the categories div ***/
    $objResponse->assign('categories', 'innerHTML', $ret);
    /*** return the object response ***/
    return $objResponse;
 }


 /**
 *
 * @fetch the products into a response object
 *
 * @param INT $category_id
 *
 * @return object
 *
 */
 function getProducts($category_id)
 {
    /*** a new xajax response object ***/
    $objResponse=new xajaxResponse();
    $objResponse->script("clearOption('products');");

    /*** get the products data ***/
    $OL=array();
    $OL=getProductData($category_id);

    /*** get the products into a value ***/
    $ret = '';
    foreach ($OL as $value => $text)
    {
        /*** the product dropdown options ***/
    $ret .= '<option value="'.$value.'">'.$text.'</option>';
    }
    /*** assign the options to the products div ***/
    $objResponse->assign('products', 'innerHTML', $ret);
    /*** and return the response ***/
    return $objResponse;
 }


 /**
 *
 * @add item to cart
 *
 * @param array $FormValues
 *
 * @return object
 *
 */
 function addToCart($FormValues)
 {
    /*** a new xajax response ***/
    $objResponse=new xajaxResponse();
    /*** assign the category id to its div ***/
    $objResponse->assign("cart_category_id", "innerHTML", $FormValues["categories"]);
    /*** assign the product id to its div ***/
    $objResponse->assign("cart_product_id", "innerHTML", $FormValues["products"]);
    /*** return the object response ***/
    return $objResponse;
 }

 /*** a new xajax object ***/
 $xajax = new xajax();
 /*** register the PHP functions ***/
 $xajax->registerFunction('getCategories');
 $xajax->registerFunction('getProducts');
 $xajax->registerFunction('addToCart');
 $xajax->processRequest();
?>

The HTML Page

The final piece of this puzzle is some basic HTML and a few xajax calls to the PHP functions above. The script starts by clicking on the Show Categories link. This populates the categories dropdown menu by calling the getProducts() PHP function via the xajax_getProducts() function. To populate the second dropdown select menu an onChange event is used so when a new category is selected, the products dropdown is populated with a list of books from that category, along with the id of each item. When a book is selected, another onChange event is triggered and calls the addToCart() function. Of course, this function is incomplete and merely shows the category ID and the product ID of the item selected. From there you can handle the data any way you wish to complete your task.

<html>
<head>
<title>PHPRO Xajax Dropdowns</title>
<?php
    /*** print the javasript ***/
    $xajax->printJavascript('/xajax');
?>

</head>
<body>

<h2>XAJAX Cascading dropdowns</h2>

<p><a href="#" onClick="xajax_getCategories();">Show Categories</a></p>

<form name="cart_form" method="post" action="post" id="cart_form">

  <select name="categories" id="categories" onChange="xajax_getProducts(this.value);">
     <option value="-1">(No Selection)</option>
  </select>

  <select name="products" id="products" onChange="xajax_addToCart(xajax.getFormValues('cart_form'));">
     <option value="-1">(No Selection)</option>
  </select>

<p>Category ID:</p>
<div id="cart_category_id"></div>
<p>Product ID:</p>
<div id="cart_product_id"></div>

</form>
</body>
</html>

Putting it all together

As with all good tutorials, a completed script has been prepared to work out-of-the-box..

<?php

/*** database class ***/
class db{

/*** Declare instance ***/
private static $instance = NULL;

/**
*
* the constructor is set to private so
* so nobody can create a new instance using new
*
*/
private function __construct() {
  /*** maybe set the db name here later ***/
}

/**
*
* Return DB instance or create intitial connection
*
* @return object (PDO)
*
* @access public
*
*/
public static function getInstance() {

 $hostname = 'localhost';
 $username = 'username';
 $password = 'password';
if (!self::$instance)
    {
    self::$instance = new PDO("mysql:host=$hostname;dbname=phpro_cart", $username, $password);
    self::$instance-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
return self::$instance;
}

/**
*
* Like the constructor, we make __clone private
* so nobody can clone the instance
*
*/
private function __clone(){
}

} /*** end of class ***/

 /*** include the xajax libraries ***/
 include '/www/xajax/xajax_core/xajax.inc.php';


/**
 *
 * @convert pdo multi-d array to single d
 *
 * @param array $result
 *
 * @return $array
 *
 */
function pdo2array($result){
$new=array();
foreach ( $result as $val )
    {
    $keys = array_keys($val);
    $new[$val[$keys[0]]] = $val[$keys[1]];
    }
return $new;
}


/**
 *
 * @getCategoryData
 *
 * @return array
 *
 */
function getCategoryData()
 {
    /*** database instance ***/
    $db=db::getInstance();
    /*** the SQL query ***/
    $sql="SELECT category_id, category_name from phpro_categories";
    /*** always user prepared statements ***/
    $stmt = $db->prepare($sql);
    /*** execute the query ***/
    $stmt->execute();
    /*** use pdo2Array function to flatten out the array ***/
    return pdo2Array($stmt->fetchAll(PDO::FETCH_ASSOC));
 }

 /**
 *
 * @fetch data from products table
 *
 * @param INT $category_id
 *
 * @return array
 *
 */
 function getProductData($category_id)
 {
    /*** a new db instance ***/
    $db=db::getInstance();
    /*** the SQL query ***/
        $sql="SELECT product_id, product_name FROM phpro_products WHERE category_id=:category_id";
    /*** always user prepared statements ***/
    $stmt = $db->prepare($sql);
    /*** bind the category_id ***/
    $stmt->bindParam(':category_id', $category_id);
    /*** execute the query ***/
    $stmt->execute();
    /*** use pdo2Array function to flatten out the array ***/
    return pdo2Array($stmt->fetchAll(PDO::FETCH_ASSOC));
 }

 /**
 *
 * fetch categories into response object
 *
 * @return obj
 *
 */
 function getCategories()
 {
    /*** a new xajax response object ***/
    $objResponse=new xajaxResponse();
    $objResponse->script("clearOption('categories');");

    /*** get the categories from the database ***/
    $OL=array();
    $OL=getCategoryData();

    /*** a return value ***/
    $ret = '';

    /*** loop of the database results ***/
    foreach ($OL as $value => $text)
    {
        /*** set the option names and values ***/
        $ret .= '<option value="'.$value.'">'.$text.'</option>';
    }
    /*** assign the response to the categories div ***/
    $objResponse->assign('categories', 'innerHTML', $ret);
    /*** return the object response ***/
    return $objResponse;
 }


 /**
 *
 * @fetch the products into a response object
 *
 * @param INT $category_id
 *
 * @return object
 *
 */
 function getProducts($category_id)
 {
    /*** a new xajax response object ***/
    $objResponse=new xajaxResponse();
    $objResponse->script("clearOption('products');");

    /*** get the products data ***/
    $OL=array();
    $OL=getProductData($category_id);

    /*** get the products into a value ***/
    $ret = '';
    foreach ($OL as $value => $text)
    {
        /*** the product dropdown options ***/
    $ret .= '<option value="'.$value.'">'.$text.'</option>';
    }
    /*** assign the options to the products div ***/
    $objResponse->assign('products', 'innerHTML', $ret);
    /*** and return the response ***/
    return $objResponse;
 }


 /**
 *
 * @add item to cart
 *
 * @param array $FormValues
 *
 * @return object
 *
 */
 function addToCart($FormValues)
 {
    /*** a new xajax response ***/
    $objResponse=new xajaxResponse();
    /*** assign the category id to its div ***/
    $objResponse->assign("cart_category_id", "innerHTML", $FormValues["categories"]);
    /*** assign the product id to its div ***/
    $objResponse->assign("cart_product_id", "innerHTML", $FormValues["products"]);
    /*** return the object response ***/
    return $objResponse;
 }

 /*** a new xajax object ***/
 $xajax = new xajax();
 /*** register the PHP functions ***/
 $xajax->registerFunction('getCategories');
 $xajax->registerFunction('getProducts');
 $xajax->registerFunction('addToCart');
 $xajax->processRequest();
?>


<html>
<head>
<title>PHPRO Xajax Dropdowns</title>
<?php
    /*** print the javasript ***/
    $xajax->printJavascript('/xajax');
?>

</head>
<body>

<h2>XAJAX Cascading dropdowns</h2>

<p><a href="#" onClick="xajax_getCategories();">Show Categories</a></p>

<form name="cart_form" method="post" action="post" id="cart_form">

  <select name="categories" id="categories" onChange="xajax_getProducts(this.value);">
     <option value="-1">(No Selection)</option>
  </select>

  <select name="products" id="products" onChange="xajax_addToCart(xajax.getFormValues('cart_form'));">
     <option value="-1">(No Selection)</option>
  </select>

<p>Category ID:</p>
<div id="cart_category_id"></div>
<p>Product ID:</p>
<div id="cart_product_id"></div>

</form>
</body>
</html>

Intermediate Scripts, Tutorials

Post Form To Self

December 29th, 2008

Using xajax to post a form to itself is same as posting any other form. Usually this simply requires the form action to be omitted, or given a path to itself. It is only when the form is to be submitted asychronously that the response is different. By submitting asychronously, the page does not need to be refreshed, and any reponse from the form is displayed.

<?php

/*** include the xajax library ***/
include 'xajax/xajax_core/xajax.inc.php';

/*** a new xajax object ***/
$xajax = new xajax();

/*** Register the function ***/
$xajax->registerFunction("myFunction");


function myFunction($string)
{
    if($string == 'wombat')
    {
        $content = 'Animal is a wombat';
        $color = 'green';
    }
    else
    {
        $content = 'Animal is not a wombat';
        $color = 'red';
    }

/***  A new xajaxResponse object ***/
$objResponse = new xajaxResponse();

/*** assign the innerHTML attribute of to whatever the new $content ***/
$objResponse->assign("element_id","innerHTML", $content);

/*** assign a color to the  element ***/
$objResponse->assign("element_id","style.color",$color);

/*** return the  xajaxResponse object ***/
return $objResponse;
}

/*** process the request ***/
$xajax->processRequest();

/*** assign the generated javascript to a variable ***/
$xajax_js = $xajax->getJavascript('/xajax');

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>

<head>
<title>PHPRO.ORG</title>
<?php
    echo $xajax_js;
?>
</head>
<body>
<form name="my_form" id="my_form" method="post">
<input type="text" name="animal_id" id="animal_id" />
<input type="button" onclick="xajax_myFunction(xajax.$('animal_id').value);" value="Check Animal" />
</form>
<div id="element_id">Please enter an animal</div>

</body>
</html>

Stepping through the above script, it starts off innocently enough by including the xajax library and creating a new xajax object and then a function named myFunction is registered. The myFunction function performs a simply comparison of the data sent to it from the form. The function simply tests if the text sent is the word ‘wombat’. If the the text matches, a message is created, and a color is set for the return text (green if it matches, red if it does not match).

When the string matching is resolved, a new response object is created. The magic happens in the next two lines of code.

<?php

/*** assign the innerHTML attribute of to whatever the new $content ***/
$objResponse->assign("element_id","innerHTML", $content);

/*** assign a color to the  element ***/
$objResponse->assign("element_id","style.color",$color);

In the above two lines of code, the content is assigned to the innerHTML of the element with the ID of element_id. In the second line the color of the text is assigned in the same manner. The response object when returned updates these asychronously.

Adding Effects

As was seen above, the magic happens within the response object for asychronous display. This functionality can be extended to call and external javascript. Here the scriptaculous library is used to create a fade effect using the xajax script method.

The xajax script method allows the plugging in of external libraries and to make calls to functions within them. This is an method called from the xajax response object. The whole script is reproduced there with the javascript includes in place in the document head and the xajax script call.

<?php

/*** include the xajax library ***/
include 'xajax/xajax_core/xajax.inc.php';

/*** a new xajax object ***/
$xajax = new xajax();

/*** Register the function ***/
$xajax->registerFunction("myFunction");


function myFunction($string)
{
    if($string == 'wombat')
    {
        $content = 'Animal is a wombat';
        $color = 'green';
    }
    else
    {
        $content = 'Animal is not a wombat';
        $color = 'red';
    }

/***  A new xajaxResponse object ***/
$objResponse = new xajaxResponse();

/*** assign the innerHTML attribute of to whatever the new $content ***/
$objResponse->assign("element_id","innerHTML", $content);
/*** assign a color to the  element ***/
$objResponse->assign("element_id","style.color",$color);

/*** apply and effect to the element_id ***/
$objResponse->script("new Effect.Opacity('element_id', { duration: 2.0, transition: Effect.Transitions.linear, from: 1.0, to: 0.5 });");


/*** return the  xajaxResponse object ***/
return $objResponse;
}

/*** process the request ***/
$xajax->processRequest();

/*** assign the generated javascript to a variable ***/
$xajax_js = $xajax->getJavascript('/xajax');

?>
<html>

<head>
<title>PHPRO.ORG</title>

<script src="scriptaculous/lib/prototype.js" type="text/javascript"> </script>
<script src="scriptaculous/src/scriptaculous.js?load=effects,dragdrop" type="text/javascript"></script>

<?php
    echo $xajax_js;
?>
</head>
<body>
<form name="my_form" id="my_form" method="post">
<input type="text" name="animal_id" id="animal_id" />
<input type="button" onclick="xajax_myFunction(xajax.$('animal_id').value);" value="Check Animal" />
</form>
<div id="element_id">Please enter an animal</div>

</body>
</html>

With the new changes in place, the call to the scriptaculous javascript library is completed and the fade effect is actioned when the script is called. Be sure to check the paths to the scriptaculous libraries in the HTML head. This is often a cause of the effect not working.

Thanks goes to PHPro for the script.

Intermediate Scripts, Tutorials

XAJAX is easy

December 17th, 2008

xajax is easy! Just include xajax, register a function (or an object or class method)…

<?php
include './xajax/xajax_core/xajax.inc.php';

$xajax = new xajax();

$rqstAdd =& $xajax->register(XAJAX_FUNCTION, 'doAdd');
$rqstReset =& $xajax->register(XAJAX_FUNCTION, 'doReset');

// set the parameters
$rqstAdd->setParameter(0, XAJAX_JS_VALUE, 39);
$rqstAdd->setParameter(1, XAJAX_JS_VALUE, 571);

$xajax->processRequest();

function doAdd($a, $b)
{
    $response = new xajaxResponse();
    $response->assign('answer', 'innerHTML', $a + $b);
    $response->assign('reset', 'style.display', 'block');
    return $response;
}

function doReset()
{
    $response = new xajaxResponse();
    $response->clear('answer', 'innerHTML');
    $response->assign('reset', 'style.display', 'none');
    return $response;
}

then add a call to the function in your HTML or javascript…

<form action="#" method="post">
<input type="button" onclick="<strong><?php $rqstAdd->printScript(); ?></strong>" id="btnAdd" value="Click Me" />
<input type="button" onclick="<strong><?php $rqstReset->printScript(); ?></strong>" id="btnReset" value="Reset" />
<p id="answer"></p>
</form>

Beginner Scripts, Tutorials