:: Archive for the 'PHP' Category ::

ObservableTrait – Experiment with PHP 5.4

Posted on March 3rd, 2012 in PHP, Web Development by Greg

PHP 5.4 was released this week, and one of the biggest new capabilities from a language perspective is traits, called mixins in some other languages. Traits are basically a way of creating a set of reusable methods and properties and adding them to class, almost like copy paste. In a way this is like inheritance, but a class can use multiple traits to add multiple capabilities. Whereas with inheritance you say something like ‘a Dog is an Animal’, with traits you say ‘a Dog can be observed’.

To try out traits I took inspiration from JavaScript, a language that I’ve been using quite a bit recently. Client-side javascript for complex applications is very event driven and accordingly makes heavy use of event listeners – both DOM events and custom events. One approach that I’ve been impressed with is Sencha’s Observable class/mixin that allows classes to easily fire events and notify any listeners without tightly coupling the listeners and the observed.

While PHP is significantly less event driven (user input only comes at the beginning of a script), I thought that implementing a similar Observable mechanism would be a good way to try out the new feature. I’ve added the trait to my growing library of utility classes on Github. Here’s how it works:

1. A class uses the ObservableTrait and then fires events whenever an important event occurs:

<?php
require_one('gUtils/ObservableTrait.php');
Class Dog {
	use gUtils\ObservableTrait;
	public $name;
 
	public function __construct($name) {
		$this->name = $name;
	}
 
	public function bark() {
		echo "woof woof\n";
		$this->fireEvent('barked', $this);
	}
 
	public function rollOver() {
		echo '(' . $this->name . " rolls over)\n";
		$this->fireEvent('didTrick', $this, 'roll over');
	}
 
	public function shake() {
		echo '(' . $this->name . " shakes hands)\n";
		$this->fireEvent('didTrick', $this, 'shake hands');
	}
}

The calls to fireEvent include the name of the event, and any additional parameters that should be passed to any listener.

2. On instantiation of an object, listeners can be attached to the object to be notified when particular events occur:

<?php
require('Dog.php');
$fido = new Dog('Fido');
$listeners = $fido->addListeners([
	'barked' => function($dog) {
		echo 'Shhh ' . $dog->name . "\n";
	},
	'didTrick' => function($dog, $trickName){
		echo 'Good dog, ' . $dog->name . " - I love it when you {$trickName}\n";
	}
]);
$fido->bark(); // Shhh Fido
$fido->rollOver(); // Good dog, Fido - I love it when you roll over
$fido->shake(); // Good dog, Fido - I love it when you shake hands
$fido->stopEvents();
echo "stopped listening for a while\n";
 
$fido->bark();
$fido->bark();
$fido->shake();
$fido->bark();
$fido->bark();
$fido->resumeEvents();
echo "listening again\n";
$fido->bark(); // Shhh Fido
$fido->removeListener($listeners[0]);
echo "removed bark listener\n";
$fido->bark();
$fido->rollOver(); // Good dog, Fido - I love it when you roll over

And that’s about it – you can:

  • Add Events
  • Add Listeners (one at a time or multiple)
  • Remove Listeners (one at a time or multiple)
  • Stop throwing events
  • Resume throwing events
  • Remove all listeners

So take a look and let me know what you think…


InputValidator – Simple Input Validation for PHP

Posted on December 26th, 2011 in PHP, Web Development by Greg

I recently needed a library for validating form input and everything seemed either verbose or required a huge number of files and libraries to be included. Here’s what I was looking for:

  • Easy to include in projects without having to change include paths, mess with auto loaders, or include other frameworks
  • Something that minimized the amount of validation code that needed to be written, preferably with a fluent interface
  • Ability to generate error messages that can be shown to the end user
  • Ability to transform data to data types needed by the rest of the script
  • Capability to validate against arbitrary regexes
  • Capability to validate against closures or other external functions

I couldn’t find exactly what I was looking for, so I decided to write it myself. I added the result, InputValidator, to my gUtils collection of PHP classes on Github. InputValidator is a standalone script for validating user input from forms or other sources.

