Needed to use this recently to create a specificity parameter for an API at work, it gives you a key/value array from an ISO date string regardless of what is actually set in the string (e.g. if you give 2011-06-07 04 you’ll get an array back as array(‘year’=>2011, ‘month’ => 6, ‘day’ => 7, ‘hour’ => 4). If you enter 2011-06-07 04:43 you’ll get: array(‘year’=>2011, ‘month’ => 6, ‘day’ => 7, ‘hour’ => 4, ‘minute’ => 43), works from just a year all the way to seconds.
/**
* Gets the parts of a date that are set in an ISO date string.
*
* @param string $date date/time to use.
*
* @return array
*/
public static function getDateParts($date)
{
$matches = array();
preg_match(
'/(
(
(
(
(
(?<year>\d{4})
(-(?<month>\d{2}))?
)
(-(?<day>\d{2}))?
)
(\s?(?<hour>\d{2}))?
)
(:(?<minute>\d{2}))?
)
(:(?<second>\d{2}))?
)/x',
$date,
$matches
);
$date = array_map('intval', array_intersect_key($matches, array_flip(array('year', 'month', 'day', 'hour', 'minute', 'second'))));
return $date;
}
This weekend I’ve finished off my first public PHP extension using the (god awful) Zend PHP macro’s, function calls etc. There were 3 reasons for me doing this:
1) See how difficult it was
2) Create a true library for PHP projects to reduce code repetition across projects.
3) Add some speed to projects that crunch a lot of data in PHP.
The extension I’ve released adds the following functions:
/**
* Given a multi line input, removes empty lines and whitespace at the ^ and $ of each line.
* Remove duplicate lines by setting the second param to true.
* Naturally case insensitive sort by setting the third param to true.
*
* @param string $string string to trim.
* @param boolean $unique strip duplicate lines [default: false]
* @param boolean $sort sort returned lines [default: false]
*
* @return string
*/
function wadew_multiline_trim($string, $unique = false, $sort = false){}
/**
* Converts catchable errors to ErrorException objects.
*
* @return void
*/
function wadew_register_error_exception_handler(){}
/**
* Checks all elements of an array to ensure they're all of the required type.
*
* @param array $elements array of objects to check
* @param string $class name of class to match against.
*
* @return boolean
*/
function wadew_array_instanceof(array $elements, $class){}
/**
* Converts a string to its binary MD5 equivalent.
* Same output as md5("string", true) - just faster!
*
* @param string $string string to convert to MD5
*
* @return string
*/
function wadew_md5bin($string){}
/**
* Returns an array of strings by casting to string or calling magic __toString()
*
* @param array $elements elements to convert
*
* @return array
*/
function wadew_array_tostring(array $elements){}
You can get it from https://github.com/wadewomersley/wadew_php_extending
We needed a CouchDB plugin in the office for some of our servers so I wrote one earlier and added it to the Plugin Store over at ServerDensity.
You can download it at http://plugins.serverdensity.com/couchdb/
It’s a straight forward plugin that exposes all your databases statistics to SD for monitoring allowing you to fully customise your graphs/alerts.
In my leedsphp talk last week I mentioned making a developer (and consumers) life easier by automatically implementing the allow methods functionality that your API may expose (e.g. you call PUT on a URL that only allows GET or POST). I did have an example slide there showing how to implement but I thought I’d posted a bare bones controller here that shows how it works.
abstract class ApiController extends Zend_Rest_Controller
{
/**
* Default head action.
*
* @internal
* @return void
*/
public function headAction()
{
ob_start();
$this->getAction();
ob_get_clean();
}
/**
* Default get action.
*
* @internal
* @return void
*/
public function getAction()
{
$this->_showAllowedMethods();
}
/**
* Default post action.
*
* @internal
* @return void
*/
public function postAction()
{
$this->_showAllowedMethods();
}
/**
* Default put action.
*
* @internal
* @return void
*/
public function putAction()
{
$this->_showAllowedMethods();
}
/**
* Default delete action.
*
* @internal
* @return void
*/
public function deleteAction()
{
$this->_showAllowedMethods();
}
/**
* Allowed methods output.
*
* @internal
* @return void
*/
private function _showAllowedMethods()
{
$methods = $this->implementedMethods();
$methods = implode(',', $methods);
$methods = strtoupper($methods);
$this->_response->setHeader('Allow', $methods);
$this->_forward('method-not-allowed', 'error', 'default'); # I have a methodNotAllowedAction on my ErrorController
# just for clarity - it does nothing other than headers
}
/**
* Direct call to get implemented methods
*
* @internal
* @return array
*/
public function implementedMethods()
{
if(!isset($this->_actionController))
return array();
$class = get_class($this->_actionController);
$oReflector = new ReflectionClass($class);
$methods = $oReflector->getMethods(ReflectionMethod::IS_PUBLIC);
$implementedMethods = array();
foreach($methods as $i => $method) /* @var $method ReflectionMethod */
{
if($method->getDeclaringClass()->getName() == $class)
$implementedMethods[] = str_replace('Action', '', $method->getName());
}
return array_intersect($implementedMethods, array('get', 'put', 'post', 'delete', 'head', 'options', 'trace'));
}
}
If you extend this controller for all your actions, you’ll get automated Allow headers every time someone calls a URL that does not implement their request type.
As I said in my talk, be sure to use an op-code cache so reflection doesn’t become your bottleneck!
Also I should mention, this code lives in my ApiController and not in an action helper or similar due to Zend Framework’s performance hit as a result of using magic methods.
Finally got around to uploading my slides (sorry for the delay!) for my talk at leedsphp on Monday 18th. They are now available online at http://www.slideshare.net/wadewomersley/building-a-horizontally-scalable-api-in-php
We use beanstalkd at work for our job queue’s due to its very low memory footprint and speed. However it was missing a few features we needed so I decided to fork it on github and start working on it and I’m pleased to announce it’s now available to download. You can grab it at https://github.com/wadewomersley/beanstalkd-ww.
* Added the much needed clear-tube function - removes all but reserved jobs, yes, even buried!
* Fixed bug in log load where group reload was attempted while not supported.
* Added removal of group reference from job on group delete
* Fixed add_job_to_group and a bug in put. Also made put group optional
* Reduced some unnecessary code from do_stats
* Optimised do_stats to only recall the fmt function if need be
* Adding job groups either during the put, using group-create. Also added group-delete to remove a group (does not delete the jobs) and group-stats allowing you to view the status of a group of jobs.
I realised it would be really useful to have a Server Density plugin that can query HAProxy and report a few stats back about it. So I wrote one! haproxy.py plugin for Server Density.
RESTClient is a great little CLI and GUI tool for testing your REST API. I recently pushed a new API up in the office and it runs over SSL. I tried to test it in the RESTClient and got a PeerNotVerified error from Java. First thing I did was go to the SSL tab in RestClient presuming I could tell it to just trust the API…apparently not.
So after a bit of web scouring about how to get Java to trust your site I came across instructions and thought I’d re-post here simplified for anyone who needs to query HTTPS from RESTClient.
These instructions are based on Windows 64-bit and Java being installed into C:\Program Files (x86)\Java. So you may have to change a few paths but the core things are the same.

Navigate to the website in your browser, click the SSL icon in the address bar and click Certificate Information or Details etc.
In the window that pops up, go to the Details tab then click the “Copy to File” button. Click Next until you get to the request for a Filename. Click Browse and navigate to “C:\Program Files (x86)\Java\jre6\lib\security”. Enter the filename to save the certificate as (I suggest the domain name with .cer ending). Finally click Next and Finish.
Now open up a command prompt (if you’ve got Windows security then be sure to run as administrator [right click the shortcut to the command prompt and the option is there]) and enter the following:
cd "C:\Program Files (x86)\Java\jre6"
bin\keytool.exe -noprompt -import -keystore lib\security\cacerts
-alias (put_domain_name_here)
-file lib\security\(name_of_certificate_you_saved_above).cer
The second command should all be on one line. You’ll get asked for a password, if you’ve never touched any Java passwords on your machine before, it’ll probably be the certificate store default which is either changeit or changeme.
That’s it! You should now be able to query your service using HTTPS without any errors.
Just had a need to reset the mysql root login password for a server, did a bit of Googling and found out this is how you do it (I work on Ubuntu so you may have to tinker with the lines slightly depending on your distribution):
- Stop the current MySQL instance from running:
/etc/init.d/mysql stop
- Run mysql with –skip-grant-tables
/usr/bin/mysqld_safe –basedir=/usr –datadir=/var/lib/mysql –user=mysql –pid-file=/var/run/mysqld/mysqld.pid –socket=/var/run/mysqld/mysqld.sock –port=3306 –skip-grant-tables &
- Log into mysql, straight into the mysql database
mysql -u root mysql
- Reset the root password.
UPDATE user SET Password=PASSWORD(‘newrootpassword’) WHERE User=’root’;
- Flush privileges
flush privileges;
- Shut down the new running mysql.
/etc/init.d/mysql stop
- Start up mysql as usual.
/etc/init.d/mysql start
Et voila, you now have a new root password without needing to know the old one!
Good start: don’t use it unless you need to, there’s plenty of alternatives, e.g. DOMXML, str_replace, etc. Also PHP5+ has lots of filters for email validation and URL validation etc, function calls you can make rather than complex regular expressions. Regular expressions can slow down quickly due to back tracking, pattern complexity and long strings.
Then the talk has become abstract, each point is prefixed with an odd statement such as “Only elephants remember everything” and “Not all matches are made in heaven” – people are getting it, but everything needs explaining before they get it!
One very good point I have seen ignored many times is “try not to be greedy.” For example /<(.+)>/ in the string <a href=”">fdsfsd</a> will match the entire thing. To make it ungreedy, either use /<(.+?)>/ or /<([^>]+)/ . Greedy matches can be 20+ times slower.