Archive of articles classified as' "PHP"

Back home

new years resolutions

7/01/2009

Firstly, Happy New Year!

In 2006 I graduated, 2007 I got married, 2008 I had my first child….2009 has a lot to live up to!

To make sure it doesn’t go down the pan I thought I’d better make some resolutions, so here they are in all their glory…

exercise more

Ok lets get the obligitories out of the way

eat less

See above

blog more

Having just become a Dad, I’m finding any spare time to be a rarity. However, I need to pull my finger out and blog more often, starting with this one (if this is the latest entry in a months time, then you have my permission to punch me in the stomach)

get more involved

Even simple things like commenting on blog posts and twitter updates. I read so many of the things, but can never normally be bothered to put my 2 cents across, this needs to change, because my opinion is quite frankly, awesome :P

get motivated

With the run up to Chrimbo, I seemed to lose all motivation for work and the web, I’m sure having a baby had something to do with this as well, but I definately want to get this back in 09 and I will damnit.

frameworkerisation

Want to start developing with a framework, with Zend being preferred choice for PHP and am still musing over a javascript framework to go with, jQuery and MooTools are in pole position at the mo.

get back into css

I use very little html/css these days, with the bulk of what I do being purely php, which is how I prefer it. However, I would like to get back into css and having read Transcending CSS: The Finid Art of Web Design I think I need to get back into it before it all goes completely over my head.

become zend certified

This is like 3rd year on the trot this has been a resolution, but who knows, maybe this year will be the year. Just need to find someone who wants to pay for me to take the exam…

attend a conference

Again this one hinges on someone paying for me, because I’m a tight git. Would love to go to FOWA, PHP conference, PHPNW etc. and hope I get the chance in 09.

1 Comment

php namespace seperator

28/10/2008

For those of you who are keeping up with the latest developments of the PHP language, you will know tha they finally decided on the serperator used to seperate namespaces, and to almost everyone’s horror they went with…

\

…that’s right, a bloody backslash. I think Paul Jones summed up what we are all thinking in his i.m. transcript.

Ok, so pretty much everyone agrees, that a backslash, blows…but what could be used as an alternative, I know a few people have suggested a single dot (foo.bar()) but this will make it ambiguous withs string concatenation. The original contenders were as follow (assuming the namespace foo):

  • foo\bar()
  • foo**bar()
  • foo^^bar()
  • foo%%bar()
  • foo:>bar()
  • foo:)bar()
  • foo:::bar()

I think the triple colon would have been my shout, sure it’s an extra character, but it fits in well with what we know so far. Would love to hear other people’s opinion on what they would prefer, if their not happy with the backslash.

2 Comments

first 5 steps to maintainable code

10/09/2008

Bad, untidy, ugly, messy code is one of my pet hates. This is by no means a definitive post, but a few guidelines on how to instantly make code less ugly and more maintainable. Please don’t think that by applying these 5 steps that your code will instantly be maintainable, however it would be a good place to start!

1. indent your code

If I open up some code and its not properly indented, I have to wade through the code and indent it correctly. It honestly makes it soo much easier to read and make changes to, if everything is indented properly. Sometimes I wish PHP was like Python and absolutely required code to be indented properly.

I cannot stress this enough, indent your code!

2. name variables meaningfully (but sensibly)

Another one of my pet hates. Variable names like the following…

$mv = 'blah';

I would much rather have to spend an extra few seconds writing a longer variable name which makes sense, so in our example above, something like…

$my_variable = 'blah';

Now, this also requires some common sense. Yes longer variable names are good if it makes them more meaningful, but that doesn’t mean you should go overboard, for example…

$this_is_my_variable_name_right_here_long_and_meaningful = 'blah';

…is just taking it a bit too far.

Meaningful variable names should also be used in the database. For example TABLENAME_id is far better than simply id.

3. comment your code

There is no such thing as ‘self documenting’ code. Sure you can write some code which is really obvious what it does, but if there’s any doubt what so ever, even a smidgin…write a frickin comment.

