PHP Without PHP—Automattic

5,183 views
5,090 views

Published on

Take a simple PHP trick and follow it on a huge tangent to the philosophy of good web architecture.

Presentation given as Flash Talk at Automattic Meetup in Seaside on September 2010

Presentation originally a long form, but in the spirit of things, I have cut it down.

Automattic is the company I work for. The company is distributed worldwide and once a year we gather at a remote location and meet face-to-face. This year, all the employees are taking a little time during the meetup to compose and give at least one presentation for each other, talking about any subject we are passionate about.

This is based on <a>a PHP Advent article I wrote almost two years ago</a> and formed a low key presentation. I thought it’d be nice to give a more “traditional” PHP talk at the meetup—but one which I felt the audience at large could relate to.

I hope you enjoy it.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,183
On SlideShare
0
From Embeds
0
Number of Embeds
308
Actions
Shares
0
Downloads
26
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

PHP Without PHP—Automattic

  1. 1. PHP without PHP A Philosophy for Good Architecture terry chay 2010-09-12T18:00-0500 WordCamp Meetup Seaside, Florida
  2. 2. Funky Caching Prologue #1
  3. 3. aka ErrorDocument trick Smarter Caching … Rasmus’s Trick (Stig’s trick) Go into apache.conf (or .htaccess) and ErrorDocument 404 /error.php
  4. 4. Error.PHP $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 it if (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=404 header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL'])); //Show the file echo $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 hilighter fputs($fp, $data); fclose($fp); @link($basepath.$filepath, $tmpfile); //suppress errors due to losing race unlink($tmpfile);
  5. 5. Error.PHP $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 it if (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=404 header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL'])); //Show the file echo $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 hilighter fputs($fp, $data); fclose($fp); @link($basepath.$filepath, $tmpfile); //suppress errors due to losing race unlink($tmpfile);
  6. 6. Error.PHP $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 it if (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=404 header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL'])); //Show the file echo $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 hilighter fputs($fp, $data); fclose($fp); @link($basepath.$filepath, $tmpfile); //suppress errors due to losing race unlink($tmpfile);
  7. 7. PHP without PHP
  8. 8. Engineer and Architect
  9. 9. 1 Fallingwater organic, democratic, plasticity, continuity
  10. 10. …including me
  11. 11. Hatchway Staircase View at the main (living room) level, from the bridge (from east)
  12. 12. Beyond the glass Fallingwater: Living room terraces and glass walls (from east).
  13. 13. Fall Foliage View from lookout, downstream.
  14. 14. Fall Foliage View from lookout, downstream.
  15. 15. No barriers Detail: corner window at the guest house, from southeast.
  16. 16. Existing tree The trellis over the driveway is built to accommodate a tree.
  17. 17. Local quarry Living room, west (downstream) side, from southeast
  18. 18. Existing boulder Living room fireplace and hearth, looking from kitchen door to south windows
  19. 19. Philosophy organic, democratic, plasticity, continuity.
  20. 20. Why on PHP?
  21. 21. Harmony with Environment Apache web server: ErrorDocument Customer-centric: Performance paramount Relational Database: Slow persistence Harmony with PHP itself…
  22. 22. Architecture of PHP Modern web architecture
  23. 23. Architecture of PHP Modern web architecture
  24. 24. 2 Bellefield Towers Design Hubris
  25. 25. Gothic Romanesque architecture The current Bellefield Church (two blocks away)
  26. 26. Other city towers Allegheny Courthouse Main Tower & Four Tower Types at Jail (and other towers)
  27. 27. Tower of Learning Within spitting distance of Bellefield Towers
  28. 28. Carnegie Library Most iconic moment in baseball history
  29. 29. Why is Bellefield Towers so Ugly?
  30. 30. Design Hubris? 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? Choosing Frameworks over Applications (Like WordPress)?
  31. 31. Solutions Consider Environment
  32. 32. 3 Golden Gate Bridge The Design Pattern
  33. 33. the other bridge
  34. 34. Same problem, different pattern Original design was hybrid cantilever-suspension. Replaced by purse suspension
  35. 35. Art Deco Bridge Tower, Lighting, pedestrial walkway
  36. 36. International Orange Rust colored like the environment it lives in … and safe.
  37. 37. Part of the whole
  38. 38. Design Patterns Defined “Each pattern describes a problem which occurs over and over again in our environment, and then 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.”
  39. 39. Certainly iconic Me in front of both icons
  40. 40. Never the same way twice How do you know which one? How do you know which way?
  41. 41. Funky Caching again “search for the closest matching valid URL and redirect, and use attempted url text as a DB keyword lookup” —Rasmus Lerdorf
  42. 42. Javascript and CSS compiling & caching
  43. 43. <?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); // }}}
  44. 44. <?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); // }}}
  45. 45. <?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); // }}}
  46. 46. <?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); // }}}
  47. 47. // 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);
  48. 48. // 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);
  49. 49. // 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);
  50. 50. Beyond Funky Caching
  51. 51. San Francisco Looking around you for inspiration
  52. 52. Thanks!

×