Everything is in a single file, making it easy to include in any (PHP 5.3+) project. Here’s some example usage:

<?
require('gUtils/InputValidator.php');
// this could be from $_POST
$data = array(
  'name' => 'Greg Neustaetter',
  'email' => 'greg@emailaddress.com',
  'website' => 'http://www.gregphoto.net',
  'favoriteNumber' => 'xyz',
  'date' => '11/11/2011'
);
 
// pass in the data to be validated
$v = new gUtils\InputValidator($data);
 
// validate each field
$v->field('name')->required()->length(3,50);
$v->field('email', 'Email Address')->required()->email();
$v->field('website')->url();
$v->field('favoriteNumber', 'Your favorite number')->intRange(0,100)->toInt();
$v->field('date')->toDateTime('m/d/Y')->after(time()); // after the current time
 
if(!$v->allValid()) {
    echo '<pre>';
    print_r($v->getErrors()); // returns an array of errors indexed by field
    echo '<pre>';
    exit();
} 
$data = $v->getValues();  // returns an array of values indexed by field
$name = $v->get('name'); // get the value of name
echo $v->escape('name'); // escape the value of name for output with htmlspecialchars

This script would print the following error array:

Array(
    'favoriteNumber' => Your favorite number must be an integer between 0 and 100
    'date' => Date cannot be before 12/24/2011
)

In addition to validation the library includes a few filters to manipulate data and cast it to formats needed by your code. Take a look at the documentation on the Github wiki for a list of the 20 validators and the 8 filters.

Let me know if you find it useful or if you have any feedback…

RecursiveFileExtensionFilteredIterator

Posted on June 9th, 2011 in PHP by Greg

RecursiveFileExtensionFilteredIterator – rolls right off the tongue, right?

Recently I had the need to find all of the files in a fairly big directory structure that were web pages – in my case, files with the .php and .html extensions. There were hundreds of directories and thousands of files to go through, so I decided to write a php script to find the files and then execute some code on the resulting files.

I abstracted out the code to find files matching a particular extension and have posted the (minimal) code on Github as RecursiveFileExtensionFilteredIterator. The 20 or so lines of code makes use of a couple of PHP’s SPL iterators including the Recursive Directory Iterator, the the Recursive Iterator Iterator, and the Filter Iterator. The result of this is a simple class that allows you to loop through a directory recursively to find only files that match a particular set of extensions, returning a SplFileInfo object for each file. Here’s a simple example that prints out all of the paths:

<?php
require('RecursiveFileExtensionFilteredIterator.php');
 
$path = '/path/to/starting/directory';
$extensions = array('php','html');
$files = new RecursiveFileExtensionFilteredIterator($path, $extensions);
 
foreach($files as $file) {
	echo $file->getPathname() . "\n";
}

that’s it – short and sweet.

PasswordHelper: PHP library for password hashing and more

Posted on January 19th, 2011 in PHP by Greg

Only two years since my last post 🙂

I was fixing up an old website I had built to improve the security and as part of that I wanted to improve the way in which passwords were stored, created, and verified for complexity. As part of this I built PasswordHelper, a small PHP library (61 lines of code) described on the overview/download/documentation/example page as follows:

———–

PasswordHelper is a lightweight BSD licensed PHP class that has a number of password related utility functions that make it easy to:

  • Securely store passwords by hashing them with the adaptive Blowfish/bcrypt algorithm with random salt values
  • Compare user submitted passwords with stored password hashes
  • Generate random passwords
  • Validate password complexity for length and matches to a configurable set of regular expressions

The library does nothing too complex – it just makes it easy to do common things to help create more secure PHP applications utilizing existing PHP functions through a simpler API. Most of the existing APIs seem a bit…cryptic (ha ha, right?) and there are so many options and algorithms from which to choose. Choosing the ‘wrong’ algorithm for password hashing can lead to big problems, like the ability for hackers to brute force hundreds of thousands of passwords from your database in an hour.

