70
PHP without PHP The Philosophy of Good Architecture terry chay 2009-05-27T14:15+0200 International PHP Conference Berlin, Germany

PHP Without PHP—IPC

Embed Size (px)

DESCRIPTION

PDF version of my slide deck for "PHP Without PHP" given at International PHP Conference in Berlin, Germany on May 2009 Abstract: An obscure but ubiquitous design pattern in PHP development is known as Funky Caching. Using real architectural examples as a lens to look at this one simple PHP design pattern, we see how we can design web architectures that are "organic, democratic, and lasting."

Citation preview

Page 1: PHP Without PHP—IPC

PHP without PHPThe Philosophy of Good

Architecture

terry chay2009-05-27T14:15+0200

International PHP ConferenceBerlin, Germany

Page 2: PHP Without PHP—IPC

Funky CachingPrologue #1

Page 3: PHP Without PHP—IPC

aka

ErrorDocument trick

Smarter Caching

… Rasmus’s Trick (Stig’s trick)

Go into apache.conf (or .htaccess) and

ErrorDocument 404 /error.php

Page 4: PHP Without PHP—IPC

$filepath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //or $_SERVER['REDIRECT_URL']$basepath = dirname(__FILE__).DIR_SEP; // Test to see if you can work with itif (false) { //…EDIT…    //output a 404 page    include('404.html'); // see http://www.alistapart.com/articles/perfect404/ for tips    return;} // Generate the file// …EDIT…$data = 'something'; // Don't send 404 back, send 200 OK because this is a pretty smart 404// not a clueless one! http://www.urbandictionary.com/define.php?term=404header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));//Show the fileecho $data; //Store the page to bypass PHP on the next request. Use a temp file with a// link trick in order to avoid race conditions between concurrent PHP// processes.$tmpfile = tempnam($basepath.'tmp','fc');$fp = fopen($tmpfile,'w'); //remove the "_" this is crashing my blog syntax hilighterfputs($fp, $data);fclose($fp);@link($basepath.$filepath, $tmpfile); //suppress errors due to losing raceunlink($tmpfile);

Error.PHP

Page 5: PHP Without PHP—IPC

$filepath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //or $_SERVER['REDIRECT_URL']$basepath = dirname(__FILE__).DIR_SEP; // Test to see if you can work with itif (false) { //…EDIT…    //output a 404 page    include('404.html'); // see http://www.alistapart.com/articles/perfect404/ for tips    return;} // Generate the file// …EDIT…$data = 'something'; // Don't send 404 back, send 200 OK because this is a pretty smart 404// not a clueless one! http://www.urbandictionary.com/define.php?term=404header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));//Show the fileecho $data; //Store the page to bypass PHP on the next request. Use a temp file with a// link trick in order to avoid race conditions between concurrent PHP// processes.$tmpfile = tempnam($basepath.'tmp','fc');$fp = fopen($tmpfile,'w'); //remove the "_" this is crashing my blog syntax hilighterfputs($fp, $data);fclose($fp);@link($basepath.$filepath, $tmpfile); //suppress errors due to losing raceunlink($tmpfile);

Error.PHP

Page 6: PHP Without PHP—IPC

$filepath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); //or $_SERVER['REDIRECT_URL']$basepath = dirname(__FILE__).DIR_SEP; // Test to see if you can work with itif (false) { //…EDIT…    //output a 404 page    include('404.html'); // see http://www.alistapart.com/articles/perfect404/ for tips    return;} // Generate the file// …EDIT…$data = 'something'; // Don't send 404 back, send 200 OK because this is a pretty smart 404// not a clueless one! http://www.urbandictionary.com/define.php?term=404header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));//Show the fileecho $data; //Store the page to bypass PHP on the next request. Use a temp file with a// link trick in order to avoid race conditions between concurrent PHP// processes.$tmpfile = tempnam($basepath.'tmp','fc');$fp = fopen($tmpfile,'w'); //remove the "_" this is crashing my blog syntax hilighterfputs($fp, $data);fclose($fp);@link($basepath.$filepath, $tmpfile); //suppress errors due to losing raceunlink($tmpfile);

Error.PHP

Page 7: PHP Without PHP—IPC

PHP without PHP

Page 8: PHP Without PHP—IPC

ParadigmsPrologue #2

Page 9: PHP Without PHP—IPC

Code CompleteThe metaphor of Code as

construction comes from this

book…

W e n o w k n o w t h i s i s fundamentally wrong…

Page 10: PHP Without PHP—IPC

Mythical Man Month“man-month” is a term from

construction work

The premise is that man and

months are interchangeable.

This means that in order to

reach a deadline I simply add

more people to the project.

Page 11: PHP Without PHP—IPC

F i r s t c o n s i d e r s o m e t h i n g l i k e

painting a fence: everything is

partionable (man-month).

…add a constant time for training.

…add communication cost: n(n-1)/2.

Compare to the unpartitionable

(single man)

Adding people to a late project

makes it later!

5

10

15

20 Tim

e t

o C

Om

pl

et

e T

itl

e

Number of People

paritionablewith trainingtraning + communicationunpartitionable

Page 12: PHP Without PHP—IPC

Engineer and Architect

Page 13: PHP Without PHP—IPC

1 Fallingwaterorganic, democratic, plasticity, continuity

Page 14: PHP Without PHP—IPC
Page 15: PHP Without PHP—IPC

…including me

Page 16: PHP Without PHP—IPC

Hatchway Staircase View at the main (living room) level, from the bridge (from east)

Page 17: PHP Without PHP—IPC

Beyond the glass Fallingwater: Living room terraces and glass walls (from east).

Page 18: PHP Without PHP—IPC

Fall Foliage View from lookout, downstream.

Page 19: PHP Without PHP—IPC

Fall Foliage View from lookout, downstream.

Page 20: PHP Without PHP—IPC

No barriers Detail: corner window at the guest house, from southeast.

Page 21: PHP Without PHP—IPC

Existing tree The trellis over the driveway is built to accommodate a tree.

Page 22: PHP Without PHP—IPC

Local quarry Living room, west (downstream) side, from southeast

Page 23: PHP Without PHP—IPC

Existing boulder Living room fireplace and hearth, looking from kitchen door to south windows

Page 24: PHP Without PHP—IPC
Page 25: PHP Without PHP—IPC

Philosophyorganic,

democratic,

plasticity,

continuity.

Page 26: PHP Without PHP—IPC

Why on PHP?

Page 27: PHP Without PHP—IPC

Harmony with Environment

Apache web server: ErrorDocument

Customer-centric: Performance paramount

Relational Database: Slow persistence

Harmony with PHP itself…

Page 28: PHP Without PHP—IPC

Architecture of PHP Modern web architecture

Page 29: PHP Without PHP—IPC

PHP is “Cheap”

“A project done in Java will cost 5 times as much, take twice as long, and be harder to maintain than a project done in a scripting language such as PHP or Perl.”

—Phillip Greenspun

Page 30: PHP Without PHP—IPC

PHP is “Scalable”

“That a Java servlet performs better than a PHP script, under optimal conditions [has] nothing to do with scalability. The point is can your application continue to deliver consistent performance as volume increases. PHP delegates all the ‘hard stuff’ to other systems.”

—Harry Fuecks

Page 31: PHP Without PHP—IPC

PHP is “Pragmatic”

“PHP is not about purity in CS principles or architecture; it is about solving the ugly web problem with an admittedly ugly, but extremely functional and convenient solution. If you are looking for purity, you are in the wrong boat. Get out now before you get hit by a wet cat!”

—Rasmus Lerdorf

Page 32: PHP Without PHP—IPC

2 Bellefield TowersDesign Hubris

Page 33: PHP Without PHP—IPC
Page 34: PHP Without PHP—IPC

Gothic Romanesque architecture The current Bellefield Church (two blocks away)

Page 35: PHP Without PHP—IPC

Other city towers Allegheny Courthouse Main Tower & Four Tower Types at Jail (and other towers)

Page 36: PHP Without PHP—IPC

Tower of Learning

Within spitting distance of Bellefield Towers

Page 37: PHP Without PHP—IPC

Carnegie Library Most iconic moment in baseball history

Page 38: PHP Without PHP—IPC

Why is Bellefield Towers so Ugly?

Page 39: PHP Without PHP—IPC

Design Hubris?Frameworks (almost by definition)

Develop in the PHP community?

Take over an existing project?

Limitations of Site Operations? Hosting? or Virtual hosting?

Business needs trump programmer desire?

Dealt with a user request?

Page 40: PHP Without PHP—IPC

…at Tagged

add slideshow

Page 41: PHP Without PHP—IPC

…at TaggedCubes

Waterfall process Oracle RAC

JavaPHP4

Zend Accelerator

Page 42: PHP Without PHP—IPC

Solutions Consider Environment

Page 43: PHP Without PHP—IPC

3 Golden Gate BridgeThe Design Pattern

Page 44: PHP Without PHP—IPC
Page 45: PHP Without PHP—IPC

the other bridge

Page 46: PHP Without PHP—IPC
Page 47: PHP Without PHP—IPC
Page 48: PHP Without PHP—IPC

Same problem, different pattern

Original design was hybrid cantilever-suspension.

Replaced by purse suspension

Page 49: PHP Without PHP—IPC

Art DecoBridge Tower, Lighting,

pedestrial walkway

Page 50: PHP Without PHP—IPC

International Orange

Rust colored like the environment it lives in … and

safe.

Page 51: PHP Without PHP—IPC

Part of the whole

Page 52: PHP Without PHP—IPC

Design Patterns Defined

“Each pattern describes a

problem which occurs over

a n d o v e r a g a i n i n o u r

e n v i r o n m e n t , a n d t h e n

describes the core of the

solution to that problem, in

such a way that you can use

this solution a million times

over, without ever doing it

the same way twice.”

Page 53: PHP Without PHP—IPC

Certainly iconic Me in front of both icons

Page 54: PHP Without PHP—IPC

Never the same way twice How do you know which one?

How do you know which way?

Page 55: PHP Without PHP—IPC

Funky Caching again

“search for the closest matching valid URL and redirect, and use attempted url text as a DB keyword lookup”

—Rasmus Lerdorf

Page 56: PHP Without PHP—IPC
Page 57: PHP Without PHP—IPC
Page 58: PHP Without PHP—IPC

Javascript and CSS compiling & caching

Page 59: PHP Without PHP—IPC
Page 60: PHP Without PHP—IPC
Page 61: PHP Without PHP—IPC

<?php

$watermark = '3129080702_c4e76f71d7_o.png';$dead_url = 'http://example.com/dead_image.png'; // {{{ start_image($filename, &$data)/*** Creates a gd handle for a valid file* @param $filename string the file to get* @param $data array the imagesize* @return resource GD handle*/function start_image($filename, &$data) {    $data = @getimagesize($filename);    if (empty($data)) { return null; }    $data['ratio'] = $data[0]/$data[1];    switch($data[2]) {        case IMG_GIF: return imagecreatefromgif($filename);        case 3: //problem where IMG_PNG is not bound correctly for my install        case IMG_PNG: return imagecreatefrompng($filename);        case IMG_JPG: return imagecreatefromjpeg($filename);        case IMG_WBMP: return imagecreatefromwbmp($filename);        case IMG_XPM: return imagecreatefromxbm($filename);    }    return null;}   // }}}$requestimg = $_SERVER['REDIRECT_URL'];if (!$_SERVER['QUERY_STRING']) {    // redirect user to invalid image    tag_http::redirect($dead_url);    return '';}// grab image to temp {{{$ch = curl_init($_SERVER['QUERY_STRING']);$tempfile = tempnam('/tmp', 'prod_remote_');$fp = f_open($tempfile, 'w'); //again delete the "_"curl_setopt($ch, CURLOPT_FILE, $fp);curl_setopt($ch, CURLOPT_HEADER, 0);curl_exec_($ch); //delete the final "_"curl_close($ch);fclose($fp);// }}}

Page 62: PHP Without PHP—IPC

<?php

$watermark = '3129080702_c4e76f71d7_o.png';$dead_url = 'http://example.com/dead_image.png'; // {{{ start_image($filename, &$data)/*** Creates a gd handle for a valid file* @param $filename string the file to get* @param $data array the imagesize* @return resource GD handle*/function start_image($filename, &$data) {    $data = @getimagesize($filename);    if (empty($data)) { return null; }    $data['ratio'] = $data[0]/$data[1];    switch($data[2]) {        case IMG_GIF: return imagecreatefromgif($filename);        case 3: //problem where IMG_PNG is not bound correctly for my install        case IMG_PNG: return imagecreatefrompng($filename);        case IMG_JPG: return imagecreatefromjpeg($filename);        case IMG_WBMP: return imagecreatefromwbmp($filename);        case IMG_XPM: return imagecreatefromxbm($filename);    }    return null;}   // }}}$requestimg = $_SERVER['REDIRECT_URL'];if (!$_SERVER['QUERY_STRING']) {    // redirect user to invalid image    tag_http::redirect($dead_url);    return '';}// grab image to temp {{{$ch = curl_init($_SERVER['QUERY_STRING']);$tempfile = tempnam('/tmp', 'prod_remote_');$fp = f_open($tempfile, 'w'); //again delete the "_"curl_setopt($ch, CURLOPT_FILE, $fp);curl_setopt($ch, CURLOPT_HEADER, 0);curl_exec_($ch); //delete the final "_"curl_close($ch);fclose($fp);// }}}

Page 63: PHP Without PHP—IPC

<?php

$watermark = '3129080702_c4e76f71d7_o.png';$dead_url = 'http://example.com/dead_image.png'; // {{{ start_image($filename, &$data)/*** Creates a gd handle for a valid file* @param $filename string the file to get* @param $data array the imagesize* @return resource GD handle*/function start_image($filename, &$data) {    $data = @getimagesize($filename);    if (empty($data)) { return null; }    $data['ratio'] = $data[0]/$data[1];    switch($data[2]) {        case IMG_GIF: return imagecreatefromgif($filename);        case 3: //problem where IMG_PNG is not bound correctly for my install        case IMG_PNG: return imagecreatefrompng($filename);        case IMG_JPG: return imagecreatefromjpeg($filename);        case IMG_WBMP: return imagecreatefromwbmp($filename);        case IMG_XPM: return imagecreatefromxbm($filename);    }    return null;}   // }}}$requestimg = $_SERVER['REDIRECT_URL'];if (!$_SERVER['QUERY_STRING']) {    // redirect user to invalid image    tag_http::redirect($dead_url);    return '';}// grab image to temp {{{$ch = curl_init($_SERVER['QUERY_STRING']);$tempfile = tempnam('/tmp', 'prod_remote_');$fp = f_open($tempfile, 'w'); //again delete the "_"curl_setopt($ch, CURLOPT_FILE, $fp);curl_setopt($ch, CURLOPT_HEADER, 0);curl_exec_($ch); //delete the final "_"curl_close($ch);fclose($fp);// }}}

Page 64: PHP Without PHP—IPC

<?php

$watermark = '3129080702_c4e76f71d7_o.png';$dead_url = 'http://example.com/dead_image.png'; // {{{ start_image($filename, &$data)/*** Creates a gd handle for a valid file* @param $filename string the file to get* @param $data array the imagesize* @return resource GD handle*/function start_image($filename, &$data) {    $data = @getimagesize($filename);    if (empty($data)) { return null; }    $data['ratio'] = $data[0]/$data[1];    switch($data[2]) {        case IMG_GIF: return imagecreatefromgif($filename);        case 3: //problem where IMG_PNG is not bound correctly for my install        case IMG_PNG: return imagecreatefrompng($filename);        case IMG_JPG: return imagecreatefromjpeg($filename);        case IMG_WBMP: return imagecreatefromwbmp($filename);        case IMG_XPM: return imagecreatefromxbm($filename);    }    return null;}   // }}}$requestimg = $_SERVER['REDIRECT_URL'];if (!$_SERVER['QUERY_STRING']) {    // redirect user to invalid image    tag_http::redirect($dead_url);    return '';}// grab image to temp {{{$ch = curl_init($_SERVER['QUERY_STRING']);$tempfile = tempnam('/tmp', 'prod_remote_');$fp = f_open($tempfile, 'w'); //again delete the "_"curl_setopt($ch, CURLOPT_FILE, $fp);curl_setopt($ch, CURLOPT_HEADER, 0);curl_exec_($ch); //delete the final "_"curl_close($ch);fclose($fp);// }}}

Page 65: PHP Without PHP—IPC

<?php

$watermark = '3129080702_c4e76f71d7_o.png';$dead_url = 'http://example.com/dead_image.png'; // {{{ start_image($filename, &$data)/*** Creates a gd handle for a valid file* @param $filename string the file to get* @param $data array the imagesize* @return resource GD handle*/function start_image($filename, &$data) {    $data = @getimagesize($filename);    if (empty($data)) { return null; }    $data['ratio'] = $data[0]/$data[1];    switch($data[2]) {        case IMG_GIF: return imagecreatefromgif($filename);        case 3: //problem where IMG_PNG is not bound correctly for my install        case IMG_PNG: return imagecreatefrompng($filename);        case IMG_JPG: return imagecreatefromjpeg($filename);        case IMG_WBMP: return imagecreatefromwbmp($filename);        case IMG_XPM: return imagecreatefromxbm($filename);    }    return null;}   // }}}$requestimg = $_SERVER['REDIRECT_URL'];if (!$_SERVER['QUERY_STRING']) {    // redirect user to invalid image    tag_http::redirect($dead_url);    return '';}// grab image to temp {{{$ch = curl_init($_SERVER['QUERY_STRING']);$tempfile = tempnam('/tmp', 'prod_remote_');$fp = f_open($tempfile, 'w'); //again delete the "_"curl_setopt($ch, CURLOPT_FILE, $fp);curl_setopt($ch, CURLOPT_HEADER, 0);curl_exec_($ch); //delete the final "_"curl_close($ch);fclose($fp);// }}}// configure image and dimensions {{{$size_data = array();$im = start_image($tempfile, $size_data);if (!$im) {    unlink($tempfile);    tag_http::redirect($dead_url);    return;}// }}}// get watermark information {{{$wm_data = array();$wm = start_image($watermark, $wm_data);if (!$wm) {    unlink ($tempfile);    tag_http::redirect($dead_url);    return;}// }}}// add watermark {{{if ($size_data['ratio']> $wm_data['ratio']) {    // image is wider format than the watermark    $new_smaller_dim = $wm_data[0] * ($size_data[1]/$wm_data[1]);    $dst_x = ($size_data[0] - $new_smaller_dim)/2;    $dst_y = 0;    $dst_w = $new_smaller_dim;    $dst_h = $size_data[1];} else {    // image is taller format than the watermark    $new_smaller_dim = $wm_data[1] * ($size_data[0]/$wm_data[0]);    $dst_x = 0;    $dst_y = ($size_data[1] - $new_smaller_dim)/2;    $dst_w = $size_data[0];    $dst_h = $new_smaller_dim;;}imagecopyresized($im, $wm, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $wm_data[0], $wm_data[1]);header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));header(sprintf('Content-type: %s',$size_data['mime']));// }}}switch ($size_data[2]) {    case IMG_GIF: imagegif($im); break;    case 3: case IMG_PNG: imagepng($im); break;    case IMG_JPG: imagejpeg($im); break;    case IMG_WBMP: imagewbmp($im); break;    case IMG_XPM: imagexbm($im); break;}imagedestroy($wm);imagedestroy($im);unlink($tempfile);

Page 66: PHP Without PHP—IPC

<?php

$watermark = '3129080702_c4e76f71d7_o.png';$dead_url = 'http://example.com/dead_image.png'; // {{{ start_image($filename, &$data)/*** Creates a gd handle for a valid file* @param $filename string the file to get* @param $data array the imagesize* @return resource GD handle*/function start_image($filename, &$data) {    $data = @getimagesize($filename);    if (empty($data)) { return null; }    $data['ratio'] = $data[0]/$data[1];    switch($data[2]) {        case IMG_GIF: return imagecreatefromgif($filename);        case 3: //problem where IMG_PNG is not bound correctly for my install        case IMG_PNG: return imagecreatefrompng($filename);        case IMG_JPG: return imagecreatefromjpeg($filename);        case IMG_WBMP: return imagecreatefromwbmp($filename);        case IMG_XPM: return imagecreatefromxbm($filename);    }    return null;}   // }}}$requestimg = $_SERVER['REDIRECT_URL'];if (!$_SERVER['QUERY_STRING']) {    // redirect user to invalid image    tag_http::redirect($dead_url);    return '';}// grab image to temp {{{$ch = curl_init($_SERVER['QUERY_STRING']);$tempfile = tempnam('/tmp', 'prod_remote_');$fp = f_open($tempfile, 'w'); //again delete the "_"curl_setopt($ch, CURLOPT_FILE, $fp);curl_setopt($ch, CURLOPT_HEADER, 0);curl_exec_($ch); //delete the final "_"curl_close($ch);fclose($fp);// }}}// configure image and dimensions {{{$size_data = array();$im = start_image($tempfile, $size_data);if (!$im) {    unlink($tempfile);    tag_http::redirect($dead_url);    return;}// }}}// get watermark information {{{$wm_data = array();$wm = start_image($watermark, $wm_data);if (!$wm) {    unlink ($tempfile);    tag_http::redirect($dead_url);    return;}// }}}// add watermark {{{if ($size_data['ratio']> $wm_data['ratio']) {    // image is wider format than the watermark    $new_smaller_dim = $wm_data[0] * ($size_data[1]/$wm_data[1]);    $dst_x = ($size_data[0] - $new_smaller_dim)/2;    $dst_y = 0;    $dst_w = $new_smaller_dim;    $dst_h = $size_data[1];} else {    // image is taller format than the watermark    $new_smaller_dim = $wm_data[1] * ($size_data[0]/$wm_data[0]);    $dst_x = 0;    $dst_y = ($size_data[1] - $new_smaller_dim)/2;    $dst_w = $size_data[0];    $dst_h = $new_smaller_dim;;}imagecopyresized($im, $wm, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $wm_data[0], $wm_data[1]);header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));header(sprintf('Content-type: %s',$size_data['mime']));// }}}switch ($size_data[2]) {    case IMG_GIF: imagegif($im); break;    case 3: case IMG_PNG: imagepng($im); break;    case IMG_JPG: imagejpeg($im); break;    case IMG_WBMP: imagewbmp($im); break;    case IMG_XPM: imagexbm($im); break;}imagedestroy($wm);imagedestroy($im);unlink($tempfile);

