Getting started with PHPUnit unit testing


The follow up to my previous post. The below is the php unit test class for the string class example I wrote.

Read more of this post

Creating a String class to represent and manipulate strings in PHP


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)

Read more of this post

Installing Xampp and adding/updating PHPUnit and PHPDocumenter and configuring Netbeans 7 to use them on Windows


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.

Read more of this post

Apache Cassandra + PHPcassa + Code Igniter = large scale PHP app in 5 minutes


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

Creating a PHP URL mapper to parse fancy URLs and query strings


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&#8230;

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.

Install thrift and build PHP (and other language) bindings for Cassandra


Install thrift and build PHP bindings for Cassandra

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

Thirft files

http://www.crlog.info/wp-content/uploads/2011/02/thrift.php_.tar

Create custom widgets for the wordpress dashboard


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

Remove the default dashboard widgets from WordPress programatically


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:

http://codex.wordpress.org/Dashboard_Widgets_API

Limit wordpress post content out put automatically


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(']]>', ']]&gt;', $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

Follow

Get every new post delivered to your Inbox.

Join 351 other followers

%d bloggers like this: