Serving ZF apps with the PHP 5.4 built-in Web Server

When teaching PHP to newcomers, I have found that (honestly to my surprise) one of the biggest barriers you have to cross is setting the stack up to serve PHP files properly, especially when it comes to Zend Framework apps and other rewrite rule based MVC applications. Even with strong development background, the idea of setting up Web Server configuration to get things working seems foreign to many.

Even as an experienced developer with good knowledge of the LAMP stack setup, setting up new vhosts and other configuration for each new project is sometimes a pain in the ass.

There are of course good news – starting from PHP 5.4, the Command Line Interface (CLI) version of PHP comes with a build-in Web server that can be used to serve PHP apps in development. This Web server is very easy to use – you just fire it up in the right place and it works, serving your PHP files. While it is by no means a viable production solution (it is a sequential, no-concurrency server meaning it will only serve one request at a time), it is very convenient for development purposes.

While it “just works” for simple “1-to-1 URL <-> File” apps, it can work almost as easily for rewrite based MVC apps, including Zend Framework 1.x and 2.x apps and probably for other frameworks as well.

Continue reading

Imagick: Maintain (fake) transparency when saving as JPEG

I haven’t blogged in a while (have been busy you know), so I’ve decided to share this small piece of knowledge I’ve obtained by experimenting. I wrote a small test app (it’s for a feature of the next version of Zend Server – maybe I’ll share it one day when the API is stable), which does some image manipulation with the ImageMagick extension.

For those of you who don’t know ImageMagick allows one to preform pretty cool stuff on images – except for the usual drawing, conversion, rotation, rescaling etc., it also exposes some API to easily preform neat effects, like drop shadow, round corners and my newest favorite (apparently only available in the very latest builds of the extension) – the Polaroid effect.

In his blog Mikko Koppanen, the author of the ImageMagick PHP extension, shows how to create drop shadows (as well as other neat things – you should check out his blog!), but in his examples Mikko will always save as PNG, which is something I dare to say most web users will not do, and prefer saving as JPEG.

Problem with many of those effects, is that they leave parts of the image as transparent. When saving the picture as JPEG (as I do, since saving as PNG produces too big files), these transparent areas appear as black.

So after some experimenting, I’ve found out that the way to work around this is to composite another opaque layer as your background layer, filled with your background color of choice (white in my case). You will of course loose the ability to place the picture on other background colors and still have a nice “transparency” look – but as long as you stick to the background color you’ve set, it will look great.

Here is a code sample producing the same thumbnail + drop shadow as in Mikko’s example, but saving it with white matte color as JPEG:

<?php

$bgColor = '#ffffff'; // End result will have a white background

/* This was taken from Mikko's example */
$im = new Imagick( 'strawberry.png' );
$im->thumbnailImage( 200, null );
$im->roundCorners( 5, 5 );

$shadow = $im->clone();
$shadow->setImageBackgroundColor( new ImagickPixel( 'black' ) );
$shadow->shadowImage( 80, 3, 5, 5 );
$shadow->compositeImage( $im, Imagick::COMPOSITE_OVER, 0, 0 );

/* My addition: clone the entire image again to create the background layer */
$bg = $shadow->clone();

/* I'm using colorFloodFiilImage with high tolerance to paint it all white - maybe there are 'cleaner' ways to do it though */
$bg->colorFloodFillImage($bgColor, 100, '#777777', 0, 0);
$bg->compositeImage($shadow, Imagick::COMPOSITE_OVER, 0, 0);
$bg->setImageFormat('jpeg');
$bg->flattenImages();

/* Display the image */
header( "Content-Type: image/jpeg" );
echo $bg;

While there’s another step in the way, and the image will only look good on white backgrounds, you can now save it as a JPEG file with good compression and acceptable file size.

Debugging CLI PHP with Zend Server and PDT on Linux and Mac

I’m working on a small PHP application and a big part of it are some CLI scripts which will be executed in the background. Some of these scripts are quite complex, and I got to a point where I need to use a debugger in order to figure out what’s going on.

I started hacking around with my locally-installed Zend Server CE and Zend Studio. I always knew how to manually start CLI debug sessions with Zend Studio (well, I knew, but forgot ;-) ), but then I figured, why not write a small shell script to automate the process, and learn a little about the Zend Debugger protocol on the way?

Here is what I did:

First, create the following shell script. I placed it at /usr/local/zend/bin/php-dbg (alongside the other Zend Server executables, which if you use Mac OS X will be at /Applications/ZendServer/bin):

#!/bin/sh

# Wrapper script for debugging PHP CLI scripts with Zend Studio
# Tested with Zend Server 4.0.0 Beta and Zend Studio for Eclipse 6.1.1
# Shahar Evron [shahar.e at zend], 2009-02-20

# Defaults
DFLT_PORT="10137"
DFLT_HOST="127.0.0.1"
DFLT_PARAMS="debug_fastfile=1&use_tunneling=0"

# Load Zend Server environment variables
. /etc/zce.rc

# Did the user specify the debug host / port?
if test "x$DEBUG_HOST" != "x"; then
  if test "x$DEBUG_PORT" != "x"; then
    QUERY_STRING="&debug_port=$DEBUG_PORT"
  else
    QUERY_STRING="&debug_port=$DFLT_PORT"
  fi

  QUERY_STRING="$QUERY_STRING&debug_host=$DEBUG_HOST&$DFLT_PARAMS"

# If no host/port were specified, try to auto-detect
else
  QUERY_STRING=`wget http://localhost:20080/ -O - 2> /dev/null`
  if test $? -ne 0; then
    # Fall back to defaults
    echo "Unable to auto-detect Zend Studio settings, using defaults" >&2
    QUERY_STRING="&debug_port=$DFLT_PORT&debug_host=$DFLT_HOST&$DFLT_PARAMS"
  fi
fi

DBG_SESS_ID=`date +%s`
QUERY_STRING="start_debug=1&debug_stop=1$QUERY_STRING&debug_session_id=$DBG_SESS_ID" 

QUERY_STRING=$QUERY_STRING $ZCE_PREFIX/bin/php -c $ZCE_PREFIX/etc/php.ini $@

Going over this code might teach you some surprising things about how Zend Debugger and Zend Studio talk to each other ;) I’m not going to go into the details now, but if you have questions feel free to ask.

Next, make this script executable – just run ‘chmod +x <path-to-script>‘ – and you’re good to go.

Here is how to use it:

  • If you have PDT or Zend Studio running locally (on the same machine as the server), just run:

    # /usr/local/zend/bin/php-dbg <script you want to debug>

    That would just work in most cases – if it works you can stop reading now ;-)
  • If you are running the script on a server, but your PDT / Zend Studio is on a different machine (in the same LAN – no NAT or firewall!) you can simply specify the IP address or host name of the machine that runs PDT / Zend Studio as the DEBUG_HOST environment variable. For example:

    # DEBUG_HOST=10.1.2.3 /usr/local/zend/bin/php-dbg <script you want to debug>
  • If you are running the script on a remote machine (as above) and your Zend Studio listens on a port other than 10137, you can also pass the DEBUG_PORT environment variable to override the default port.
  • Also, don’t forget to make sure that the machine that runs your Zend Studio is in the list of allowed debugging clients. You can check it at the Zend Server GUI on Server Setup -> Debugger.
  • If you are running the script on a remote host and there’s a firewall / NAT between you and the server (e.g. you are in an office LAN, trying to debug a script on a remote production machine which is not in your subnet) you’ll probably need to use SSH remote port forwarding to forward connections to your PDT / Zend Studio. I won’t get into how to do it right here – unless you insist.
  • If you want to only type ‘php-dbg’ when running instead of the full path, you can place the file in your $PATH (e.g. in /usr/local/bin) or even better, Add /usr/local/zend/bin (or /Applications/ZendServer/bin) to your $PATH – you can do that by adding the following line to ~/.bashrc:

    PATH=$PATH:/usr/local/zend/bin

Upon running the script, a debug session should simply pop-up in your PDT / Studio and you’ll be able to debug. How cool is that?

BTW: This has been tested with Zend Server 4.0.0 beta1 and Zend Studio 6.1.1. It should work with other versions of Studio as well. In fact, it can also work without Zend Server as long as you have Zend Debugger installed – but why ruin a perfectly good plug?

If you improve the script or find bugs, let me know! Also, if you know how to get the same thing going with xDebug, let me know and I’ll add it to the script.

Subversion: Finding the “base” revision of a branch

I use Subversion a lot – but today I’ve learned something new:

You can easily find the “base” revision of a branch or a tag (i.e. the revision in which the branch or tag was created) by issuing the following command:

svn log -v --stop-on-copy 

http://glista.googlecode.com/svn/branches/feature-reminders

The last revision you see in the log (in this case from one of my own Glista project’s branches) is the revision the svn copy command was issued on, i.e. the branch was made.

This can then be used when merging the same branch back into trunk.

Neat!