How to identify your clients` browser type

Posted by Dan Sosedoff on October 02, 2009

Some time ago i wrote a simple regex patterns to determine whether my client crawler bot, mobile client or just regular one. Easy to expand and to use.

function is_mobile($agent) {
    $pattern = '/(blackberry|motorokr|motorola|sony|windows ce|240x320|176x220|palm|mobile|iphone|ipod|symbian|nokia|samsung|midp)/i';
    return (bool)preg_match($pattern, $agent);
}
 
function is_crawler($agent) {
    pattern = '/(google|yahoo|baidu|bot|webalta|ia_archiver)/';
    return (bool)preg_match($pattern, $agent);
}

Simple php url routing controller 1

Posted by Dan Sosedoff on July 04, 2009

!!! CONSIDER THIS AS AN UPDATE:Rails-like PHP Url Router

Here is simple url parser, that produces output parameters lile: controller, action, parameters. Also, it support simple virtual key rules, “rails” style.

For example, url like “http://foo.bar/book/view/12″ will produce parameters: controller = book, action = view, id = 12.

Here is php code:

<?
 
/* ------------------------------------------------------------- */
/* URL Router class */
/* ------------------------------------------------------------- */
 
class Router {
  static protected $instance;
  static protected $controller;
  static protected $action;
  static protected $params;
  static protected $rules;
 
  public static function getInstance() {
    if (isset(self::$instance) and (self::$instance instanceof self)) {
      return self::$instance;
    } else {
      self::$instance = new self();
      return self::$instance;
    }
  }
 
  private static function arrayClean($array) {
    foreach($array as $key => $value) {
      if (strlen($value) == 0) unset($array[$key]);
    }  
  }
 
  private static function ruleMatch($rule, $data) {    
    $ruleItems = explode('/',$rule); self::arrayClean(&$ruleItems);
    $dataItems = explode('/',$data); self::arrayClean(&$dataItems);
 
    if (count($ruleItems) == count($dataItems)) {
      $result = array();
 
      foreach($ruleItems as $ruleKey => $ruleValue) {
        if (preg_match('/^:[\w]{1,}$/',$ruleValue)) {
          $ruleValue = substr($ruleValue,1);
          $result[$ruleValue] = $dataItems[$ruleKey];
        }
        else {
          if (strcmp($ruleValue,$dataItems[$ruleKey]) != 0) {
            return false;
          }
        }
      }
 
      if (count($result) > 0) return $result;
      unset($result);
    }
    return false;
  }
 
  private static function defaultRoutes($url) {
    // process default routes
    $items = explode('/',$url);
 
    // remove empty blocks
    foreach($items as $key => $value) {
      if (strlen($value) == 0) unset($items[$key]);
    }
 
    // extract data
    if (count($items)) {
      self::$controller = array_shift($items);
      self::$action = array_shift($items);
      self::$params = $items;
    }
  }
 
  protected function __construct() {
    self::$rules = array();
  }
 
  public static function init() {
    $url = $_SERVER['REQUEST_URI'];
    $isCustom = false;
 
    if (count(self::$rules)) {
      foreach(self::$rules as $ruleKey => $ruleData) {
        $params = self::ruleMatch($ruleKey,$url);
        if ($params) {          
          self::$controller = $ruleData['controller'];
          self::$action = $ruleData['action'];
          self::$params = $params;
          $isCustom = true;
          break;
        }
      }
    }
 
    if (!$isCustom) self::defaultRoutes($url);
 
    if (!strlen(self::$controller)) self::$controller = 'home';
    if (!strlen(self::$action)) self::$action = 'index';
  }
 
  public static function addRule($rule, $target) {
    self::$rules[$rule] = $target;
  }
 
 
  public static function getController() { return self::$controller; }
  public static function getAction() { return self::$action; }
  public static function getParams() { return self::$params; }
  public static function getParam($id) { return self::$params[$id]; }
}
?>

Basic usage:

$router = Router::getInstance(); // init router
$router->addRule('/books/:id/:keyname',array('controller' => 'books', 'action' => 'view')); // add simple rule
// add some more rules
$router->init(); // execute router

So, as you can see, the router class can be accessible from anywhere in your code. Just because the class has beed designed as one-instance object, you cannot call for new instance. To get instance of router you need to call Router::getInstance() instead.
We have added simple rule for url`s like this ‘/books/12345/this-is-a-book-keyname’. Default routing system will identify this url incorrectly (controller => books, action => 12345). So the action 12345 not exists. That`s why we need to add custom rule. It will parse this url correctly: controller => books, action => view. And the rest of parameters will be automatically added to parameteres array. To access this array you need to call $router->getParams(); If you need to get just one parameter, call directly: $var = $router->getParam(0).

This router is really simple and can be used in small web sites that not require complete framework. Also it is fast.

Download file Router.php
View paste

Scaling images with ImageMagick and PHP 1

Posted by Dan Sosedoff on March 20, 2009

Here is php version of ruby class that i made a long time ago. The same functionality and results.

<?
class ImageScale {
 
	private function changeGeometry($sz,$value) {
		if ($sz['width'] > $sz['height']) { // horizontal image
			$newsz['width'] = $value;
			$newsz['height'] = ceil(($newsz['width'] * $sz['height']) / $sz['width']);
		}
		else { // vertical image
			$newsz['height'] = $value;
			$newsz['width'] = ceil(($newsz['height'] * $sz['width']) / $sz['height']);
		}
		return $newsz;	
	}
 
	private function changeGeometry2($sz,$value) {
		$newsz['width'] = $value;
		$newsz['height'] = ceil(($newsz['width'] * $sz['height']) / $sz['width']);
		return $newsz;
	}
 
	/**
	 * 	Make thumbnail of specified maximum side size
	 */
	public function processThumb($source_path, $dest_path, $sidesize, $quality=85, $scale_method=1) {
		if (file_exists($source_path) && is_readable($source_path)) {
			$image = new Imagick($source_path);
 
			$geometry = $image->getImageGeometry(); // ['width', 'height']
			if ($geometry['width'] > $sidesize) {
				if ($scale_method == 1) $geometry = $this->changeGeometry($geometry,$sidesize);
				if ($scale_method == 2) $geometry = $this->changeGeometry2($geometry,$sidesize);
			}
			$image->cropThumbnailImage($geometry['width'],$geometry['height']);
			$image->setCompression(Imagick::COMPRESSION_JPEG);
			$image->setCompressionQuality($quality);
			return $image->writeImage($dest_path);
		}
		return false;
	}	
 
	/**
	 * 	Make square thumbnail
	 */
	public function processRectThumb($source_path, $dest_path, $size=150, $quality=85) {
		if (file_exists($source_path) && is_readable($source_path)) {
			$image = new Imagick($source_path);
 
			if ($image) {
				$image->cropThumbnailImage($size,$size);
				$image->setCompression(Imagick::COMPRESSION_JPEG);
				$image->setCompressionQuality($quality);
				return $image->writeImage($dest_path);
			}
		}
		return false;
	}
}
?>

Download file – http://files.sosedoff.com/1167c8db/