Page 67: PHP Without PHP—IPC

<?php

$watermark = '3129080702_c4e76f71d7_o.png';$dead_url = 'http://example.com/dead_image.png'; // {{{ start_image($filename, &$data)/*** Creates a gd handle for a valid file* @param $filename string the file to get* @param $data array the imagesize* @return resource GD handle*/function start_image($filename, &$data) {    $data = @getimagesize($filename);    if (empty($data)) { return null; }    $data['ratio'] = $data[0]/$data[1];    switch($data[2]) {        case IMG_GIF: return imagecreatefromgif($filename);        case 3: //problem where IMG_PNG is not bound correctly for my install        case IMG_PNG: return imagecreatefrompng($filename);        case IMG_JPG: return imagecreatefromjpeg($filename);        case IMG_WBMP: return imagecreatefromwbmp($filename);        case IMG_XPM: return imagecreatefromxbm($filename);    }    return null;}   // }}}$requestimg = $_SERVER['REDIRECT_URL'];if (!$_SERVER['QUERY_STRING']) {    // redirect user to invalid image    tag_http::redirect($dead_url);    return '';}// grab image to temp {{{$ch = curl_init($_SERVER['QUERY_STRING']);$tempfile = tempnam('/tmp', 'prod_remote_');$fp = f_open($tempfile, 'w'); //again delete the "_"curl_setopt($ch, CURLOPT_FILE, $fp);curl_setopt($ch, CURLOPT_HEADER, 0);curl_exec_($ch); //delete the final "_"curl_close($ch);fclose($fp);// }}}// configure image and dimensions {{{$size_data = array();$im = start_image($tempfile, $size_data);if (!$im) {    unlink($tempfile);    tag_http::redirect($dead_url);    return;}// }}}// get watermark information {{{$wm_data = array();$wm = start_image($watermark, $wm_data);if (!$wm) {    unlink ($tempfile);    tag_http::redirect($dead_url);    return;}// }}}// add watermark {{{if ($size_data['ratio']> $wm_data['ratio']) {    // image is wider format than the watermark    $new_smaller_dim = $wm_data[0] * ($size_data[1]/$wm_data[1]);    $dst_x = ($size_data[0] - $new_smaller_dim)/2;    $dst_y = 0;    $dst_w = $new_smaller_dim;    $dst_h = $size_data[1];} else {    // image is taller format than the watermark    $new_smaller_dim = $wm_data[1] * ($size_data[0]/$wm_data[0]);    $dst_x = 0;    $dst_y = ($size_data[1] - $new_smaller_dim)/2;    $dst_w = $size_data[0];    $dst_h = $new_smaller_dim;;}imagecopyresized($im, $wm, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $wm_data[0], $wm_data[1]);header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));header(sprintf('Content-type: %s',$size_data['mime']));// }}}switch ($size_data[2]) {    case IMG_GIF: imagegif($im); break;    case 3: case IMG_PNG: imagepng($im); break;    case IMG_JPG: imagejpeg($im); break;    case IMG_WBMP: imagewbmp($im); break;    case IMG_XPM: imagexbm($im); break;}imagedestroy($wm);imagedestroy($im);unlink($tempfile);

Page 68: PHP Without PHP—IPC

Beyond Funky Caching

Page 69: PHP Without PHP—IPC

San FranciscoLooking around you for

inspiration