The new stuff

Let's see what are the new features PHP 5.4 has to offer, first.

Traits

Probably the biggest new feature in 5.4, traits allow you to share code between multiple classes, without resorting to (multiple) inheritance. It is similar to Perl mixins, or Ruby roles (Ruby has roles, right?). This is good, because inheritance was usually abused for code sharing, but it's primary goal was never that. So, you can define a Trait, which is similar to a class in structure, then have your classes use it, which basically means they will get all the methods defined in the traits. I like to call it runtime copypaste.

trait CamelCaser {

    public function camelize($str) {
        return lcfirst(str_replace(" ", "", ucwords(strtr($word, "_-", " "))));
    }

    public function unCamelize($str) {
        return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $word));
    }

}

// Database abstraction layer
class DBAL use CamelCaser {
}

$dbal = new DBAL();
$dbal->camelize("hello_world"); // outputs helloWorld

While I see lot of potential in Traits, I can't help but fear, that this will be the new public static function, that is, it will get abused by programmers for quick shortcuts, leading to code smells. I think, a very good use case would be like a language supported object composition, so, instead of passing around a CamelCaser object, you can make a trait out of it, but this only works if the code does not depend on state, since Traits won't (and cannot) be instantiated, you don't have any options for customizing them runtime.
We'll see. Of course there are edge cases, like what happens if two traits have a method with the same name, or if a trait has a method that class already has, and so on, the traits docs have everything explained.

Short array syntax

Short array syntax was originally requested in 2008 with a complete RFC, but it never got implemented, because the developers' opinion was "it would confuse users". Well, it seems their opinion has changed, and PHP now has support for an array syntax that is similar to the JSON notation:

$fruits = [ 'apple', 'orange', 'banana' ];
$person = [ 'name' => 'Jane Doe', 'age' => 23 ];

Array dereferencing

I was surprised that this has a so well defined name. Array dereferencing allows you to pick an element out of an array, even if the array is the result of an expression, and not a simple variable.

// What you had to do < PHP 5.4
$userData = getUserData($id);
$name = $userData['name'];

// But now you can do
$name = getUserData($id)['name'];

Also, you are now allowed to "call through constructors", without saving the object into a variable, like how Java allows you to do. Not sure about the usefulness of that one, though:

// Before 5.4
$object = new Foo();
$object->method();

// Now
new Foo()->method();

Closure rebinding, and closures using $this

Oh sweet Baby Jesus, yes please, no more $that = $this bullshit. I'm more stoked for this, than Traits. How many times have I had to write code like this:

// Back in the dark times
public function getExecutor() {
    $that = $this;
    return function($arg) use ($that) {
        return $that->method($arg);
    };
}

// WELL NO MORE BABY
public function getExecutor() {
    return function($arg) {
        return $this->method($arg);
    };
}

// But wait, there is more, you can even change what $this points to, with closure rebinding
$object = new Foo();
$closure = $object->getExecutor();
$newClosure = $closure->bindTo($anotherObject); // $this points to $anotherObject, inside $newClosure

Closures (anonymus functions), act like an instance of the class Closure, this was already introduced in PHP 5.3.0, but now they have a method called bindTo(), which you can use to specify what $this points to, inside the function. Note that $closure->bindTo() does not modify $closure, but creates, and returns a new one! Also, the scoping rules are evaluated correctly, which means you can even call private methods, which was impossible with the $that = $this workaround.

Callable typehint

A very small thing, but useful nonetheless, Callable as a typehint allows you to restrict parameters in a function to only values that can be executed with call_user_func, and the likes:

function run(Callable $command) {
    // now you can safely do this, without the need to make sure it's callable
    call_user_func($command);
}

// The following values are considered Callable
$var = function () { };
$var = "function_name";
$var = ['class', 'staticMethodName'];
$var = [$object, 'methodName'];
$var = $invokableObject;

// Another neat little thing, everything that is considered a Callable can be called with the "()" notation, so this works
$var = [$object, 'methodName'];
$var();

The short echo syntax <?= is always available

That's right, <?= which is a shortcut for <?php echo, works independently of short_open_tags. Note that this only affects the echo shorthand, the short open tag itself is still dependent on the ini setting, so feel free to continue debating around whether they should be enabled or disabled by default, or removed altogether.

Removed features

New versions don't just bring new features, they sometimes remove old deprecated stuff. Some of the notable ones:

Safe Mode

Safe mode introduced some settings, that when enabled would only allow PHP to open files that are owned by the same gid/uid as the PHP process, restrict passed environment variables, restrict where (which directory) shell code related functions (like system(), exec()) can run, and disabled some functions that could be considered harmful. There are many solutions to securing your PHP installation, without resorting to safe mode, so don't worry about it.

Magic Quotes

This was probably the biggest facepalm feature in PHP. Magic quotes was advertised as an "automatic protection against SQL injection attacks" solution, but all it did in reality was to run addslashes(), on the $_GET, $_POST, $_REQUEST superglobals, which was only partial solution, since addslashes() is not enough to prevent against SQL injection. It just lead to further problems when you correctly escaped your SQL statements, because if some other server had it enabled, you had to write some dispel magic logic, so you won't end up with double escaping. Well, no more of that, magic quotes is finally dead. The developers were pretty clever, because they left get_magic_quotes_gpc(), and get_magic_quotes_runtime() in (and they always return false), so you don't have to rewrite your old apps that were only checking if it was enabled.

Minor stuff

There are of course lots and lots of minor stuff, like call time pass by reference removed, register_globals removed (and if you still have to maintain code depending on that, I'll give you a bro hug), a JsonSerializable interface, which allows you to customize how your object get's serialized when json_encode() is called on it, new reserved keywords, removed functions, a built-in webserver, and so on. According to the developers, it also performs better, by around 5-20%, 25% smaller memory footprint.

Useful links for details