Archive for the Category 'php'

Kohana book for Coda

Kohana Book for Coda

This is book number two for Coda. NOM is currently working on a project built with Kohana, a framework originally based on CodeIgniter.

Their marketing copy reads something like this:

Kohana is a PHP 5 FRAMEWORK that uses the MODEL VIEW CONTROLLER architectural pattern. It aims to be SECURE, LIGHTWEIGHT, and EASY to use.

This book cover is much simpler than the one i produced for Subversion here. I quickly came to realize that there’s no point at all in spending the time to make such a complicated image.

Book Title: Kohana
URL: http://docs.kohanaphp.com/
Simple cover: KohanaBook.png
Use for Mode: PHP-HTML
Search URL: http://docs.kohanaphp.com/?do=search&id=*

completely suppressing errors in php

This is something that's been bugging me for awhile, and I never really bothered to dig in and see what I could do to work around it, until now.

unserializing an unserializable string

The easiest, and most popular way to check if a string is serialized is simple.

PHP:
  1. /**
  2. * Is a string serialized?
  3. *
  4. * @param string
  5. * @return boolean  
  6. */
  7. function isSerialized($str)
  8. {
  9.     if ($str === 0)
  10.     {
  11.         return false;
  12.     }
  13.     else
  14.     {
  15.         return ($str == serialize(false) || @unserialize($str) !== false);
  16.     }
  17. }

Quite a few very popular frameworks and apps do it this way, try to just simply pass the string to the unserialize method, make sure it isn't the boolean false, and prepend the method with an @ to suppress notice-level error output. Don't get me wrong, it works. But if you're logging your notice-level errors, then any time you're trying to check if a string is serialized in this way, it logs the notice that's generated. Storing data as a serialized hash in a key-value database (Tokyo Cabinet — which we've chosen to use for Nomcat, BerkeleyDB, CouchDB, Redis, etc.) magnifies the scenario and takes this wee-little_old Notice, and makes your logs fill up really fast. Since error logs are for tracking issues that a developer should really concern themselves with, logging all of these notices just wouldn't do, it's simply a waste of space and processing time to handle them over and over and over again.

As we've been building Nomcat over at NOM, we're often faced with dozens of reads from the data storage layer with each view that's generated, and recently while testing, we've run into log files that look something like this.

CODE:
  1. ERROR - 2009-06-04 01:49:15 --> Severity: Notice  --> unserialize(): Error at offset 0 of 1 bytes /path/to/application/libraries/App_Model.php 432
  2. ... a couple hundred lines ...
  3. ERROR - 2009-06-04 01:51:19 --> Severity: Notice  --> unserialize(): Error at offset 0 of 1 bytes /path/to/application/libraries/App_Model.php 432

just set_error_handler to an empty method

Initially I tried a few different options to work around this annoying little problem.

  1. Prepending the unserialize method with @ to suppress output, but it doesn't prevent logging.
  2. Wrapping in a try-catch block doesn't do the trick
  3. Wrapping it with error_reporting(0) and error_reporting(2) doesn't do the trick either
  4. But creating an method to handle the error, have it to nothing, and wrapping the unserialize line with set_error_handler and restore_error_handler does the trick!

This is what I came up with.

PHP:
  1. /**
  2. * Is a string serialized?
  3. *
  4. * @param string
  5. * @return boolean  
  6. */
  7. function isSerialized($str)
  8. {
  9.     if ($str === 0)
  10.     {
  11.         return false;
  12.     }
  13.     else
  14.     {
  15.         set_error_handler(array('App_Model','unserialize_handler'));
  16.         $return = ($str == serialize(false) || @unserialize($str) !== false);
  17.         restore_error_handler();
  18.         return $return;
  19.     }
  20. }
  21.  
  22. /**
  23. * dummy error handler set up to obsorb any errors thrown by isSerialized
  24. * @return
  25. * @param object $errno
  26. * @param object $errstr
  27. */
  28. function unserialize_handler($errno, $errstr)
  29. {
  30.    // don't do anything
  31. }