———–

Here’s a quick example of how it is used:

require('PasswordHelper.php');
$pass = new PasswordHelper();
 
// Hash a password with bcrypt and a random salt before storing it in a database
$hash = $pass->generateHash('myP@ssword');
 
// Validate the password against the stored hash on a login attempt
if($pass->compareToHash('myWrongPassword', $hash)) {
	// password matches	
} else {
	// password doesn't match
}
 
// Generate a random password
$randomPassword = $pass->generateRandomPassword();
 
// Validate the complexity of a password
if($pass->checkPasswordComplexity($password)) {
	// password meets requirements	
} else {
	// password doesn't meet requirements
}

Check it out if you need some help with passwords in your PHP application…

PHP5 Defensio Class

Posted on November 24th, 2007 in PHP by Greg

Looooong time since I’ve written anything here – about 9 months! This time around I’ve put together a simple PHP5 class for communicating with the Defensio web service. Defensio has an example PHP class, but unfortunately it is PHP4 only and it’s more fun to rewrite it, right?

For those who don’t know about Defensio, it is a web service for determining whether a comment on a blog or message in an application is spam. To use it, you must first register for an API key. Defensio is very similar to the venerable Akismet (see the article I wrote on Akismet) but they provide a couple other features such an indication of the ‘spaminess’ of an individual message. Akismet has worked out great for me (123,419 spam comments caught so far!), but I figured it would be good to try out something new as well.

The class is a PHP5 class and the public methods are reasonably well commented. The bottom of this post has a link to a test application and a download of the class/test application. So…the usage of this class is quite straightforward, as shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
require('library/Gregphoto/Defensio.php');
require('library/Gregphoto/Defensio/Adapter/Streams.php);
 
$apiKey = 'mysecretapikey';
$siteUrl = 'http://my.secret.site.url.com';
 
$defensio = new Gregphoto_Defensio($apiKey,$siteUrl);
$defensio->setHttpClient(new Gregphoto_Defensio_Adapter_Streams());
 
$params = array(
	'user-ip' => $_SERVER['REMOTE_ADDR'],
	'article-date' => '2007/11/24',
	'comment-author' => 'Big Bad Spammer',
	'comment-type' => 'comment',
	'comment-content' => 'please click links and buy viagra',
	'comment-author-email' => 'bigbadspammer@annoying.com',
	'comment-author-url' => 'http://www.annoying.com'
);
$result = $defensio->audit_comment($params);
if($result['spam'] == 'true') {
	echo "Comment is spam with a spam score of " . $result['spaminess'];
} else {
	echo "Comment is not spam";
}

A couple key points on usage:

  • Each Gregphoto_Defensio object requires an Http adapter that it will use to make Http POST requests to the Defensio web service. I originally hardcoded it to use the Zend_Http_Client from the Zend Framework, but figured this could discourage people from using it. Then I wrote up a quick adapter to use PHP’s Http Stream Wrappers, but realized that didn’t work on my Dreamhost account, so I added in an extra one for the Curl extension. In theory I should have added a Gregphoto_Defensio_Adapter_Interface class, but I was lazy and didn’t want to add in an extra file.
  • Each Gregphoto_Defensio object can be used to make many requests
  • All of the current Defensio API’s are covered by the class. These are covered by the following methods in the Gregphoto_Defensio class:
    • validate_key
    • announce_article
    • audit_comment
    • report_false_negatives
    • report_false_positives
    • get_stats
  • Each of these methods takes a single parameter, an associative array of options as defined by the Defensio API. Each API also returns an associative array of response parameters. Two static utility methods Gregphoto_Defensio::getActions (returns a list of defensio methods such as ‘validate-key’) and Gregphoto_Defensio::getActionDetails (returns a list of required parameters, optional parameters, and response parameters for a specific Defensio action) are provided in order to get the details of the input and output parameters.

I created a simple test application which can be used to test Gregphoto_Defensio and all of the APIs provided by Defensio.

Download the Gregphoto_Defensio class and the test application