It will take only a few seconds extra and could save the next developer hours.

There is also no such thing as over-commenting, although quality should always trump quantity.

Also worth mentioning is docblocks, these are excellent and means you can use a documentation tool such as phpDocumentor to create documentation for your code.

4. use a coding standard

Coding standards make life so much easier, especially when developing in a team. They set the development rules. Without rules, anarchy ensues, and the same goes for code. I hate to have to open some code and see something like the following where different developers have added or edited the code…

require_once 'blah.php';
include("foobar.php");

if ($foo == $bar) {
    $random_array[] = 'hello';
}

foreach ($random_array as $word)
{
    echo "hello";
}

Using a coding standard you would not get the mixture of bracket placement, the single and double quotation mash-up and you wouldn’t get the combo of require_once and include().

There are a few coding standards out there, but the one I would go for is the PEAR standard.

5. separate code and html

I’m not going to get into a spiel about MVC (I’ll save that for another post) but what you should definately have is a clear separation between your code and your html. Even if this means just having your code at the top of the page and the html at the bottom, it’s a start. However, ideally you should be putting your html is a separate file, bonus marks for using a templating engine.

1 Comment

obligatory dev tools post

9/09/2008

I’ve been blogging now for a few months (albeit quite sparsely!) and I think it’s about time I write the obligatory dev tools post. These are tools that I use day in, day out and couldn’t imagine developing without. If you have any which you would like to add, please do so in the comments below…

editor/ide

Texpad – love its flexibility and simplicity. Does everything I need, never crashes and has loads of settings.

ftp

Smart FTP – ok, so you have to pay for it, but it really is the best ftp client out there.

honourable mention

FileZilla – a nice, simple, free solution. Seems to update all the time, which is a bit annoying, but other than that a very nice alternative to smart FTP.

database management

PHPMyAdmin – Was torn between this and Navicat for the main spot, but went for this because it’s free.

honourable mention