If you noticed that I'm passing an array like this: set_error_handler(array('App_Model','unserialize_handler'));, you've got a good eye. This is how you can specify in which class to find the method you want to use as a callback, neither $this->methodname or Classname::methodname will work. However if you aren't writing object oriented code, you can simply pass the name of the method you want to use to handle the error as a string like this: set_error_handler('unserialize_handler');.

Let me know how it works for you.

Outer-glow effect with PHP and the GD library

I was recently working on a photo gallery project for a friend who is an avid Flickr user. She had an established workflow when it came to making her work available to her friends and clients on Flickr and didn't want to change that workflow if she didn't have to.

Ok, now it's time to skip ahead. I built the side using the Flickr API, and everything is working swimmingly. I decided to hire my friend Matthew Armendariz to handle the interface design. Since the client was a friend of mine, having someone else be responsible for the creative would keep me free from having to worry about that process, and Matt is a pretty good designer.

It took no time for Matt to whip up a few comps, the one we ended up going with had a slight outer-glow around each photograph, and since we were working with seemingly fixed output from Flickr, I figured, no worries, I'll just create two "glowing" background images, and display one or the other depending on whether the current photo was portrait or landscape.

It worked like a charm... until I came across a few photographs that the client had uploaded with non-standard aspect ratios. Then I had the realization that these outer glows needed to be dynamically generated. Since as the developer there wasn't any way that I could trust that she upload files of any specific aspect ratio, and since she was using Flickr to manage her photos I couldn't (and wouldn't want to anyway) enforce any specific sizes uploaded, I needed to come up with a an easy, browser agnostic, and friendly solution.

CSS wasn't going to help me. SVG and Canvas isn't broadly enough supported. And since this site was pretty much Javascript free, I had to look to the server to help me execute the agreed upon creative work

Oh my GD!

The GD library is an often overlooked alternative to ImageMagick, but since it's light weight, comes with most PHP installs, and was already available on the production server, it seemed like the best choice.

First I had to start with making sure that the file I was generating was going to identify itself properly

PHP:
  1. header ("Content-type: image/png");

Next was to pull in the parameters i was going to need to generate the correct size image... I decided to go with a 22px "border", which is really just the size of the glow.

PHP:
  1. $border = ($_REQUEST['b'])? $_REQUEST['b'] : 22;
  2. $width = ($_REQUEST['w']) ? $_REQUEST['w']+($border*2): 500;
  3. $height = (isset($_REQUEST['h'])) ? $_REQUEST['h']+($border*2): 500;

Next we create the image, using the specified or default dimensions. And then define the colors (in RGB) that will be used to generate the image... white and light gray.

PHP:
  1. $im = @imagecreatetruecolor($width, $height)
  2.       or die("Cannot Initialize new GD image stream");
  3. $white = imagecolorallocate($im, 255, 255, 255);
  4. $gray= imagecolorallocate($im,200,200,200);

Now it's time to create our initial shape... First the image is painted entirely white, and then a box is drawn inside of the white image with the gray color.

PHP:
  1. imagefill($im, 0, 0, $white);
  2. imagefilledrectangle($im, $border, $border, $width-$border, $height-$border,$gray);

Now there's just a grey box with a white border... not only is it boring, but it's not glowing at all. It's time to fix this. GD has a few decent filters built in, just as any image library should, and the ones that I chose to use for this were IMG_FILTER_SMOOTH and IMG_FILTER_GAUSSIAN_BLUR. The gaussian blur filter, unlike the one you find in PhotoShop, does not unfortunately accept parameters, so instead I had to put calls to GD's imagefilter() method in a for loop. The loop allowed me to also easily play around with the number of times and in what order each filter was applied to the image without having to do too much cutting and pasting.

PHP:
  1. for($i = 0; $i <10; $i++){
  2.     imagefilter($im,IMG_FILTER_SMOOTH, 0);
  3.     imagefilter($im,IMG_FILTER_GAUSSIAN_BLUR);
  4.     imagefilter($im,IMG_FILTER_GAUSSIAN_BLUR);
  5. }

Now we just generate the image as a png, and then clear the memory

PHP:
  1. imagepng($im);
  2. imagedestroy($im);

And that's all there is too it. Since the default size specified is 500px square, the default output looks like this. If I need to generate an outer–glow for an image that's 250px tall by 400px wide, I add the following query to the URI of the file blur.php?h=250&w=400 and voila! Of course caching the output of this file on the server will speed up any requests after the initial one, but that is beyond the scope of this post.

I've included the source of the file below.

PHP:
  1. <?php
  2. header ("Content-type: image/png");
  3. $border = ($_REQUEST['b'])? $_REQUEST['b'] : 22;
  4. $width = ($_REQUEST['w']) ? $_REQUEST['w']+($border*2): 500;
  5. $height = (isset($_REQUEST['h'])) ? $_REQUEST['h']+($border*2): 500;
  6. $im = @imagecreatetruecolor($width, $height)
  7.       or die("Cannot Initialize new GD image stream");
  8. $white = imagecolorallocate($im, 255, 255, 255);
  9. $gray= imagecolorallocate($im,200,200,200);
  10. imagefill($im, 0, 0, $white);
  11. imagefilledrectangle($im, $border, $border, $width-$border, $height-$border,$gray);
  12. for($i = 0; $i <10; $i++){
  13.     imagefilter($im,IMG_FILTER_SMOOTH, 0);
  14.     imagefilter($im,IMG_FILTER_GAUSSIAN_BLUR);
  15.     imagefilter($im,IMG_FILTER_GAUSSIAN_BLUR);
  16. }
  17. imagepng($im);
  18. imagedestroy($im);
  19. ?>

working with a googleAPIKey and subdomain of localhost

Though all googleAPIKeys work when you run your code at http://localhost or http://localhost/any/sub/directory/, I ran into a bit of a problem with my development server's key once I tried running the site we're developing at http://projectname.localhost/.

It turns out, that Google wanted me to register for an API key for my localhost subdomain.

Now by adding this else if everything is working swimmingly.

PHP:
  1. if ($_SERVER["HTTP_HOST"] == "projectname.dev.naterkane.com"){ //for development server
  2. $googleAPIKey = "ABQIAAAAXDA3g3QE28o3DpCEOJaK7RRbiuQmYjiTrMm7iJcFkjKKtES62BTJwMA8r_9--PPf1lirxSLFF7AjoA";
  3. } else if ($_SERVER["HTTP_HOST"] = "projectname.localhost"){ //for local development subdomain
  4. $googleAPIKey = "ABQIAAAAXDA3g3QE28o3DpCEOJaK7RQd8-PxSvU34sqHMt5i1yPetZP44hRjKyK727DILgg9wBKEDitvz4a0tg";
  5. } else { //catchall for "localhost" and default production domain
  6. $googleAPIKey = "ABQIAAAAzIcwHNZqp-D2TJm3qjeWyxQjCl-yVJ0Kz7eVNz89X4I7MZtKDxSog71ziTBuu1ICptxfQLN7rq9Xag";
  7. }

Still adding support for Collections in Flickr

I updated my post about pulling Collections info from a Flickr account. I started to originally post about it a month ago, but had completely forgot as the idea got abandoned from one of my projects. For those who are curious you can find the update here: http://www.naterkane.com/blog/2007/12/01/adding-support-for-collections-in-the-flickr-api/

Similar Posts

Categories

Archives

About

Nater Kane is freelance developer and user experience & technology consultant based in Brooklyn, NY.

Nater's focus is on creating a semantic and accessible web, and having delighted clients with happy customers.

He likes to spend time playing with his cats, playing drums, working on his diesel vw rabbit and his motorcycle, and enjoying a decent espresso.

RSS

Twitter » What I'm Up To

How I'm Social

Basecamp

Meta


Nater Kane naterkane personal http://www.naterkane.com LinkedIn Profile Web Technologist personal nater@naterkane.com 1978-09-12 voice 845.234.6698 | fax 707.922.0593
964 Flushing Ave. Brooklyn, NY 11206