HOW TO: Install PDT Plugin In Aptana Studio

I was just trying to setup the PHP Development Tools (PDT) in Aptana Studio on my new laptop.  However, when I selected the package I received an error saying:

Cannot complete the install because one or more required items could not be found.
Software being installed: PDT Runtime Feature 2.0.0.v20090315-1850 (org.eclipse.php.feature.group 2.0.0.v20090315-1850)
Missing requirement: PDT Runtime Feature 2.0.0.v20090315-1850 (org.eclipse.php.feature.group 2.0.0.v20090315-1850) requires ‘org.eclipse.dltk.core.feature.group [1.0.0,2.0.0)’ but it could not be found

The error occurs because Aptana fails to find the Eclipse repository in its list of update sites and can’t download the required packages for the PDT plugin.  The steps below describe how to rectify the problem:

  1. In Aptana go on Window -> Preferences
  2. Select “Install/Update
  3. Select “Available Software Sites
  4. Press “Add
  5. In name enter “Eclipse Galileo”
  6. In location enter “http://download.eclipse.org/releases/galileo/”
  7. Click “OK
  8. Close the Preferences window
  9. Go on Help -> Install New Software
  10. In the “Work with” dropdown select “PDT Update Site”
  11. Select the PDT package you want to install.  This time the installer should run smoothly and allow you to install the PDT.

Note

This issue isn’t only for the PDT plugin as it also occured for me when trying to install the Android SDK on my computer.  You just need to run this fix once and you should no longer have any issues.

Results: The David Walsh SEO Challenge

Two weeks ago the original David Walsh Challenge commenced.  For those that missed it, the aim was to see who could appear higher up in Google when searching for the other persons name i.e:

Search David Walsh and see Cube Websites higher up than Chachakawooka
Search Ashraf Vali and see Chahchakawooka higher up than Cube Websites
As a bonus challenge, we were also trying to see who could appear higher up when searching for “Ashraf Walsh”.

Techniques Used

Whilst there were no set restrictions on what methods we could use, we did agree that if either of us did something really over the top, then other person would win by default.

I stuck to just writing blog posts.  I wrote 2 articles, both with the terms “Ashraf Vali”, “David Walsh” and “Chachakawooka”.  By tagging my articles with those keywords I was also able to generate extra pages with WordPress based on those tags.  Once the articles were written they were submitted to Reddit and Twitter.  Within an hour of posting they’d be indexed by Google and my ranking for that search term would be updated.

David did a lot more.  He wrote a blog article, he changed the page title and footer of all 2000+ pages of his site and submitted articles to Digg, Reddit and Twitter.  By having his entire site plastered with the term he was trying to optimise for in prominent areas (page titles count a lot for Google) he blackhat-SEO’d his site to the extreme.  It would have been fair for me to call his cheating at that point, but I opted not to just to see how Google would react to his spamming.

The Results

At this point bear in mind that the initial challenge was just to see who could get higher up first. In that case the winner was me, acheiving a higher ranking for David Walsh within 24 hours of starting.

After agreeing that I’d already won, we decided to carry on a bit longer to see what happens over a period of 2 weeks.  Now that the 2 weeks are up, here’s how things changed:

When searching for David Walsh, Cube Websites appears on page 5, whereas Chachakawooka is on page 6 (was 7 this morning).  One point to me!

When searching for Ashraf Vali, Chachakawooka and Cube Websites both appear on page 1, but unfortunately Chachakawooka does appear higher up.  One point to David.

A search for “Ashraf Walsh” returns both sites, with Chachakawooka first and then Cube Websites second.

Summary

As mentioned, I won the original challenge – me and David are both agreed on that.  However, the long term results actually led to a 2-1 win for David.  This is fully understandable when you take certain factors into account:

  1. David made the modifications to his site AFTER both my blog posts.  This led to Google thinking his content is actually fresher than mine
  2. I have David Walsh in 2 page titles, and Ashraf Vali in none.  David has Ashraf Vali in one page title and David Walsh in every page title on his site.  This means beating Cube Websites for Ashraf Vali is very easy in comparison to beating Chachakawooka for David Walsh due to the fact that Chachakawooka is optimised for David Walsh whereas Cube Websites isn’t optimised for Ashraf Vali.
  3. Davids methods were only short terms measures.  Whilst my blog posts will remain on Cube Websites for the foreseeable future, he’s already changed his page titles back although his footer message is still on every page.

