Getting started with PHPUnit unit testing
July 4, 2011 Leave a comment
The follow up to my previous post. The below is the php unit test class for the string class example I wrote.
Looking beyond
July 4, 2011 Leave a comment
The follow up to my previous post. The below is the php unit test class for the string class example I wrote.
July 3, 2011 1 Comment
In getting started with PHPUnit, I didn’t have any code I felt like writing unit tests for. Mainly because I wanted to start with something very simple. I started writing some code, one thing lead to another and I ended with a simple class to represent a string. It only has a few methods but it was more than enough to provide me with quite a few test cases. The unit test for the class in another post I’m going to do soon. (PHP Unit tests for string class is here)
July 2, 2011 17 Comments
That title is quite a mouthful isn’t it? I usually do development on Ubuntu and only ever develop Windows specific programs on Windows using .NET but I’ve found the need to setup an environment to do some PHP/MySQL dev on windows (7). I’m running Windows 7 but the steps should work fine for XP and Vista too.
April 7, 2011 22 Comments
I’m working on a new project, migrating an existing site using custom code with a very monolithic design on top of MySQL.
Design goals : Implement all the same functionality using a manageable framework with a small footprint on a distributed NoSQL database.
Small footprint? I’m thinking Code Igniter (CI)… Distributed NoSQL (my favorite part)? I’m thinking Apache Cassandra!!!
First problem…issue, whatever you want to call it. CI is built with SQL DB tied in fairly tightly. How do I separate the two without hacking the CI core and allow me to have the flexibility of upgrading CI in the future? And at the same time being able to integrate Cassandra tightly enough to not make it stand out like a penguin in Africa sore thumb?
Enough with the questions, I’m very new to CI so this took me about an hour to make it happen. The idea is, CI provides a $this->db object when “database” is one of the auto loaded options. I want to still have this db instance available but providing methods to access Cassandra. I also want this to be auto loaded and available in all controllers… So how? Read more of this post
February 21, 2011 2 Comments
I’ve been working on a PHP framework for my group over the last few weeks. We were required to build almost everything from scratch so using another framework such as Codeignitor was not an option.
The URL mapper basically breaks up a URL into chunks and allows you to programatically add variables to the query string or get the value of a variable in the URL of the current page request.
Admittedly it’s not perfect and could do with improvements but it works well for our use case and we don’t have time to spend making it any better.
The first bit to this is to use .htaccess file and route all requests to index.php – Only requests that are not for a real file or directory is mapped to idnex.php, so for example if the file view.php exists then the request will go to that file. This .htaccess code is actually the original from WordPress.
# BEGIN ROUTING
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END ROUTING
The code for the PHP class, URI is as follows:
<?php
class URI {
private $uri;
private $uriParts = array();
private $data;
private $isPrettyUrl = true;
private $currentURI;
private $currentURL;
private $scheme;
private $host;
private $port;
private $user;
private $pass;
private $path;
private $query;
private $fragment;
public function __construct() {
$this->currentURI = parse_url($_SERVER["SCRIPT_URI"]);
$this->port = $_SERVER["SERVER_PORT"];
$this->host = $_SERVER["SERVER_NAME"];
$this->scheme = $this->currentURI["scheme"];
$this->getPath();
//build the current url before anything is done
$this->currentURL= $this->buildURL();
}
/**
*
* @return string The full url of the current page is returned
*/
public function getCurrentURL(){
return $this->currentURL;
}
/**
*
* @param string $varName the key to which a value must be returned
* @return string the value of the query parameter is returned e.g
* if url is path/name and @param $varName is path then "name" is returned
* returns null if the requested var does not exist
*/
public function getVar($varName) {
if (isset($this->data[$varName])) {
return $this->data[$varName];
} else {
return NULL;
}
}
/**
*
* @param string $varName the name of the key you wish to set a value to
* this can be an existing key, in which case the old value is overriden
* @param string $value
*/
public function setVar($varName, $value) {
$this->data[$varName] = $value;
}
/**
* Only call this method if you do not want to include all the existing
* varaibles/data from the current url, in which case you must
* use setVar to set the query strign parameters you need
*/
public function emptyQueryString() {
$this->data = NULL;
}
/**
*
* @return string returns the base domain without trailing slash
*/
public function getHost(){
return $this->scheme . "://" . $this->host;
}
public function buildURL() {
$base = $this->scheme . "://" . $this->host . "/";
$q = "";
foreach ($this->data as $key => $val) {
if ($this->isPrettyUrl == true) {
//if key is not empty
if(!empty($key))
$q.=$key . "/" . $val . "/";
} else {
//if empty we need a ?
if (empty($q)) {
$q.="?" . $key . "=" . $val;
} else {
$q.="&" . $key . "=" . $val;
}
}
}
return $base . $q;
}
private function getPath() {
// Get the URL path...everything after the domain name
$this->uri = $_SERVER['REQUEST_URI'];
if (preg_match('/\/index\.php\?/', $this->uri)) {
//only case where we can say fo sure that its not a pretty url
$this->isPrettyUrl = false;
$this->parseQueryString();
} else {
// IF ? is found at an position >1 then still parse
//can be found at domain.com/? or domain.com/path? or domain.com/path/?
if (strpos($this->uri, "?") >1) {
//remove the query string first i.e path/?some=value
$parts = split('\?', $this->uri);
//set new uri for parsequerystring to operate on
$this->uri = $parts[1];
$this->parseQueryString(); //parse query string and join data
//now have idx 0 = path and idx 1 = some=value
//set new uri for parse to operate on
$this->uri = $parts[0];
$this->parse();
} else {
$this->parse();
}
}
}
private function parseQueryString() {
//parse query string
$this->uriParts = parse_url($this->uri);
$parts = "";
if (isset($this->uriParts["query"])) {
//parse the query string and stick its values into data
parse_str($this->uriParts["query"], $parts);
} else {
parse_str($this->uriParts["path"], $parts);
}
//merge the query string with anything already in data
$this->data = array_merge((array) $parts, (array) $this->data);
}
/**
* if directory style url then parse parts
*/
private function parse() {
//// Split URL into array
$this->uriParts = explode('/', $this->uri);
//first element is always empty so remove it
array_shift($this->uriParts);
//domain.com/key/value is the format
//every second part is a value and the first is the key
$i = 0; //counter i, when =1 its a value when =0 its a key
//on second iteration
$key = ""; //need to store the key on the first iteration to access data array
foreach ($this->uriParts as $part) {
if ($i == 0) {
//if i==0 then its a key so set it to an empty string
$this->data[$part] = "";
$key = $part;
$i++; //only increment if i==0
} else {
//need to make first letter upper case if the key is view
if ($key == "view") {
$this->data[$key] = ucfirst($part);
} else {
$this->data[$key] = $part;
}
//lets make sure we destroy this key since the value is now assigned
unset($key);
$i = 0; //reset to get next key
}
}
}
}
?>
Example usage:
$url=new URI();
//assuming the query string has view=somevalue
print $url->getVar("view");
//change the value of view to home - override existing var
$url->setVar("view", "home");
//add a new var and assign testing
$url->setVar("test", "testing");
//build the url with any changes
print $url->buildURL();
The URL generated will be in the form
http://www.domain.com/view/home/test/testing
If the ckass determines that you’re not using fancy URLs then the generated URL will be
http://www.domain.com/?view=home&test=testing
It determines if you’re using fancy URLs by checking to see if the current URL starts off in the form http://www.domain.com/? or if index.php? is in the url which mean your URL is in the form http://www.domain.com/index.php?some=var…
It also handles a combination of fancy URLs and normal query strings but only if the query string is tacked on to the end of the URL in the form
http://www.domain.com/home/view/test/testing?query=string&page=1
In this case, it still assumes fancy URL is the format and when buildURL() is called it generates a fancy URL converting the query string into part of the fancy URL.
February 14, 2011 4 Comments
This guide should work for 0.7+ versions of Cassandra. Other versions may need tweaking here and there but the general path should be similar. Lets begin…
Install thrift dependencies
yum install automake libtool flex bison pkgconfig gcc-c++ boost-devel libevent-devel zlib-devel python-devel ruby-devel
Download thrift
wget http://mirrors.enquira.co.uk/apache/incubator/thrift/0.5.0-incubating/thrift-0.5.0.tar.gz
extract
tar –xvf thrift-0.5.0.tar.gz
cd thrift-0.5.0
./configure
make && make install
Once its all completed you should now be able to run thrift, test it by typing:
thrift
and you should get an output telling you a bunch of options are available. If not something went wrong when you were installing and you need to try and find where the error occurred and fix it.
Now lets download Cassandra’s source so that we can get the thrift file from it:
wget http://mirror.fubra.com/ftp.apache.org/cassandra/0.7.0/apache-cassandra-0.7.0-src.tar.gz
tar -xvf apache-cassandra-0.7.0-src.tar.gz
cd apache-cassandra-0.7.0-src/interface
You should see some files listed, the one we’re interested in is cassandra.thrift …
Now we can generate the thrift bindings for any of the supported languages:
#thrift –gen XYZ cassandra.thrift
Where xyz is the language you need, so for PHP it would be:
thrift –gen php cassandra.thrift
You will now have a gen-php folder in the directory, it contains the subdirectory for Cassandra and finally the php files. The files cassandra_constants.php, Cassandra.php and cassandra_types.php should have been generated.
Lets copy the generate files to our website include path for use later.
cd gen-php
tar –cvf cassandra.php.tar
#now copy or move (mv) the archive to your website’s include path
#cp cassandra.php.tar /home/username/websiteRoot/includes/thrift
You can now include these files in your PHP program. There are additional files that you need to find and include. One such file is Thrift.php, depending on the system you’re running the location may be different.
On my Centos distro, it is located in /usr/lib/php/ – along with the folders “protocol” and “transport” and a second file, “autoload.php”
If you open the Cassandra.php file from earlier, you’ll notice it is including files from “thrift_root” or similar. These files are the ones you need to copy to wherever you want you thrift root location to be. Since I only have the thrift files in /usr/lib/php I’m going to tar this folder and copy it to a location where I want to include files from. If that directory contains files not belonging to thrift then only copy Thrift.php, protocol and transport.
#create an archive of the required files
cd /usr/lib/php/
tar -cvf thrift.php.tar *
#now copy or move (mv) the archive to your website’s include path
#cp thrift.php.tar /home/username/websiteRoot/includes/thrift
We now have the Cassandra PHP bindings as well as the required PHP thrift files.
extract the files from the tar archives and put them all in the folder thrift (or whichever you want).
Cassandra.php,Cassandra_constants.php and Cassandra_types.php includes the thrift php files in the following manner:
include_once $GLOBALS['THRIFT_ROOT'].'/Thrift.php';
You need to therefore set THRIFT_ROOT in your PHP file like this:
$GLOBALS['THRIFT_ROOT'] = '/home/username/websiteRoot/includes/thrift'; //where /home/username/websiteRoot/includes/thrift is the location of Thrift.php
You’re now ready to test it all out. The example at http://wiki.apache.org/cassandra/ThriftExamples#PHP
Should work nicely. In a future tutorial, I’ll write some PHP examples using thrift.
You may also download the files I generated for 0.7 while doing this tutorial:
PHP bindings
http://www.crlog.info/wp-content/uploads/2011/02/phpBindings.tar
http://www.crlog.info/wp-content/uploads/2011/02/thrift.php_.tar
February 13, 2011 Leave a comment
Following on from my previous post on how to remove the default widgets/modules on the wordpress dashboard, today I’m going to show you how quick and simple it is to add your own custom widget/module that displays or does what ever you want it to.
The code below creates to widgets on our dashboard with the title of posts from two different categories,
specified by the cat=x parameter.
// add 10 most recent post to dashboard from category with id 10
function blogPost_widget() {
$recentPosts = new WP_Query();
$recentPosts->query('showposts=10&cat=10');
?>
<ul>
<?php
while ($recentPosts->have_posts()) : $recentPosts->the_post();
?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; ?>
</ul>
<?php
}
//adds news widget to dashboard
function blogNews_widget() {
$recentPosts = new WP_Query();
$recentPosts->query('showposts=10&cat=1');
?>
<ul>
<?php
while ($recentPosts->have_posts()) : $recentPosts->the_post();
?>
<li><a href="<?php echo the_permalink() ?>" ><?php the_title(); ?></a></li>
<?php endwhile; ?>
</ul>
<?php
}
// Create the function use in the action hook
function add_dashboard_widgets() {
//this will display titles and links to the blog posts
wp_add_dashboard_widget('blogPost_widget', 'Recent Blog Posts', 'blogPost_widget');//widget one
wp_add_dashboard_widget('blogNews_widget', 'Company news', 'blogNews_widget');//widget two
}
// Hook into the 'wp_dashboard_setup' action to register our other functions
add_action('wp_dashboard_setup', 'add_dashboard_widgets');
The above code goes into your functions.php file for a template or anywhere in your plugin file. Taken directly from the wordpress documentation, the wp_add_dashboard_widget is the magic function here,
it gives our widget an ID and a name and tells wordpress which function to invoke when creating the widget.
The parameters expected from the wordpress docs are:
<?php wp_add_dashboard_widget($widget_id, $widget_name, $callback, $control_callback ); ?>
Parameters
$widget_id
(integer) (required) an identifying slug for your widget. This will be used as its css class and its key
in the array of widgets.
Default: None
$widget_name
(string) (required) this is the name your widget will display in its heading.
Default: None
$callback
(string) (required) The name of a function you create that will display the actual contents of your widget.
Default: None
$control_callback
(string) (optional) The name of a function you create that will handle submission
of widget options forms, and will also display the form elements.
Further reading: http://codex.wordpress.org/Function_Reference/wp_add_dashboard_widget
February 12, 2011 1 Comment
It’s been over a week since I made a decent post (been extremely busy) so I thought I’d give it a go today.
One of the project’s I’ve had going on requires building a website for a local charity. I discussed it with the charity and agreed on using wordpress. It turns out however, the API for wordpress admin is very minimal and has very little documentation.
I found myself having to develop a large portion of things for the admin section so I’ve had to make do. One of the things I was asked for was to show custom widgets on the dashboard with various things and to remove the default ones…. whaaaaa? Usually wordpress users just manually remove and/or configure these widgets, however the potential users of this are going to be people who have little or no technical expertise… Below is a quick and simple way to remove all the default widgets/modules that are loaded on the dashboard.
function remove_dashboard_widgets() {
// Globalize the metaboxes array, this holds all the widgets for wp-admin
global $wp_meta_boxes;
//remove all default dashboard apps
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_right_now']);
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_recent_comments']);
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_incoming_links']);
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_plugins']);
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_quick_press']);
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_recent_drafts']);
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_primary']);
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_secondary']);
}
// Hoook into the 'wp_dashboard_setup' action to register our function
add_action('wp_dashboard_setup', 'remove_dashboard_widgets');
Put that block of code in your functions.php file, if it is a template you’re working on or include it somewhere if it is a plugin.
That’s all there is to it… In my next post I’ll show you how to add your own modules.
Further reading:
January 30, 2011 Leave a comment
This is a quick and dirty hack to limit the amount of words wordpress outputs on your homepage.
Its sometimes not ideal to have the entire post showing on the homepage when you have really long posts. 10 or 15 long posts will make the page take forever to load, especially if they all have images.
First thing to do is backup your theme’s index.php file. So go to wp-content/themes/your-theme-name/ and make a copy of index.php
just in case you mess it up and forget what the original content was…
Open the file, (the original, not the copy ) and find where it has the_content();
Replace it with:
<?php
$content = get_the_content();//apply_filters('the_content', $content);
$content = str_replace(']]>', ']]>', $content);
$con=explode(" ",$content);
$i=0;
while($i<50 && $i<count($con)){
echo $con[$i]." ";
$i++;<
}
?>
<a href="<?php the_permalink(); ?>" rel="bookmark" title="
<?php the_title_attribute(); ?>">... <br />Continue reading, <?php the_title(); ?>.</a>
Change 50 in the loop to the amount of words you want to allow. When done just save and re-upload the file.
Further reading:
codex.wordpress.org/Template_Tags/the_content