Moazzam’s Ramblings

13Mar/108

PHP and Sabre

What is Sabre?

Sabre is a company that has data of all flight schedules, etc. And, using their system, you can book flights, hotels, rent cars, etc.

Getting PHP to talk with Sabre

I tried PHP Soap and nuSoap. They both didn't work for me because of their limitations. So I ended up writing a small script of my own that talks with Sabre for me after I realized that the headers being sent by all the SOAP libraries I tried, were not compatible with Sabre's web services.

Sabre checks the "Content-Type" header in your request. If that is not "text/xml", you will always get an error, even if your xml is correct.

Here's a little piece of code that should help with the transport part.  I will leave the generation of XML to you.

/**
 * Sabre class (for connecting to Sabre web services)
 * @author Moazzam Khan <moazzam at moazzam-khan dot com>
 * @version $Id$
 */
class Sabre {
	public $host;
	public $port;
	public $timeout;
 
	public function Sabre()
	{
		$this->timeout = 30;
	}
 
	public function makeRequest($body)
	{
		$header = "POST /websvc HTTP/1.1\r\n"
					. "Host: {$this->host}:{$this->port}
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Content-Type: text/xml
Content-Length: ".strlen($body)."
Pragma: no-cache
Cache-Control: no-cache";
 
		$fp = fsockopen("ssl://".$this->host, $this->port, $errno, $errstr, $this->timeout);
		if(!$fp){
			print "SOCKET ERROR $errstr ($errno)\n";
		} else {
				//send the request
				fputs($fp, $header."\r\n\r\n".$body, strlen($header."\r\n\r\n".$body));
				stream_set_timeout($fp, 30);
				stream_set_blocking ($fp, 1);
				while (!feof($fp)) {
					$line = fread($fp, 2048);
					if (trim(strlen($line)) < 10) continue;
					$output .= $line;
				}
				fclose($fp);
		}
		$ret = explode("\r\n\r\n", $output);
		$ret = explode("\r\n", $ret[1]);
		for ($i=0; $i<count($ret); ++$i)
			if (strlen($ret[$i]) < 5) $ret[$i] = '';
		return implode('', $ret);
	}
}
20Jan/090

Processing forms in PHP

For this article, I will assume that you (the reader) know what a form is and have a general idea of what needs to be done on the HTML side to submit a form. I will cover a bit about what needs to be done but I will not go into details (it will be enough for you to get through form submissions :) )

Among all the languages I have come across processing a form in PHP is the easiest. PHP was made with web development in mind and it shows in its ease of use.  PHP provides you with 3 variables that can be used to access the information sent through a web page. They are :

  • $_POST
  • $_GET
  • $_REQUEST

These variables are already present when PHP's code is run. You don't have to do anything special. $_POST contains all variables sent through a post request. $_GET contains all the variables sent through a GET request (in a query string). $_REQUEST contains the information sent through both post and get(query string).

Let's take a look at an example shall we. Here is an HTML page with a form :

 
<form action="index.php" method="post"> 
    Name: <input name="name" type="text" ><br>
    Email: <input name="email" type="text" > <br>
    Message :<br>
    <textarea cols="40" rows="10" name="message"></textarea><br>
    <input name="submit" type="submit" value="Send" > 
    <input type="reset" >
</form>

All the form elements are enclosed in between <form> and </form> tags. The attribute action="index.php" lets the browser know where the form is to be submitted. In this case, it is submitted to index.php. And, method="post" lets the browser know that the method being used to submit the form is post (and not get). In every form you need one "button" or image that will submit the form. In the above code, it is a button. Now that we know the form we will use to submit the information. Let's take a look at the PHP page which will process it.

<?php
 
/** 
 * This code will send an email with all the information submitted in the form
 */
$to = "owner@example.com";
$subject = "Email from website";
$body = "A visitor has submitted a form on your website.nn".
              'Name : '.$_REQUEST['name']."nn";
              "Email Address: {$_REQUEST['email']}n".
              "Message : {$_REQUEST['message']}nn";
 
mail($to, $subject, $body, "From: formSubmitter@domain.com");
 
print "Thank you for your submission";
?>

