Handling Ajax requests in the Zend Framework

Tags:

Originally posted in my old blog at My Opera

Doing Ajax is quite simple these days with the various JavaScript libraries offering easy ways to do it. But how do you do it on the server side, without complicating things too much?

Typically, in addition to the Ajax response, you need a traditional page response to a request as well – for example, for browsers which don't support Ajax.

Let's look at some methods how one can detect if a request is an Ajax request and how to respond to them in the Zend Framework.


Read More

What kind of software is needed at a LAN party?

Tags:

Originally posted in my old blog at My Opera

So, the Solid Fireparty is over now and I'm back home. Something like 1200 kilometers driven. I have also posted some photos to the photo gallery and more can be found at http://fireparty.org/lanikuvat/, so check it out.

Getting back on the usual topics, let's look at what kind of software is needed at a LAN party.
There were something like 300-340 visitors at the event, and we had various web-based systems running. I'm going to describe them a bit and some other applications that could come in handy at a slightly larger event like the Fireparty.


Read More

Going to Helsinki

Tags:

Originally posted in my old blog at My Opera


I'm going to Helsinki today, to the Solid Fireparty LAN, to help with the event organization and to do other LAN-party'ish things, whatever they are. I might not post anything from the usual topics for the rest of this week, but stay tuned for photos from the trip (Oulu to Helsinki = 600km, something like 7 hours in a car if driven non-stop) and from the event itself.

LAN party place reservation

Tags:

Originally posted in my old blog at My Opera

Let's take a look at one of my biggest PHP projects so far: Reservinator 1.0, or in other words, a very advanced place reservation system for LAN parties. The page is in finnish, but the post is not, so read on!

If you've even been to a LAN party, you might've used something similar to this system. Amongst other features, Reservinator let's you view an overview map of the event location, choose your place by clicking the place you wish to reserve, and sign up for competitions.

It also has various admin tools, such as sending email to users, marking their reservations as paid based on the bill reference number, and biggest of all, building the overview map with a very easy to use drag and drop interface for placing rooms, tables and other things.

Read More

How to make a modal AJAX login box with Mootools

Tags:

Originally posted in my old blog at My Opera

Sometimes I've been asked to do a modal AJAX login box for a website. What is that you ask?

It's basically what you can do in JavaScript with alert() but with different functionality: If you do alert('foo'), you get a box with text “foo” that you must close before doing anything else. This kind of dialogs are called modal dialogs.

In this post I'll show you how to make a modal login box that can work nicely even in browsers without proper JavaScript support. This is quite easy with the proper tools.

For this article, you will just need to know some HTML and JavaScript.

Read More

Lively Kernel – Another waste of time?

Tags:

Originally posted in my old blog at My Opera

Sun Labs recently introduced Lively Kernel, which is an attempt to treat web applications in a similar way as desktop applications are programming-wise.

The Lively Kernel places a special emphasis on treating web applications as real applications, as opposed to the document-oriented nature of most web applications today. In general, we want to put programming into web development, as opposed to the current weaving of HTML, XML and CSS documents that is also sometimes referred to as programming.

Says it the best. Despite sounding interesting, this may all be a big waste of time.

Read More

Blocking ads on websites is bad behavior

Tags:

Originally posted in my old blog at My Opera

A lot of people really dislike any ads on a website. This shows in browsers too: Opera added a content blocker and Firefox has AdBlock and probably at least two other plugins for getting rid of ads. Some people even use separate ad blocking proxy tools such as Proxomitron and IP address blocks for servers known as ad servers.

I think people who block ads are wrong.

Read More

How to easily redirect PHP output to a file

Tags:

Ever wanted to change where your PHP sends the output to a file instead of the browser?
I have, and it involved changing every echo and other printing statemenet to fwrite. But

there is a better solution to that…


Tell me more

You probably have heard, or even used, PHP's output buffering functions. When you normally do something like echo 'hello'; in PHP, it will be immediately sent to the browser. Sometimes you may want to send headers, perhaps a redirection, to the user after the script has sent something else to the browser. This will normally cause an error, because the HTTP protocol says that you must send headers first and content after them. Output buffering functions can be used to buffer any data you output, and including other things, will let you send headers after other data has already been sent.

ob_start() and ob_end_flush() might already be familiar to you. In addition to their typical uses, the output buffering functions can be used to do various neat tricks, such as writing all output to a file.

The function ob_start() takes an optional parameter for a callback function. The callback function receives all output from PHP, so this is what we can use for our purprose.

Onwards to the code

Now that we have the basics covered, let's look at the code a bit.

Let's first look at a few functions to see how this will work, and then we will refactor it into a nice class. Let's start!

We need to open a file where the output will be written to

$ob_file = fopen('test.txt','w');

Very basic stuff. Next, let's create the callback function which will perform the actual writing to the file:

function ob_file_callback($buffer)
{
  global $ob_file;
  fwrite($ob_file,$buffer);
}

Look! There's a global, aren't they evil?
Don't worry about it, when we get to the next chapter, we will get rid of it in the class we will create.

Now we have all that we need together:

$ob_file = fopen('test.txt','w');

ob_start('ob_file_callback');

//Anything we output now will go to test.txt
echo 'Hi everyone!';
echo 'I bet you can\'t see this in your browser';

ob_end_flush();

Provided your script can write to test.txt, the above code will write the echo's to the file and not to the browser. Simple and easy.

This code we just made isn't very easy to re-use though: We used a global variable and we have to manually open the file and things like that. To make our code a little nicer, let's make it into a class!

Classified