Final Words

The David Walsh SEO Challenge was a fun task, and we both won in our own rights.  We’ve already planned our next challenge and I’ll let you know when it starts!

CCKW Text-To-Speech (TTS) jQuery Plugin

David Walsh (colleague and web developer) has launched his new Speech Recognition system.  It’s currently available as a jQuery plugin but he has promised that version 2 will bring a full featured API.

What can you do with it?
The TTS plugin can read out any text from your website to your visitors.  It would be a great aid in terms of accessibility, and of course you could probably think up other more fun uses of it too.  You could annoy users by reading out your terms and conditions to them or have your website tell visitors how awesome it is on every single page.

It would actually be nice to tell users the next action that’s required from them.  For example, you could read out form validation errors or after running an AJAX request you could read the success/failure message and so on.

Example

Here’s a basic example showing you how to use this plugin. First you need jQuery on your page if you haven’t got it already, and a link to the TTS plugin itself. I use Google for jQuery because it means you’re saving the bandwidth on your own server.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="http://chachakawooka.com/js/cckw_tts.js"></script>

In your webpage you need an element which is going to contain the text to convert to voice. For this example I’m using an input box but it could be any element (just make sure it has a unique id). You also need a trigger (button or link) which will start the conversion.

<input type="text" id="my-speech" />
<input type="submit" id="my-speech-submit" value="Convert text to speech" />

Finally we attach the elements above to the TTS plugin.

<script type="text/javascript">
    $(document).ready(function() {
        $('#my-speech-submit').cckwTTS({
                selector: '#my-speech'
	 });
    });
</script>

Demo
Here’s the above example code implemented for you to see what it does!

Notes

  • For this example I’ve put the JavaScript code inline but try to keep it together in the footer (I prefer loading JavaScript after everything) or in the <head> if that’s what you prefer.
  • David has said thanks for this post and has updated his own blog to use my example.
  • This plugin is still in its early stages and I’m sure David would appreciate all feedback and feature requests.  If you want to get in touch just Tweet <a href=”http://twitter.com/chachakawooka”>@chachakawooka</a> on Twitter.

Credits

The CCKW Text-To-Speech Plugin is created and developed by David Walsh at Chachakawooka.
PS: this guy’s the proper David Walsh, not the guy who develops MooTools.

HOW TO: Catch PHP Errors and Warnings

This morning I was faced with an issue with SwiftMailer where the PHP code was throwing an error message as it failed to connect with the mail server.

To solve it I first thought of using a try/catch, but obviously that wouldn’t work due to the fact that the function only throws a Warning, not an Exception.

The solution was quite straight forward…

  1. Create a custom error handler, to gracefully capture the warning and display a custom message
  2. Set the custom error handler before attempting to call the function causing the warning (in this case it was fsockopen)
  3. Reset the error handler to the default PHP one after calling the function.

Here’s an example of an error handler function you can use. I’m using Smarty for my output, but you can send your output to the users browser in any way you wish.

function errorHandler($errno,$errmsg,$errfile) {		
	   	//email yourself the error message and code
	   	$email	=	"An error {$erro} occured on page ".$_SERVER['REQUEST_URI'].", in the file {$errfile}.\r\n\r\nThe error is shown below:\r\n{$errmsg}";
	   	mail("email@domain.com","PHP Error Notification",$email);
	   	
	   	//output a friendly message for the user	
	   	$wrapper	=	new SmartyTemplate(); 
	   	$msg		=	"Thank  you for your message.  Unfortunately we have been unable to send your email, please go back and resubmit the form or call us on 0800 123 456 directly.  Sorry for any inconvenience caused";   	
	   	$wrapper->assign("content", $msg);   		
	   	$wrapper->display("display_wrapper.tpl");
		exit();		
	}

