Distributed work with Gearman

Permanent Link: Distributed work with Gearman 16. November 2011 Comment No Comment

Gearman is an easy-to-use message queue system with binaries for many programming languages. I gave a 1hr session about Gearman at this years International PHP Conference in Mainz, you can watch the slides here:

If you have any questions regarding Gearman feel free to ask in the comments. I hope the slides clear up most of it.

Ext JS: Nonblocking Notifications (Steam-style)

Permanent Link: Ext JS: Nonblocking Notifications (Steam-style) 17. November 2010 Comment Comments (4)

If you want to notify the user about something in Ext.JS, you do only have the MessageBox (at least I don't know any other possibility). The only disadvantage of MessageBox is that it's in front of any other element and usually has to be clicked away manually. Since we wanted to notify our users of things without them having to click away the notification and without it blocking the rest of the application, I wrote a Notification Extension which allows you to easily create Notifications on the bottom right of the browser window. The notifications look like this:

A single notification in application context

To be able to create those notifications, you need to add some CSS first:

.ux-chip-notification {
position: absolute;
right: 10px;
bottom: 10px;
background: #CEDFF5;
z-index: 1001;
border: 1px solid #99BBE8;
}

Second you need to add 2 JavaScript files for the 2 components Ext.ux.Chip.Notification and Ext.ux.Chip.NotificationMgr. The first component is the Notification itself, the NotificationMgr manages all your notifications, so that your notifications are displayed above each other in case you create more than one notification (see image later on):

Notification.js (Ext.ux.Chip.Notification)
NotificatioMgr.js (Ext.ux.Chip.NotificationMgr)

Once you have added those 3, you can simply create a notification with the following code:

new Ext.ux.Chip.Notification({
title: 'Something changed',
text: 'This notification is to inform you that something has changed. I will autoclose in 10 seconds.',
autoClose: 10000
});

The parameter autoClose is optional and it defines the time in milliseconds after which the notification is closed automatically. If you leave out the autoClose, the notification has to be closed manually by clicking on it. Right now the notification looks like this:

A single notification with autoClose

The second example has no autoClose, meaning the notification has to be closed manually. Additionally it has an icon:

new Ext.ux.Chip.Notification({
title: 'Something different changed',
icon: 'images/award_star_gold_2.png',
text: 'This notification is to inform you that something different has changed. ' +
'I will not autoclose, but I have an icon! If you click me I will close.'
});

The icon is always shown on the right side of the notification title:

A single notification without autoClose, with icon

Last, if for some reason you want to change the behaviour, when the user clicks the notification (remember: by default the notification is closed when clicking it), you can do it by simply overriding the handler:

new Ext.ux.Chip.Notification({
title: 'Unclosable notification',
icon: 'images/award_star_gold_2.png',
text: 'If you click me, I will not close, instead my text will change',
handler: function() {
this.setText('See? My text has changed!');
}
});

If you have created all 3 notifications at the same time, the notifications now look like this:

3 notifications

If you close one of these notifications (or when they are auto-closed) the notifications above it will be automatically re-placed, so that there are no holes between the notifications. This is managed by the NotificationMgr.

Developer's shame day: Dear god

Permanent Link: Developer's shame day: Dear god 3. November 2010 Comment One Comment

Since today is Developer's shame day, I dug deep in my old code and found some really terrifying stuff. Both code examples are several years old.

The first example needs no further explanation:

case "submit_add":

$some=0;

$tempo_add = file("users.gspb");
while (list($key, $value) = each($tempo_add)) {
$tempo_add[$key] = eregi_replace("\n", "", $value);
$tempo_add2 = explode("<~>", $tempo_add[$key]);
$user[$key] = $tempo_add2[1];
}

while(list($key2, $value2) = each($user)) {
if ($feld[0] == $user[$key2]) { echo "Fehler
Der Username $user[$key2] ist bereits belegt. Bitte wählen sie einen anderen Usernamen.
[Zurück]"; $some=1; break; }
}

if ($some!=1) {
if (empty($feld[0])) { echo "Fehler
Das Feld Username ist leer.
[Zurück]"; }
elseif (empty($feld[1])) { echo "Fehler
Das Feld Passwort ist leer.
[Zurück]"; }
elseif (empty($feld[2])) { echo "Fehler
Das Feld Passwort (Wdh.) ist leer.
[Zurück]"; }
elseif (empty($feld[3])) { echo "Fehler
Das Feld Nickname (im GSPB) ist leer.
[Zurück]"; }
elseif (empty($feld[8])) { echo "Fehler
Das Feld E-Mail Adresse ist leer.
[Zurück]"; }
elseif (empty($feld[4])) { echo "Fehler
Das Feld Realname ist leer.
[Zurück]"; }
elseif (empty($feld[5])) { echo "Fehler
Das Feld Alter ist leer.
[Zurück]"; }
elseif (empty($feld[7])) { echo "Fehler
Das Feld Woher stammt dein Nickname? ist leer.
[Zurück]"; }

elseif (preg_match("/<~>/", $feld[0])) { echo "Fehler
Die Zeichenkombination <~> ist unzulässig.
[Zurück]"; }
elseif (preg_match("/<~>/", $feld[1])) { echo "Fehler
Die Zeichenkombination <~> ist unzulässig.
[Zurück]"; }
elseif (preg_match("/<~>/", $feld[2])) { echo "Fehler
Die Zeichenkombination <~> ist unzulässig.
[Zurück]"; }
elseif (preg_match("/<~>/", $feld[3])) { echo "Fehler
Die Zeichenkombination <~> ist unzulässig.
[Zurück]"; }
elseif (preg_match("/<~>/", $feld[4])) { echo "Fehler
Die Zeichenkombination <~> ist unzulässig.
[Zurück]"; }
elseif (preg_match("/<~>/", $feld[5])) { echo "Fehler
Die Zeichenkombination <~> ist unzulässig.
[Zurück]"; }
elseif (preg_match("/<~>/", $feld[6])) { echo "Fehler
Die Zeichenkombination <~> ist unzulässig.
[Zurück]"; }
elseif (preg_match("/<~>/", $feld[7])) { echo "Fehler
Die Zeichenkombination <~> ist unzulässig.
[Zurück]"; }
elseif (preg_match("/<~>/", $feld[8])) { echo "Fehler
Die Zeichenkombination <~> ist unzulässig.
[Zurück]"; }

elseif ($feld[1] != $feld[2]) { echo "Die Passworteingaben stimmen nicht überein!
[Zurück]"; }

else {

$feld[7] = eregi_replace("\n", "
", $feld[7]);

$feld[0] = stripslashes($feld[0]);
$feld[1] = stripslashes($feld[1]);
$feld[2] = stripslashes($feld[2]);
$feld[3] = stripslashes($feld[3]);
$feld[4] = stripslashes($feld[4]);
$feld[5] = stripslashes($feld[5]);
$feld[6] = stripslashes($feld[6]);
$feld[7] = stripslashes($feld[7]);
$feld[8] = stripslashes($feld[8]);

unset($feld[2]);


$temp['a']=implode("<~>", $feld);

$zeilen = file("users.gspb");
while (list($key, $value) = each($zeilen)) {
$temp[$key] = eregi_replace("\n", "", $value);
}


$output=implode("\n", $temp);

$file = fopen("users.gspb", "w");
fputs ($file, $output);
fclose($file);

echo "Sie wurden erfolgreich hinzugefügt. Klicken sie hier, um auf die Startseite zurückzukehren";
}
}

break;

This second example actually made me laugh real hard. It's the only line in a file named index.php:

<?php require('index2.php');>  

Introducing: "Developer's shame day"

Permanent Link: Introducing: 26. Oktober 2010 Comment No Comment

Cem Demin (aka "der php hacker") had a great idea: The "Developers shame day". A day on which every developer posts some old code of his that is so awful it really hurts.

The first developers shame day will be on Nov. 3rd, 2010. Let's all participate!

Better Quality through Scrum (Oct '10)

Permanent Link: Better Quality through Scrum (Oct '10) 12. Oktober 2010 Comment One Comment

Here are the slides of my reworked talk "Better quality through Scrum", which I presented at International PHP Conference 2010:

 

var_dumpo

Permanent Link: var_dumpo 20. September 2010 Comment Comments (3)

This common typo will never bug you again!

function var_dumpo()
{
$arguments = func_get_args();
call_user_func_array('var_dump', $arguments);
}

;-)

Better Quality through Scrum (Slides)

Permanent Link: Better Quality through Scrum (Slides) 4. Juni 2010 Comment No Comment

Here are my slides for my talk "Better Quality through Scrum" about how Scrum helps you to improve the quality of your product. I held the talk at the International PHP Conference 2010 Spring Edition.

 

 

Live on Stage (Slides)

Permanent Link: Live on Stage (Slides) 14. Mai 2010 Comment No Comment

Here are my slides for my talk "Live on Stage" about database staging at phpday2010.

 

Some slides don't seem to have been converted correctly though.

Ext.JS: Global shortcuts (e.g. close current tab)

Permanent Link: Ext.JS: Global shortcuts (e.g. close current tab) 17. März 2010 Comment Comments (3)

Ext.JS has an easy way of configuring keyboard shortcuts using Ext.KeyMap. If you wanna use global shortcuts you simply have to bind it to document. I wanna show you in an example how you can bind Alt+X to closing the current tab of a TabPanel layout accessible by the JavaScript variable tabPanelLayout.

new Ext.KeyMap(
document,
[
{
// Alt + X: Close current tab
key: 'x',
alt: true,
// Prevent any browser actions triggered by the shortcut that may occur
stopEvent: true,
fn: function() {
var activePanel = tabPanelLayout.getActiveTab();
Layout.closeTab(activePanel);
}
}
]
);

That's about it! If you only have this one shortcut, you can leave out the JS array.

OOP in JavaScript - Part 4: Scoping

Permanent Link: OOP in JavaScript - Part 4: Scoping 21. Dezember 2009 Comment One Comment

I agree, it took me a while to write part 4 of my OOP in JavaScript series, but here it is now. As for the whole series, basic JavaScript knowledge is needed.

Scoping together with OOP is always an issue, when using asynchronous calls combined with callbacks. Let's create a very easy example where one method of a class registers an onclick EventListener and the second method of the class is the callback for the EventListener. The second method simply calls an alert with a message text defined in the class. Note that the Event Listener registration is not cross-browser safe:

function Handler()
{
}

Handler.prototype.messageText = 'You have clicked somewhere in the document';

Handler.prototype.registerAll = function()
{
window.addEventListener('click', this.handleOnclick, true);
}

Handler.prototype.handleOnclick = function(event)
{
alert(this.messageText);
}

var handler = new Handler();
handler.registerAll();

When clicking anywhere in the document you'd be expecting to see a message box "You have clicked somewhere in the document", but you only get a mesage box saying "undefined". Why is that?

The second argument of addEventListener() is the callback, it expects a function. By putting this.handleOnclick as callback, you are passing a copy of that function. It would be same if you had written it like this:

window.addEventListener('click', function() { alert(this.messageText); }, true);

As you can clearly see now the function stands for itself, this is not in the context(=scope) of the class Handler. In order to achieve exactly that, JavaScript gives us 2 possibilities: apply() and call(). Basically they are both the same, the only difference is in the way you pass further arguments. For a closer distinction, take a look at this page.

By passing an instance as first argument we are telling the function that is called in which scope to be executed, meaning: What instance is this? Let's alter the registerAll method of the example:

Handler.prototype.registerAll = function()
{
window.addEventListener('click', this.handleOnclick.apply(this), true);
}

When running your page now, you will notice that the alert puts out the right message, but is called the moment your page is rendered and the onclick event doesn't work anymore. This is because apply() and call() directly call the respecting function.

What we need to do, is to dynamically create a function that is called with the right scope when needed.

function Handler()
{
}

Handler.prototype.messageText = 'You have clicked somewhere in the document';

Handler.prototype.registerAll = function()
{
window.addEventListener('click', this.createOnclickHandler(), true);
}

Handler.prototype.createOnclickHandler = function()
{
var myScope = this;
return function(event) {
var handle = function(event) {
alert(this.messageText);
}
handle.call(myScope, event);
}
}

var handler = new Handler();
handler.registerAll();

Finally we get to see a "You have clicked somewhere in the document" message box only when clicking somwhere in the document. Note that the second parameter of call() is the Event Object, which is passed as first argument to the called function.

If using this is not total must for you, you can also throw away one of the functions and simply use myScope instead of this:

Handler.prototype.createOnclickHandler = function()
{
var myScope = this;
return function(event) {
alert(myScope.messageText);
}
}

next page >