The code is very simple and straight forward. It takes all the information sent through the HTML form and emails it to owner@example.com. In the HTML form, we had an input field with the name of message :

<textarea cols="40" rows="10" name="message"></textarea>

You can access the value of this field in PHP through the variable : $_REQUEST['message']. If you used the method post (like I did in the code above), you can also access the value of the message field through the variable $_POST['message']. However, $_GET['message'] will not contain anything as the method we used in our form was post and not get.

9Nov/080

Design Patterns – Singletons in PHP 5.x

Design Patterns (and anti-patterns) are techniques of programming. There are a lot of design patterns. It is upto the programmer to pick and choose which patterns to use based on their needs. Singleton is also a design pattern. A singleton is a type of class which can have only 1 object of its kind through the lifecycle of an application. It is very suitable for database, caching, etc. I will use a database class as an example as it is probably the most-widely used class in web development.

Why use a singleton you ask? A popular practice among PHP4's developers is to make a database object global then use that variable anything a query needs to be run. It works in small applications and even in not-so-big applications. In enterprise applications where you use hundreds (if not thousands) of variables, there is a very good chance that you database object will get mutated or overridden. You also don't want to have multiple instance of a database class (unless you are running a multi-threaded application).

A database class should be able to connect to a database, run queries, return results and close the connection to the database when it's done. Keeping that in mind, let's start writing our database class.

/**
 * Database wrapper
 */
class Database {
	private $_host;
	private $_user;
	private $_pass;
	private $_name;
	private $_conn;
	private $_err;

	/**
	 * Setting the constructor as private will make sure
	 * that the class cannot be instantiated using the
	 * "new" keyword. You can to instantiate it like this :
	 * $db = Database::getInstance();
	 * getInstance() is implemented right after the constructor
	 */
	private function __construct($host, $user, $pass, $name)
	{
		$this->_host = $host;
		$this->_user = $user;
		$this->_pass = $pass;
		$this->_name = $name;
	}

	/**
	 * This function is what makes this whole class a singleton.
	 * It will make sure only one instance of this class is available
	 */
	function getInstance($host='', $user='', $pass='', $name='')
	{
		static $obj;
		if (null == $obj) {
			$obj = new Database($host, $user, $pass, $name);
			$obj->connect();
		}
		return obj;
	}
	/**
	 * Connects to the database
	 */
	function connect()
	{
		$this->_err = null;
		if (!mysql_connect($this->_host, $this->_user, $this->_pass)) {
			$this->_err = mysql_error();
			return false;
		}
		if (!mysql_select_db($this->_name)) {
			$this->_err = mysql_error();
			return false;
		}
		return true;
	}

	function error()
	{
		return $this->_err;
	}

	function user($val=null)
	{
		if (null == $val) return $this->_user;
		$this->_user = $val;
	}
	function host($val=null)
	{
		if (null == $val) return $this->_host;
		$this->_host = $val;
	}
	function pass($val=null)
	{
		if (null == $val) return $this->_pass;
		$this->_pass = $val;
	}
	function name($val=null)
	{
		if (null == $val) return $this->_name;
		$this->_name = $val;
	}
}

So, we wrote a class called database and made its constructor private so you can't instantiate it using the "new" keyword. We also wrote a method/function for this class called getInstance() which will return a database object. getInstance() has a local static variable called $obj. It checks if this variable is null. If it's null then that means there is no object of the type "Database". So, it creates an object and assigns it to $obj. It also returns the object to the code that called it. Setting permissions of private, protected and public could not have been done in PHP 4, which frustrated a lot of OOP enthusiasts. PHP 5, however, has the capability of doing it and thus fulfilling one of OOP's main goals - encapsulation.

The first time  an object of the class Database is instantiated, it will have to pass all the variables required to make a database connection. Its subsequent calls need not do that.

// First call
$db = Database::getInstance('localhost', 'root', '', 'myDB');

function hello()
{
	// Second call
	$database = Database::getInstance();
}

Both $db and $database point to the same object. Any changes made to $database will be reflected in $db also. This eliminates the use of global variables for quite a few things (especially our database class).