The next step is to set our new error handler before the call to the function that causes the warning. As mentioned, my issue was with fsockopen in in SwiftMailer, but the fix is the same for anything. Here’s how I did it in Swift.
find the offending function (in Swift/Transport/StreamBuffer.php)

if(!$this->_stream = fsockopen($host, $this->_params['port'], $errno, $errstr, $timeout)) {

and add set the error handler before it.

set_error_handler("errorHandler");
    if(!$this->_stream = fsockopen($host, $this->_params['port'], $errno, $errstr, $timeout)) { 

As I only want my error handler to run for that particular function, and not for every function in the entire site, I just have to make sure I remove my custom error handler after the function.
Just add this after your function:

restore_error_handler();

Which will cause PHP to revert to it’s normal error handling method once it’s gotten back your function.

Extras
My usage of error handling was very specific to a single function. Of course you can have a site wide error handler instead which gracefully handles every PHP error/warning/notice within a single function. You could just declare the function a common file and then handle each kind of error independently. The PHP website has a great example of this:

function myErrorHandler($errno, $errstr, $errfile, $errline)
{
    if (!(error_reporting() & $errno)) {
        // This error code is not included in error_reporting
        return;
    }

    switch ($errno) {
    case E_USER_ERROR:
        echo "<b>My ERROR</b> [$errno] $errstr<br />\n";
        echo "  Fatal error on line $errline in file $errfile";
        echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
        echo "Aborting...<br />\n";
        exit(1);
        break;

    case E_USER_WARNING:
        echo "<b>My WARNING</b> [$errno] $errstr<br />\n";
        break;

    case E_USER_NOTICE:
        echo "<b>My NOTICE</b> [$errno] $errstr<br />\n";
        break;

    default:
        echo "Unknown error type: [$errno] $errstr<br />\n";
        break;
    }

    /* Don't execute PHP internal error handler */
    return true;
}

It would be quite easy to tweak that function so that it emailed you a log of the error (and/or stored it in the DB) and then redirected the user to a nice looking page notifying them that there’s an error, but you’re aware of it.

The David Walsh SEO Challenge, Day 2

Yesterday me and a colleague (David Walsh) began our SEO challenge.  In case you missed it, the aim is to see who can get their website to appear higher than the other persons, when searching for our names i.e.

Search for David Walsh and get Cube Websites to appear higher than Chachakawooka
Search for Ashraf Vali and get Chachakawooka to appear higher than Cube Websites

Yesterday, I posted my original article, and within an hour my site was on page 11 when searching for “David Walsh”.  In retalliation, David resorted to some dirty tactics, including altering all his page titles to mention my name, as well as putting a link to his blog post in his footer, with the text “Ashraf Vali”.

Despite his attempts to best me, he’s still failing.  His blog post was made last Friday, yet even 5 days later it still hasn’t even been crawled by Google (compare to mine taking less than an hour!).  The modifications to his page layout haven’t been crawled yet either.

No doubt today we’ll see some more poor techniques on his part to try and convince Google to show his site above this one for my name.  Even if he does succeed, do bear in mind that unless he maintains the changes he’s made to his site (my name in all page titles, in the footer and generally spammed across his site) his ranking for my name will drop significantly as soon as he undoes his changes.

Morning Update

Since getting so quickly indexed and appearing on page 11 for David Walsh, my blog post now doesn’t seem to be showing on Google – a matter I’m still investigating.  In the meantime, David’s own home page has slipped down from page 5 to page 6!

As well as SEO’ing each others names, we’ve agreed to extend the challenge to include “Ashraf Walsh”.  After my blog post yesterday, my website appeared on page 2 on Google for that search term – so I’ve already won on that account.

Additionally, I was playing around on Google this morning, and found that my site actually appears second when searching for “Chachakawooka”, the only site beating it being chachakawooka.com itself which is understandable really.