Navicat – This has some really nice features and is a lot more enterprisey than PHPMyAdmin, but then you have to pay for it :(

browser

Firefox – at the time of writing Google Chrome has just been released and so far it looks good, however firefox is still number 1. Everything about it just feels right, and the add ons take it to a different level.

honourable mention

Google Chrome – just released, but looks by far the next best thing after firefox, and who knows, could even surpass firefox one day (Tangent: isn’t google developing a browser a bit of a conflict of interests, considering the money they plough into firefox?!)

firefox extensions

Web Developer – the mother of all firefox webdev extensions. If you’re a web developer and you don’t have this plugin, you may as well go home.

Firebug – Another plugin I couldn’t live without. The inspect function is awesome, the javascript console and debugging is incredible, again this is a must have.

HTML Validator – Validates pages as they load and has some nice features like tidying up the html.

Color Zilla – Lets you instantly get any colour from any web page with the handy colour picker.

Screengrab – Allows you to easily take a screengrab of the page, visible portion or just a selection.

YSlow – A plugin for firebug this allows you to see how fast your page is and where you could improve.

Delicious Bookmarks – Allows me to easily bookmark pages and also gives me access to my bookmarks at the click of a mouse.

Bloglines Notifier – A bit naughty this one, but when you love bloglines as much as me it makes sense.

version control

Tortoise SVN – If you’re using subversion then you need to have this gui tool (if working in windows).

regex

Regex Builder – There are loads of online ones, but I like this one for its simplicity and quickness. Shame it requires the .net framework though.

misc

Stickies – Very useful when having to log time. These handy sticky notes sit on your desktop so you can easily record what your working on and between what hours.

Ok, so that’s my list. If you would like to add to it, or feel there’s a tool out there which you can’t believe I don’t use then please point me toward it.

2 Comments

useful function of the day

12/08/2008

An equivalent javascript function to php’s urlencode() is escape()

No Comments

truncate text snippet

17/07/2008

Just a quick snippet to truncate a string to a certain length (in this case 200 chars) and append … at the end of it.

<?=(strlen($my_string > 200) ? substr($my_string,0,200).'...' : $my_string?>

If you are using smarty you can use the somewhat simpler truncate modifier

{$my_string|truncate:200}
2 Comments

the joys of .net, soap and php

17/06/2008

The first letter in the acronymn SOAP is supposed to stand for Simple. Although that has been altered in the 1.2 version of the protocol, I cannot help but smile at the irony. My first encounter with using SOAP was using php to interface with a .NET web service. I can certainly say that this was anything but simple.

Using PHP 5′s Soap extension it appeared really easy to call the remote methods from the web service and in actual fact, it was. What I found really time consuming and frustrating was the untold .NET quirks which you had to account for and program around. Any documentation out there was poor and if not for the comments on the php.net documentation I would still be struggling with it.

First, a few rules you must stick to:

  • You can only pass objects to the remote methods
  • Parameters must be passed as SoapVar objects

The other thing which took me a while to work out was how to pass the username and password into the header, again the documentation on this was poor. What you need to do is set a SoapHeader object which you then need to set in the client using the __setSoapHeaders method.

Finally, I have put together an example which will hopefully help you get started when you need to access a .net web service through php. The headers stuff is only needed if the web service you are trying to access requires it.

// Specify your wsdl file.
$wsdl = WSDL_URL;

// Create our parameter class, this is needed for .NET compatibilty
class Params {
}

// Create our auth header class, this is needed for .NET compatibility
class AuthHeader{
}

// Instantiate our auth header class and set the username and password
$a = new AuthHeader;
$a->Username = USERNAME;
$a->Password = PASSWORD;        

/* Create our soap headers, this takes the namespace of the web service
    The name of the remote method which is used for authorisation and finally
    the object with the login details */
$headers = new SoapHeader(NAMESPACE, REMOTE_AUTH_METHOD, $a);

// Call try calling the soap client
try {
    $client = new SoapClient($wsdl, array('classmap'=>array('REMOTE_METHOD'=>'Params'),'trace'=>1,'exceptions'=>0));

    // Set the soap headers
    $client->__setSoapHeaders($headers);

   // Build our paramaters for our remote method call
    $p = new Params;

    $p->PARAM1 = new SOAPVar(VALUE, null);
    $p->PARAM2 = new SOAPVar(VALUE, null);

    // Try to call the remote method
    try {

        $result = $client->REMOTE_METHOD($p);

    } catch (SoapFault $exception) {

        echo 'Error: <br />';
        echo $exception->getMessage();
    }

} catch (SoapFault $exception) {
	echo 'Error: <br />';
	echo $exception->getMessage();
}
2 Comments

commidea payment class

9/06/2008

Update: I have a new version of this which uses the SOAP method and integrates 3D secure as well. If you are interested in this, leave a comment and I can send you a copy, if enough people are interested I’ll post it. Cheers.

Having recently integrated the commidea payment gateway into an online shop, I thought I would share the class in which I created to do this. I searched high and wide to find a class that was already out there but could not find one. So hopefully this will prove useful to some of you.

There are a few ways you can use the commidea gateway, you can use SOAP for example. This example uses Curl, so make sure that you have Curl installed on your server.

Please let me know if you find this class useful.

/* Class to deal with commidea payments

        Developed by Ian Jenkins - www.Jenkins-Web.co.uk

 	Usage:

	// Create a new object passing card details into the constructor.  This should be an array of details such as type, number etc.
	$payment_obj = new CommideaPayment($card_details);							

	// Validate the card
	$error = $payment_obj->validateCard();				

	// Ok, if we have no errors we can move on
	if (empty($error)) {		

		// Set the order id/reference
		$payment_obj->setOrderID($order_id);

		// Set the total for the order
		$payment_obj->setOrderTotal($order_total);

		// Make the payment
		$payment_response = $payment_obj->makePayment();					

		// The response will be either true or false, depending on whether the payment was successful or not
		if ($payment_response) {

			// Payment was successful, do what you need to do, probably update order and send the user to a success page.

			// To get the transaction id you can call this method.
			$payment_obj->getTransactionID()

			// If you are going to redirect the user to a success message, you will probably want something like:
			header("Location: /success/");
			exit;

		} else {

			// Payment was unsuccessful, do what you need to do, probably display an error message and give the user
			// a chance to enter alternative payment details.

			$error = 'Sorry, your payment was unsuccessful, please try alternative payment details.';
		}
*/

class CommideaPayment {

	// Define our commidea params
        // Change if not in testing mode
	private $post_url = 'https://testing.commidea.com';
        // Your account id
	private $account_id = 'XXXXXXXXX';
        // Your account number
	private $account_number = 'XXX';
        // Your GUI ID
        private $gui_id = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX';
        // Change to N to take payment as well as authorise
        private $auth_only = 'Y';

	public $card = array();
	public $order_id;
	public $order_total;

	public $transaction_id;

	/* Take in an array of card details, should have the following elements (elements with * are required):
		$card['type']*
		$card['number']*
		$card['security_code']*
		$card['expiry_month']*
		$card['expiry_year']*
		$card['start_month']
		$card['start_year']
		$card['issue']
	*/
	function __construct($card) {

		if (is_array($card)) {
			$this->card = $card;
		} else {
			die('Card details must be an array');
		}

	}

	// Some setters
	function setOrderID($order_id) {
		$this->order_id = $order_id;
	}

	function setOrderTotal($order_total) {
		$this->order_total = $order_total;
	}

	// Some getters
	function getTransactionID() {

		return $this->transaction_id;
	}

	function getCardType() {			

		return $this->card['type'];
	}

	function getCardRef() {

		// Return the card number with stars for all the digits except the last 4.
		return str_pad('', strlen($this->card['number'])-4, 'X').''.substr($this->card['number'], -4);

	}

	/* Validate our card.
		- Ensure card number is long enough and matches the Luhn formula
		- Ensure they have not entered an expired card!
		- Ensure the security code is only 3 digits
	*/
	function validateCard() {

		$err = array();

		// Required fields array fieldname=>label
		$required_fields = array('type'=>'Credit card type',
									'number'=>'Credit card number',
									'security_code'=>'Security code',
									'expiry_month'=>'Expiry month',
									'expiry_year'=>'Expiry year');

		foreach ($required_fields as $field=>$label) {

			// Have they filled in a credit card type?
			if (empty($this->card[$field])) {

				$error[] = '<strong>'.$label.'</strong> is missing.';
			}

		}

		/* Lets check the credit card number now
			- before we do anything, strip whitespace from the card number */
		$card_number = str_replace(' ','',$this->card['number']);

		if (!empty($card_number) && $card_number < 13) {

			$error[] = '<strong>Cred card number</strong> is not long enough.';
		}

		/* Ensure the card number is valid using the Luhn formula */
		if (!empty($card_number)) {

			$is_valid = $this->_validateCreditCardNumber($card_number);

			if (!$is_valid) {
				$error[] = '<strong>Invalid card number</strong>, check your card.';
			}
		}		

		// Ensure card has not expired!
		if (($this->card['expiry_month'] < date(m)) && ($this->card['expiry_year'] == date(Y))) {

			$error[] = 'Credit card has <strong>expired</strong>';
		}				

		// Ensure security code is numeric and only 3 digits
		if ($this->card['securitycode']) {

			if (!is_numeric($this->card['securitycode'])) {

				$error[] = '<strong>Security code</strong> is invalid.';
			}

			if (strlen($this->card['securitycode']) != 3) {

				$error[] = '<strong>Security code</strong> is invalid.';
			}
		}

		// If a maestro card is used then make sure they have also provided an issue number
		if ($this->card['type'] == 'Maestro' && empty($this->card['issue'])) {

			$error[] = '<strong>Issue No.</strong> is missing.';
		}	

		return $error;

	}

	/* Function to attempt to make a payment.  Will post the data to commidea using curl and see what response we get */
	function makePayment() {

		// First lets get our data
		$data = $this->_buildData();

		// Get our response from commidea
		$response = $this->_postData('cctransaction', '/cctransaction.asmx/CardTxn', 'CommideaTransaction', $data['cctransaction']['#data']);				

		// Assume payment was rejected unless told otherwise
		$result = "REJECTED";

		if (!isset($response["xml_array"]["TransactionResult"]) ) {

			die('Curl error');
		} else {

			$result = $response["xml_array"]["TransactionResult"];
		}				

		// Approved - Success!
		if ($result == 'ACCEPTED')  {			

			// Capture Transaction ID
			$transaction_id = $response["xml_array"]["TransactionID"];

			$this->transaction_id = $transaction_id;

			return true;

		} elseif ($result == 'REJECTED') {

			// Payment was rejected :( 

			// Capture Transaction ID
			$transaction_id = $response["xml_array"]["TransactionID"];

			$this->transaction_id = $transaction_id;

			return false;

		} elseif ($result == '0') {

			// Something went wrong...

			// Capture Transaction ID
			$transaction_id = $response["xml_array"]["TransactionID"];

			$this->transaction_id = $transaction_id;

			return false;
		}		

	}

	// Function to build the data we require for the commidea transaction
	private function _buildData() {

		$data = array(
			'payerauth' => array(
				'#page' => "/payerauth.asmx/CardCheck",
				'#xmlroot' => 'CommideaPayerAuthCheck',
			),
			'cctransaction' => array(
				'#page' => "/cctransaction.asmx/CardTxn",
				'#xmlroot' => 'CommideaTransaction',
				'#data' => array(
					'Merchant' => array(
						'GUID' => $this->gui_id,
						'MerchantData' => $this->order_id,
					),
					'TRecord' => array(
						'AccountID' => $this->account_id,
						'AccountNumber' => $this->account_number,
						'TxnType' => '01',
						'Pan' => $this->card['number'],
						'ExpiryDate' => ($this->card['expiry_month']).(substr($this->card['expiry_year'],2,4)),
						'TxnValue' => $this->order_total,
						'CSC' => ($this->card['security_code']),
						//'AVS' => '',
						'Issue' => ($this->card['issue']),
						'StartDate' => ($this->card['start_month']).(substr($this->card['start_year'],2,4)),
						'Reference' => $this->order_id,
						'CNP' => 'Y',
						'ECom' => 'Y',
						'AuthOnly' => $this->auth_only
					),
				),
			),
			'confirmtxn' => array(
				'#page' => "/cctransaction.asmx/ConfirmTransaction",
				'#xmlroot' => 'CommideaConfirmation',
			),
			'serverstatus' => array(
				'#page' => "/serverstatus.asmx/GetServerStatus",
				'#xmlroot' => NULL,
			),
		);		

		return $data;
	}

	/* Using curl, lets post the data to commidea and return the response */
	private function _postData($service, $page, $xmlRoot = NULL, $xml = array()) {

		//Validate the service
	  	if (!in_array($service, array("payerauth", "cctransaction", "confirmtxn", "serverstatus"))) {

	  		die("Invalid Service");
	  	}

	  	//If there IS an XML root, grab the XML using the recursive function below and create an XML output string
	  	if ($xmlRoot && is_array($xml)) {

			$output  = '<?xml version="1.0" ?>' . "\n";
			$output .= '<'.$xmlRoot.' xmlns="https://www.commidea.webservices.com">' . "\n";
			$output .= $this->_getXML($xml);
			$output .= '</'.$xmlRoot.'>';

	  	} else {

			//Otherwise, output is blank.
			$output = '';
	  	}	  		  	

	  	//Set the headers as an array
	  	$header[] = "Host: testing.commidea.com";
	  	$header[] = "Content-type: application/x-www-form-urlencoded";

	  	//If the output is not empty, set the xmlStream
	  	if (empty($output)) {

			$header[] = "Content-length: 0 \r\n";

	  	} else {

			$header[] = "Content-length: ".strlen('xmlStream=' . $output) . "\r\n";
			$header[] = "xmlStream=" . $output;
	  	}	  			  		  	

	  	// Create a curl object
	  	$ch = curl_init();
	  	curl_setopt($ch, CURLOPT_URL, $this->post_url.$page);
	  	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	  	curl_setopt($ch, CURLOPT_TIMEOUT, 10);
	  	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
	  	curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
	  	curl_setopt($ch, CURLOPT_HTTPHEADER, $header);	  		  

	  	// Execute the curl and save the result
	  	$returned = curl_exec($ch);	  

	  	// Lets tidy up the xml a bit
	  	if (curl_errno($ch) == 0) {

			$p = xml_parser_create();

			xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
			xml_parse_into_struct($p, $returned, $returnedxml, $returnedxmlindex);
			xml_parser_free($p);

			$temp = array();

			foreach ($returnedxml as $key => $value) {

			  if ($value['type'] == 'complete') {

				$temp[$value['tag']] = (isset($value['value']) ? $value['value'] : '');
			  }

			}

			$returnedxml = $temp;

			unset($temp);

	  	} else {

			$returnedxml = array();
	  	}		  		  	

	  	$res = array('curl_error' => curl_errno($ch), 'xml_array' => $returnedxml);	  		  	

	  	return $res;
	}	

	// Validate credit cards using the LUHN formula
	private function _validateCreditCardNumber($cardnumber) {

		/* Credit card LUHN checker - coded '05 shaman - www.planzero.org        *
		 * This code has been released into the public domain, however please    *
		 * give credit to the original author where possible.                    */

		$cardnumber=preg_replace("/\D|\s/", "", $cardnumber);  # strip any non-digits
		$cardlength=strlen($cardnumber);
		$parity=$cardlength % 2;
		$sum=0;

		for ($i=0; $i<$cardlength; $i++) {

			$digit=$cardnumber[$i];
			if ($i%2==$parity) $digit=$digit*2;
			if ($digit>9) $digit=$digit-9;
			$sum=$sum+$digit;
		}

		$valid = ($sum%10==0);

		return $valid;
	}

	/* Recursive XML creator.
		- Pass an array into $data. It loops around each element in the array. If $value is not an array,
		- It prints it out using the $key as the element tag.
		- If $value IS an array, the function calls itself with the $value array as the new tree with an incremented depth.
		- The $depth is used to tab indenting to make the XML human friendly. Option in the future to add an arg to make
			code computer friendly by making it all one line.
		- Returns the xml as a string.
	*/
	private function _getXML($data = array(), $depth = 1) {

		$output = "";

	  	foreach ($data as $key => $value) {

			if (is_array($value)) {

			  $output .= str_repeat("  ", $depth) . "<$key>\n";
			  $output .= $this->_getXML($value, $depth+1);
			  $output .= str_repeat("  ", $depth) . "</$key>\n";

			} elseif (empty($value)) {

			  $output .= str_repeat("  ", $depth) . "<$key />\n";

			} else {

				$output .= str_repeat("  ", $depth) . "<$key>$value</$key>\n";

			}
	  	}

	  	return $output;
	}	

}
2 Comments

obscure credit card numbers

5/06/2008

Handy little function to have when developing a shop. If you wish to store or display obscured credit card numbers. It will replace all number in the credit card number with X’s apart from the last 4.

	function getObscuredCreditCardNumber($card_number) {

		// Return the card number with X's for all the digits except the last 4.
		return str_pad('', strlen($card_number)-4, 'X').''.substr($card_number, -4);

	}
No Comments