Making this into a nice, easy to use class is pretty simple. I don't want to have to manually open a file, so I want the class to be able to open the target file for writing. It also obviously needs to handle the callback and such on its own so after I have written the class, I won't have to bother with the details anymore.

Let's just call the class OB_FileWriter. Note that I'm using PHP5 syntax, so if you're running PHP4, you need to change all variable declarations to var $variablename, change __construct into OB_FileWriter, remove __destruct and remove “public” from all function declarations.

class OB_FileWriter
{
  private $_filename;
  private $_fp = null;

  public function __construct($filename)
  {
    $this->setFilename($filename);
  }

  public function __destruct()
  {
    if($this->_fp)
      $this->end()
  }

  public function setFilename($filename)
  {
    $this->_filename = $filename;
  }

  public function getFilename()
  {
    return $this->_filename;
  }

  public function start()
  {

  }

  public function end()
  {

  }

  public function outputHandler($buffer)
  {

  }
}

So there's the basic skeleton for the class. Now let's add the code to the empty functions.

public function start()
{
  $this->_fp = @fopen($this->_filename,'w');

  if(!$this->_fp)
    throw new Exception('Cannot open '.$this->_filename.' for writing!');

  ob_start(array($this,'outputHandler'));
}

This function will be used for starting output buffering. It opens the file, checks if it was succesfull and starts buffering. Note that we used the @ symbol in front of the fopen command to suppress PHP error messages and instead just check if the $_fp variable was set and throw an exception if it failed.

ob_start takes the callback as the first parameter, but why is it an array? In PHP if you want to pass class' functions as callbacks, you need to pass an array containing the owner class and the class function name.

Next, the end function..

public function end()
{
  @ob_end_flush();
  if($this->_fp)
    fclose($this->_fp);
  
  $this->_fp = null;
}

First calling the ob_end_flush to end the buffering and flush the data to the file. Then if the file is still open as it should be, close it and set the variable to null to signify that the file is no longer open.

Finally, the outputHandler function

public function outputHandler($buffer)
{
  fwrite($this->_fp,$buffer);
}

Simplest of them all! Just dump the contents of the buffer to the file.

Now we have a class for sending output to a file. Compare using this class to the approach in the earlier example:

$obfw = new OB_FileWriter('test.txt');
$obfw->start();

echo 'Hi everyone!';
echo 'I bet you can\'t see this in your browser';

$obfw->end();

Nice and easy!

Final improvements

The class can be used now, but there's one small thing to consider:

If we start the buffering and the code we run after that gives an error or throws an uncaught exception, what happens?

The message from the error will go straight to the file, which isn't necessarily what you want. At least I like to see my errors when they happen so that I can do something about it, so let's make it so that our class can optionally try to detect errors and exceptions and halt the buffering so that we can see them.

We can do this by registering our own error and exception handlers inside our class which will then stop the buffering and display the errors.

The class needs some new functions and a new variable for this, so let's add the variable first…

private $_errorHandlersRegistered = false;

and the functions…

private function _stopBuffering()
{

}

public function setHaltOnError($value)
{

}

public function exceptionHandler($exception)
{

}

public function errorHandler($errno, $errstr, $errfile, $errline)
{

}

The function names should be pretty self explanatory, so let's continue with adding the code in them:

public function setHaltOnError($value)
{
  //Do nothing if the value is the same as old
  if($value === $this->_errorHandlersRegistered)
    return;

  if($value === true)
  {
    set_exception_handler(array($this, 'exceptionHandler'));
    set_error_handler(array($this, 'errorHandler'));
    $this->_errorHandlersRegistered = true;
  }
  else
  {
    restore_exception_handler();
    restore_error_handler();
    $this->_errorHandlersRegistered = false;
  }
}

So depending on the value you pass to this function, it will either register the class' error and exception handlers or restore the old handlers for them.

Now, let's add the code for the handlers:

public function exceptionHandler($exception)
{
  $this->_stopBuffering();
  echo 'Fatal error: Uncaught ', $exception;
}

Quite simple. Stop buffering and print a message with the exception details.

public function errorHandler($errno, $errstr, $errfile, $errline)
{
  $this->_stopBuffering();
  
  $errorNumber = E_USER_ERROR;
  switch($errno)
  {
    case E_NOTICE:
      $errorNumber = E_USER_NOTICE;
      break;
    case E_WARNING:
      $errorNumber = E_USER_WARNING;
      break;
  }

  trigger_error($errstr.', File: '.$errfile.' line '.$errline, $errorNumber);
}

We can re-trigger errors and they will be handled by the default error handler, so that's what we do here.

So what about _stopBuffering()? Let's move the code which stops the buffering from end() to this function and modify end a bit too…

public function end()
{
  $this->_stopBuffering();
  $this->setHaltOnError(false);
}

private function _stopBuffering()
{
  @ob_end_flush();
  
  if($this->_fp)
    fclose($fp);

  $this->_fp = null;
}

We do this because we want to be able to stop the buffering without removing the error handlers. Also, when we end(), we want to return back to using the normal error handlers so we must add that to end()

In closing

So redirecting PHP output to a file is pretty simple to do. Just some things to remember, such as that error/exception thing.

You might wonder why not just simply use ob_start(), ob_get_clean() and file_put_contents… With the class I described, everything outputted will be sent to the file when it's being written and if something else fails afterwards, the stuff which was sent earlier is still in the file. Writing the contents of the buffer to the file in the end of the script would mean that nothing is written if there's an error, so which way is better just depends on what your goal is.

Complete source code for OB_FileWriter