related links

   Bluekora

   Linkedin

   Facebook

   Chris Shiflett Blog

   CSS-Tricks

Coffee!!
Drag Me!

Welcome!

I’m a 23 year old lad from Portugal, Vila Nova de Gaia.
I’m a Software Engineer working, at the moment, at bluekora.
I can be found on LinkedIn at my profile.

August 03 2011

PHP Cropimage Script (memcache and APC support)

Tagged Under : , , , , , , , , , ,

Hello!

 

This script will enable you to automaticaly resize images without loosing quality.
It uses a simple math formulas to calculate the desired final size and then rerenders the image.

The usage is very simples. On you HTML code just create an image and replace the src with:

cropimage.php?src=img/myimage.jpg&size=320×240

src – the source of the image itself
size – the size that the image should have. If the size is not directly compatible with the original size it will display a simple background and the image with the correct size on top.

Example: cropimage.php?src=img/myimage.jpg&size=320×240

If it’s a square image you can just use myimage.jpg&size=320 and it will make a 320×320 image.

If you don’t want that nasty name (I wouldn’t :P ) you can add a rewite rule on your htaccess file:

RewriteRule ^images\/crop\/([^/]+)\/([^/]+)\/(.+)$ cropimage.php?src=$3&size=$2&id=$1&rewrite=1 [L,QSA]

With this rule you can use something like: http://www.example.com/images/crop/1234/320×180/my-awesome-image.png

Now on the script itself you need to do some adjustments on line “$_GET['src'] = ‘img/’.$_GET['id'].’/’.$_GET['src'];” where you point the image name to the respective folder.

If you want the original size just call it like this:

http://www.example.com/images/crop/1234/original/my-awesome-image.png

Note: using an ID is very important since it will prevent image overwriting.

 

Using with memcache:

This script works great with memcache and apc, and it’s highly recommended!
For that just set “define(“USE_MEMCACHE”, true);” to true (as it is on this example).

Using with APC:

This script works great with memcache and apc, and it’s highly recommended!
For that just set “define(“USE_APC”, true);” to true (as it is on this example).

 

Watermark

This script also supports a watermark.
If you want to have a go with the watermark just set “define(“USE_WATERMARK”, false);” to true and set the path to the watermark in “define(“WATERMARK”,”);”.

 

Fork me @ http://bit.ly/odG98h

 

Examples

You can see it in action here: http://www.porvocacao.com
In this website we’re using this script in memcache mode.

Let me know your thoughts :)

June 29 2010

WP-RESTful WordPress Plugin

Tagged Under : , , , , , ,

Hello!

I’m 99% sure that you already heard about APIs or REST APIs, it’s what Twitter, flickr and a lot more companies use to share they’re resources with a consumer.
A consumer can be anything from a website (for example, showing your Twitter updates on your blog or personal website) to a desktop / mobile application (iPhone, Android, Windows Mobile, …).
This is possible because all information sent to and from the API is encoded in either two common, inter-platform language, XML and JSON.
The difference between a regular API and a REST API is on the way they work. A REST API requires two entities to work, a client and a server.

Download WP-RESTful (Version 0.1)

Download WP-RESTful Users Plugin (Version 0.1)

Download WP-RESTful Categories Plugin (Version 0.1)

Download WP-RESTful Tags Plugin (Version 0.1)

Follow me for real-time updates

Twitter

How does it work?

WP-RESTful uses OAuth, a widely, commonly and open source API implementation used all over the World (Wide Web).
The way it work is fairly simple.

First a Consumer registers with a Server. At this point the Server will provide the Consumer with 2 tokens, a public and a private token. The public token will be used to communicate and identify the Consumer with the Server while the private token will be stored locally for security and integrity reasons.
After this the Consumer will request the Server with a Request Token. This Request Token will be used to initiate the Authentication Protocol in where the Consumer will be required to authorize the Server.
The Server will create 2 new token (definitive tokens). They will be our authentication tokens.

I know this sounds and seems complicated but you won’t need to do anything as the Plugin will do almost everything for you (Registration and Authentication process are manual).

Plugin features

  • Add new Plugins to API Plugin to extend functionalities to any way you want/need. (See next group)
  • Fully manageable Client and Server side.
  • Ability to choose what fields are allowed to be returned to the consumer.
  • Ability to restrict modules to OAuth authentication process or liberated them and make them open.
  • Load balance system where you can specify how many requests a given consumer is allowed in a 60 minute timeframe.
  • Out of the box Post and Comments management.
  • And much more…

Plugins

As stated on “Plugin Features” you have the ability to develop and/or add new modules to your REST API. This means, for example, if you use a plugin like WP E-Commerce, you can develop a plugin for the REST API in order to provide support for WP E-Commerce resources.
The way these plugins are developed is very similar to how plugins for WordPress are developed.
You can see this video that explains how plugins work and how you can develop them.

Requirements?

All requirements for the plugin to work properly are addressed by the plugin itself, upon activation. You can see your system status on WP-RESTful link after activation the plugin.

How to install?

This plugin is installed like any other WordPress plugin out there.

  1. First you need to download it from WordPress Plugin Repository.
  2. Upload the contents of the compacted file to your plugin folder on your WordPress installation.
  3. Go to your WordPress Administration page and activate the Plugin (Plugins → Installed → WP-RESTful → Activate)
  4. Create a new page, name it API, set the permalink to /api and set the content as [REST_return] and save the page.
  5. Go to WP-RESTful → WP-RESTful to check your system status.

I need help!

Check these two videos. They will help you starting up.

This post will be updated, if needed, to reflect changes made to the plugin.

May 17 2010

WordPress Plugin – Parallel Loading System

Tagged Under : , , , , , , ,

Hello!

The WP-PLS (short for Parallel Loading System) is a WordPress plugin that will enhance the loading efficiency of your Blog. It’s very simple to use and it will only require a small amount of time to configure at the start.

Download from WordPress Plugin Repository (Updated to version 0.1.8)

Follow me for real-time updates

Twitter

Why use it?

If you have an image intensive Blog, or even if you don’t, this plugin will boost the loading time of your Blog. The more images you have the more it will improve.

The amount of people that will visit your website for the first time or visit with an empty cache or disabled cache is huge, therefore, the best your website performs on that first visit the more chances that person will remain to view your website.

It is also known that nowadays, Google (and other search engines), are taking into account, for ranking purposes, your website page speed. Google Bot does not conserve a cache when it visits your website, so, the faster your website loads the more chances you have to rank higher.

This plug will not change anything on your Blog. Every change that it makes will be processed in real time, right before the HTML code of your Blog is sent to the browser.

How does it work?

Standard HTTP v1.1 requests only allow 2 connections, at the same time, from the same domain.

This plugin will virtualize connections, through defined subdomains. You can have as many subdomains as you like, but I do recomend using a maximum of 5.

WP-PLS Comparison

Requirements?

The plugin is programmed to be aware of this requirements, and if not fulfilled it will not change anything on your Blog.
It will not break your Blog code!

  • Your server needs to have a working GD Library module for PHP.
  • You should have a PHP installation with a minimum version of 5.1.3
  • Access to your server Administration Painel (cPanel, DirectAdmin, Plesk) in order to create new sub-domains for your domain.
    Lets say your domain is wp-pls.com. You will need to create domains like
    image1.wp-pls.com
    image2.wp-pls.com

How to install?

This plugin is installed like any other WordPress plugin out there.

  1. First you need to download it from WordPress Plugin Repository.
  2. Upload the contents of the compacted file to your plugin folder on your WordPress installation.
  3. Go to your WordPress Administration page and activate the Plugin (Plugins → Installed → WP-PLS → Activate)
  4. Go to Settings → Parallel Loading System

Plugin features?

Some of the features that you can expect when using this plugin:

  • Automatic Image Optimization.
  • Parallelize HTTP connections.
  • Page speed improvement.
  • Auto-Path find (Automatically find server root path, sub-domain path, plugin resources path…).
  • Cache loss minimization.
  • Sub-domain real-time health tracking.
  • Auto recovery from resource files bad sync.
  • Ability to activate / deactivate sub-domains
  • Plugin Updates aware. (automatically re-sync files and database after an update)

What’s in the cooking pan?

This was only the first release of the plugin. I’ve got a lot of new ideas that I would like to see implemented on next releases.
Some of them are:

  • Also parallelize CSS and JavaScript loading.
  • Add support to also load external images. At the moment it will only load locally stored images.
  • Add real-time rewrite functions to CSS and JavaScript. That way, images that have been called from the CSS file will also be parallelized.
  • Overall improve of the code.
  • Add options to manage image quality rendering.
  • Bug fixes (when found or reported).
  • And much more…

If you have any features that you would like to see implemented, please don’t hesitate to comment this post, tweet me or mail me :)

I need help!

It’s normal if you run into problems and I’m here to tell you how to fix them.

If for any reason the plugin is telling you that it doesn’t have permissions to alter a given file you will need to access your server, using your favorite FTP Client (Filezilla, Cyberduck, FlashFXP…) and change the permissions of the file to 777. You can revert them back to 644 (normal permissions of a file) after the plugin finishes the modifications.

If you get a sub-domain health notification stating that your sub-domain is returning a 500 HTTP error code the most probable explanation is that your sub-domain folder has 777 permissions. Revert them back to 755 and you should be fine.

If you have any further questions please don’t hesitate to send me an email or add a comment on this post.

Creating sub-domains on cPanel?

Creating sub-domains on Plesk?

  1. Log in to Plesk
  2. Once logged in, click the ‘Home’ button in the left navigation frame.
  3. Click on the domain name you wish to create a subdomain for.
  4. Click on the ‘Subdomains’ button. This will take you to the subdomain manager.
  5. Add a new subdomain by clicking the corresponding button (Add New Subdomain).
  6. Enter the subdomain in the associated field. The SSL support checkbox is optional, and should be used if you intend on using SSL with your subdomain.
  7. If you’d like to use the same FTP information as your main domain to access the subdomain, skip down to the ‘Services’ section. If not, select the checkbox ‘Create a separate FTP user account for this subdomain’. Enter an FTP username and password, along with a hard disk quota. If you do not enter a hard disk quota, the subdomain will be allowed to use all resources included with your main domain.
  8. In the ‘Services’ section, it is advised to check all services. This will ensure that your subdomain can support all the features our hosting accounts offer.
  9. Click the ‘OK’ button to create the subdomain.

Creating sub-domains on DirectAdmin?

Creating sub-domains on manually on your server?

To create a sub-domain, if don’t use a Control Panel, edit your http.conf file (normally located on /etc/http/conf/http.conf) and add the following at the end:

NameVirtualHost *:443

<VirtualHost *:80>
ServerName YOUR SUBDOMAIN
DocumentRoot ROOT TO SUBDOMAIN PATH
ErrorLog ROOT TO SUBDOMAIN LOG
</VirtualHost>

<VirtualHost *:443>
ServerName YOUR SUBDOMAIN
DocumentRoot ROOT TO SUBDOMAIN PATH (SSL)
ErrorLog ROOT TO SUBDOMAIN LOG (SSL)
</VirtualHost>

This post will be updated, if needed, to reflect changes made to the plugin.

March 30 2010

WP e-commerce SKU on variations

Tagged Under : , , , , ,

UPDATE – 22/02/2011

Files for the 3.7.8 version of wp-e-commerce. I have provided only the altered files and full plugin if you just want to replace it.
DON’T FORGET TO BACKUP FIRST!!

Download → http://bit.ly/3-7-8-SKU

UPDATE – 01/09/2010

If you need additions that are not contemplated in this fix package you can email me for a specific quote.

UPDATE – 18/05/2010

There has been an update on wp-e-commerce a few days ago and if you have applied my add-on you’ll probably have problems with the plugin. Post a comment or email me if you’re having problems.

===============================

If you are using wp-ecommerce plugin for wordpress and you ran into some missing functionalities this might help you.

The specific mod I’ll show you today will enable you to specify SKU to any variation on any product on your system.

I don’t know how proficient your are on programming WordPress, but let me know if you run into any difficulty.

So, first of all you need to add a new field on your database on table wp_wpsc_variations_properties called “sku”. I added this field as varchar with a length of 64 characters, but do adapt this one to fit your needs.

Backup your e-commerce plugin folder.

DOWNLOAD 3.7.8 FILES HERE

This should get you up and running. Let me know if you need anything.

August 03 2009

Screencast 1 – mod_rewrite and PHP

Tagged Under : , , ,

Screencast – mod_rewrite and PHP from José Airosa on Vimeo.

Hello folks!

This time, and for the first time, I bring you a screencast! It’s all about mod_rewrite and PHP. What it is, how can we use it and how can we integrate it to be used with PHP.

Below are the functions that i talked about in the screencast. Use them, or not, as you please.

/**
 * Get current page URL
 * 
 * @return string with paeg name
 */
function curPageURL() {
	$pageURL = 'http';
	if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
		$pageURL .= "://";
		if ($_SERVER["SERVER_PORT"] != "80") {
			$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
		} else {
			$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
	}
	return $pageURL;
}
 
/**
 * Get current page script name
 * 
 * @return string with page script name
 */
function curPageScriptName() {
 return substr($_SERVER["SCRIPT_NAME"],strrpos($_SERVER["SCRIPT_NAME"],"/")+1);
}
 
/**
 * Get current page name
 * 
 * @return string with page script name
 */
function curPageName() {
 return end(explode("/",curPageURL()));
}

Hope you’ll enjoy as much as I did making it :)

Let me know your feedback.

July 21 2009

Image Scale&Crop with Cache support in PHP

Image Scale&Crop with Cache support in PHP

Hello fellow readers!

Sorry for not posting anything for so long, but my work has been taking me most of my time… anyway.

Today we’ll go over on creating a PHP Script that will resize and crop (if wanted) an image with the added support of cache.

PHP is not limited to creating just HTML output. It can also be used to create and manipulate image files in a variety of different image formats, including GIF, PNG, JPEG, WBMP, and XPM. Even more convenient, PHP can output image streams directly to a browser. You will need to compile PHP with the GD library of image functions for this to work. GD and PHP may also require other libraries, depending on which image formats you want to work with.

You can use the image functions in PHP to get the size of JPEG, GIF, PNG, SWF, TIFF and JPEG2000 images.

For this to work you’ll need a PHP 4.3.0 version or greater. Check http://www.libgd.org/ for more information.

This script will work in stages.

  • Stage 1: Read the image and check if it is present on our cache folder. If so we’ll just use the cached version. Take in account that even if you supply an image on an external source it will not check the image itself but rather the link, thus, no external connection is made.
  • Stage 2: Start reading the source image and do the required operations of cropping and scaling.
  • Stage 3: Apply the changes and create image resource (new one).
  • Stage 4: Save image in cache and return the new image.

Ok, enough with all this “mumbo jumbo” an lets get to action:

<?php
/**
 * Created and developed by José P. Airosa
 * 
 * This file will enable you to automaticaly resize images without loosing quality.
 * It uses a simple math formulas to calculate the desired final size and then rerenders the image.
 * 
 * The usage is very simples. On you HTML code just create an image and replace the src with cropimage.php?src=img/myimage.jpg&size=320x240
 * 
 * src - the source of the image itself
 * size - the size that the image should have. If the size is not directly compatible with the original size it will display a simple background and the image with
 * the correct size on top.
 * 
 * Example: <img src="cropimage.php?src=img/myimage.jpg&size=320x240" alt="" />
 * 
 * If it's a square image you can just use myimage.jpg&size=320 and it will make a 320x320 image.
 * 
 */
ini_set ( "memory_limit", "64M" );
class cropImage {
	// Initialize variables;
	var $imgSrc, $myImage, $cropHeight, $cropWidth, $x, $y, $thumb, $dif;
	/**
	 * Stage 2: Read the image and check if it is present on our cache folder. If so we'll just use the cached version. Take in account that even if you supply 
	 * an image on an external source it will not check the image itself but rather the link, thus, no external connection is made.
	 * 
	 * Also check what type of file we're working with. Different files, different methods.
	 * 
	 * @param $image The image that it's to crop&scale
	 * @return nothing
	 */
	function setImage($image) {
 
		// Your Image
		$this->imgSrc = $image;
		// Getting the image dimensions
		list ( $width, $height ) = getimagesize ( $this->imgSrc );
		// Check what file we're working with
		if ($this->getExtension ( $this->imgSrc ) == 'png') {
			//create image png
			$this->myImage = imagecreatefrompng ( $this->imgSrc ) or die ( "Error: Cannot find image!" );
			imagealphablending ( $this->myImage, true ); // setting alpha blending on
			imagesavealpha ( $this->myImage, true ); // save alphablending setting (important)
		} elseif ($this->getExtension ( $this->imgSrc ) == 'jpg' || $this->getExtension ( $this->imgSrc ) == 'jpeg' || $this->getExtension ( $this->imgSrc ) == 'jpe') {
			//create image jpeg
			$this->myImage = imagecreatefromjpeg ( $this->imgSrc ) or die ( "Error: Cannot find image!" );
		}
 
		// Find biggest length
		if ($width > $height)
			$biggestSide = $width;
		else
			$biggestSide = $height;
 
		// This will zoom in to 50% zoom (crop!)
		$cropPercent = .5; 
		// Get the size that you submitted for resize on the URL
		$both_sizes = explode ( "x", $_GET ['size'] );
		// Check if it was submited something like 50x50 and not only 50 (wich is also supported)
		if (count ( $both_sizes ) == 2) {
			if ($width > $height) {
				// Apply the cropping formula
				$this->cropHeight = $biggestSide * round ( ($both_sizes [1] * $cropPercent) / $both_sizes [0], 2 );
				$this->cropWidth = $biggestSide * $cropPercent;
			} else {
				// Apply the cropping formula
				$this->cropHeight = $biggestSide * $cropPercent;
				$this->cropWidth = $biggestSide * round ( ($both_sizes [0] * $cropPercent) / $both_sizes [1], 2 );
			}
		} else {
			$this->cropHeight = $biggestSide * $cropPercent;
			$this->cropWidth = $biggestSide * $cropPercent;
		}
 
 
		// Getting the top left coordinate
		$this->x = ($width - $this->cropWidth) / 2;
		$this->y = ($height - $this->cropHeight) / 2;
 
	}
	/**
	 * From a file get the extension
	 * 
	 * @param $filename The filename
	 * @return string file extension
	 */
	function getExtension($filename) {
		return $ext = strtolower ( array_pop ( explode ( '.', $filename ) ) );
	}
	/**
	 * For PNG files (and possibly GIF) add transparency filter
	 * 
	 * @param $new_image
	 * @param $image_source
	 * @return nothing
	 */
	function setTransparency($new_image, $image_source) {
		$transparencyIndex = imagecolortransparent ( $image_source );
		$transparencyColor = array ('red' => 255, 'green' => 255, 'blue' => 255 );
 
		if ($transparencyIndex >= 0) {
			$transparencyColor = imagecolorsforindex ( $image_source, $transparencyIndex );
		}
 
		$transparencyIndex = imagecolorallocate ( $new_image, $transparencyColor ['red'], $transparencyColor ['green'], $transparencyColor ['blue'] );
		imagefill ( $new_image, 0, 0, $transparencyIndex );
		imagecolortransparent ( $new_image, $transparencyIndex );
	}
	/**
	 * Stage 3: Apply the changes and create image resource (new one).
	 * 
	 * @return nothing
	 */
	function createThumb() {
		$thumbSizex = $thumbSizey = $_GET ['size'];
		$both_sizes = explode ( "x", $_GET ['size'] );
		if (count ( $both_sizes ) == 2) {
			$thumbSizex = $both_sizes [0];
			$thumbSizey = $both_sizes [1];
		}
 
		$this->thumb = imagecreatetruecolor ( $thumbSizex, $thumbSizey );
        $bg = imagecolorallocate ( $this->thumb, 255, 255, 255 );
        imagefill ( $this->thumb, 0, 0, $bg );
		imagecopyresampled ( $this->thumb, $this->myImage, 0, 0, $this->x, $this->y, $thumbSizex, $thumbSizey, $this->cropWidth, $this->cropHeight );
		if ($this->getExtension ( $this->imgSrc ) == 'png' && isset ( $_GET ['transparent'] ) && $_GET ['transparent'] == 1) {
			$this->setTransparency ( $this->thumb, $this->myImage );
		}
	}
	/**
	 * Stage 4: Save image in cache and return the new image.
	 * 
	 * @return nothing
	 */
	function renderImage() {
		$image_created = "";
		global $size_string;
		if ($this->getExtension ( $this->imgSrc ) == 'png') {
			header ( 'Content-type: image/png' );
			imagepng ( $this->thumb );
			/**
			 * Save image to the cache folder
			 */
			imagepng($this->thumb, 'img_cache/'.$size_string.end(explode("/",$this->imgSrc))); 
		} elseif ($this->getExtension ( $this->imgSrc ) == 'jpg' || $this->getExtension ( $this->imgSrc ) == 'jpeg' || $this->getExtension ( $this->imgSrc ) == 'jpe') {
			header ( 'Content-type: image/jpeg' );
			imagejpeg ( $this->thumb );
			/**
			 * Save image to the cache folder
			 */
			imagejpeg($this->thumb,'img_cache/'.$size_string.end(explode("/",$this->imgSrc))); 
		}
		imagedestroy ( $this->thumb );
	}
}
// Some variables needed for this to work. We set $size_string as global in order to access it on renderImage()
global $size_string;
// Initialize our Crop Image class
$image = new cropImage ( );
$size_string = "";
$both_sizes = explode ( "x", $_GET ['size'] );
if (count ( $both_sizes ) == 2) {
	$size_string = $both_sizes [0]."x".$both_sizes [1];
} else {
	$size_string = $_GET ['size']."x".$_GET ['size'];
}
/**
 * Atempt to load our cached image. If we can't that means there is no cache for that image. If we find 
 * we'll just load that one adn won't even think about cropping and scaling.
 * 
 * Stage 1: Read the image and check if it is present on our cache folder. If so we’ll just use the cached version. 
 * Take in account that even if you supply an image on an external source it will not check the image itself but rather the link, thus, no external connection is made.
 */
$img_cached = 'img_cache/'.$size_string.end(explode("/",$_GET ['src']));
if(file_exists($img_cached)) {
	if ($image->getExtension ( $img_cached ) == 'png') {
		$myImage = imagecreatefrompng ( $img_cached ) or die ( "Error: Cannot find image!" );
		header ( 'Content-type: image/png' );
		imagepng ( $myImage );
	} elseif ($image->getExtension ( $img_cached ) == 'jpg' || $image->getExtension ( $img_cached ) == 'jpeg' || $image->getExtension ( $img_cached ) == 'jpe') {
		$myImage = imagecreatefromjpeg ( $img_cached ) or die ( "Error: Cannot find image!" );
		header ( 'Content-type: image/jpeg' );
		imagejpeg ( $myImage );
	}
	imagedestroy ( $myImage );
} else {
	$image->setImage ( $_GET ['src'] );
	$image->createThumb ();
	$image->renderImage ();
}
?>

All the code is commented and I think anyone will understand it pretty well.

A few things to take it into account. There should be a folder called “img_cache” with write permissions otherwise cache won’t work.

While loading external files is normal for the image to take a few seconds to appear. That’s only on the first time you access it. Next times it will just load the cached version directly.

That’s about it. Really simple script.. oh yeh, i’ve only added support for jpg and png, but i think that from the code I’ve given you can easily add support for the others. But if someone requires and is not able to do it, please do ask me and I’ll do it :)

Hope you enjoy!

July 09 2009

Create a simple TagCloud in PHP

Create a simple TagCloud in PHP

Ok, as for my first post after my away time I’ll be showing you how to make a… Yes you figured it out, a TagCloud.

A TagCloud is as you know a Cloud… with Tags… hum, for some reason I think you already knew that. Anyway, jokes aside, a TagCloud is one of the most powerful visual information display nowadays. It’s not a complex module, by the opposite, it’s very simple.

A normal TagCloud displays all tags, in alphabetic order and the font size varies in according to the amount of times that tag has been found in use. Imagine that you have “hello”, “this”, “is”, “jose”,”blog” as your tags. You would get something like:

hello this is jose blog

You would know that “jose” is the tag with most views (when we say views we can say records in a database).

The installation of the module is very easy and all the required information can be found on the files that i provide.

Extra info:

// This will create a TagCloud with default max font size and minimum font size. The default values can be set on file tagcloud.php in function create_tag_cloud($array,$limit_top_size = 38,$limit_low_size = 18)
$tag_size = create_tag_cloud($tags_array);

Or with specific values

$tag_size = create_tag_cloud($tags_array,40,10);

Max font size will be 40 and minimum font size 10. (these are the max and min values allowed for TagCloud font fluctuation.

And there you go. Just style the code as you like.

PS: Yes, i know what you’re thinking, you can change the code as you please :)

Let me know if you have any issues.

February 10 2009

A good way to create Logs in PHP

Tagged Under : ,

A good way to create Logs in PHP

Hello everyone :)

Today we’re gonna go over Logging in PHP as nested Class.

With the introduction of PHP5 we now get the opportunity to use PHP as an Object Oriented Programming Language. What this means is, and in a very short way, that we can now have a more reliable, faster and safer way to program in PHP.

OO programming brings abstraction, encapsulation, inheritance, and polymorphism so, therefore, PHP also does.

  • Abstraction – Allows the programmer to declare abstract methods that can be instantiated in a class and declared by an object.
  • Encapsulation – Gives us the ability to protect which ever data, inside a class, by using protected methods like private classes ou functions.
  • Inheritance – We can now create tree like class structure where the lower levels on the tree are childes of the level above. (in this Logging example we’re going to be using this methodology)
  • Polymorphism – Using this feature we’re able to declare a given class and use his children methods even tho we have declared parent class without the need to redeclare them.

First of all we’re going to go over the basic structure of our Log class.

1
2
3
4
interface iLogs
{
 public function insereLog($entrada,$tipo); 
}

We declared an interface. This way the application that will be calling this class is able to read its available content without the need to directly access the class internally.

Note: Methods that are declared on the interface need to be equal to the ones declared inside the class itself (either method name or number of arguments required). Otherwise you’ll get a fatal error from PHP.

Next step takes us to declaration of the class itself.

1
2
3
4
5
6
7
class Logs implements iLogs
{
 const VERBOSE = false;
 // Max size for log compression -> 1MB
 private static $max_size = 1024000;
 // Folder in your root where the logs will be stored
 private static $cwd = 'logs/';

As you can see, we’re telling class Logs that it should implement interface iLogs that we previously declared.

Every class needs a constructor and a destructor. Basically what should and should not be done when we initialize the class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 public function __construct() {
  if (!defined('LOG_FILE_ADMIN')){
   define('LOG_FILE_ADMIN','logAdmin.log');
  }
  if (!defined('LOG_FILE_CLIENTES')){
   define('LOG_FILE_CLIENTES','logClientes.log');
  }
  if (!defined('LOG_FILE_WEBSERVICES')){
   define('LOG_FILE_WEBSERVICES','logWebServices.log');
  }
  self::preparaDirectorias();
  self::preparaLogs();
 }
 public function __destruct() {
 
 }

__construct and __destruct use “__” since they are native to PHP5 and are automatically called when a class is instantiated.

When the class is built we want to create some constants used throughout the class and we want to check if everything is according to the file structure required.
We also use self to address the actual instantiated class and :: in place of -> because we’ll be calling them in static mode (no data can be changed).

Our destruct class is empty since there is nothing to be done when the class is destroyed.

Note: Normally you can use this function for a DB connection and destruct can close the connection.

1
2
3
4
5
6
7
8
9
10
11
 private function preparaDirectorias() {
  chdir('./');
  if(!is_dir("logs")) {
   if(!mkdir('logs'))
    throw new Exception ("It was no possible to create 'logs' dir"); 
  }
  if(!is_dir(self::$cwd."logs_arquivo")) {
   if(!mkdir(self::$cwd.'logs_arquivo'))
    throw new Exception ("It was no possible to create 'logs_arquivo' dir");
  }
 }

We attempt to check if folder structure is properly created, if not we create it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 private function preparaLogs() {
  if (!file_exists(self::$cwd.LOG_FILE_ADMIN)) { 
   if(!fopen(self::$cwd.LOG_FILE_ADMIN , 'w'))
    throw new Exception("It was not possible to create '".LOG_FILE_ADMIN );
  } 
  if(filesize(self::$cwd.LOG_FILE_ADMIN) > self::$max_size) {
   self::compressbz2(LOG_FILE_ADMIN);
   unlink(self::$cwd.LOG_FILE_ADMIN);
   if(!fopen(self::$cwd.LOG_FILE_ADMIN , 'w'))
    throw new Exception("It was not possible to create '".LOG_FILE_ADMIN );
  }
  if (!file_exists(self::$cwd.LOG_FILE_CLIENTES )) { 
   if(!fopen(self::$cwd.LOG_FILE_CLIENTES , 'w'))
    throw new Exception("It was not possible to create '".LOG_FILE_CLIENTES );
  }
  if(filesize(self::$cwd.LOG_FILE_CLIENTES) > self::$max_size) {
   self::compressbz2(LOG_FILE_CLIENTES);
   unlink(self::$cwd.LOG_FILE_CLIENTES);
   if(!fopen(self::$cwd.LOG_FILE_CLIENTES , 'w'))
    throw new Exception("It was not possible to create '".LOG_FILE_CLIENTES );
  }
  if (!file_exists(self::$cwd.LOG_FILE_WEBSERVICES)) { 
   if(!fopen(self::$cwd.LOG_FILE_WEBSERVICES, 'w'))
    throw new Exception("It was not possible to create '".LOG_FILE_WEBSERVICES);
  }
  if(filesize(self::$cwd.LOG_FILE_WEBSERVICES) > self::$max_size) {
   self::compressbz2(LOG_FILE_WEBSERVICES);
   unlink(self::$cwd.LOG_FILE_WEBSERVICES);
   if(!fopen(self::$cwd.LOG_FILE_WEBSERVICES, 'w'))
    throw new Exception("It was not possible to create '".LOG_FILE_WEBSERVICES);
  }
 }

We’re going to check the size of our logs. If they exceed $max_size then we compress them and create a new and fresh log file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 private function compressbz2($file_name) {
  $file_pointer = fopen(self::$cwd.$file_name, "r");
  //Opens the file in readonly,
  //Check for permissions
  $file_read = fread($file_pointer, filesize(self::$cwd.$file_name));
  //Reads the content
  fclose($file_pointer);
  //Closes the file
  $actual = date("-Ymd-His");
  $filename = $file_name.$actual.".bz2";
  //Opens compression file for writing purpose
  $bz = bzopen(self::$cwd.'logs_arquivo/'.$filename, "w");
  //Writes the file
  bzwrite($bz, $file_read);
  //Closes the file
  bzclose($bz);
 }

A simple function for compressing files. I will not go into a lot of detail on this section. If you find it to be useful please contact me and I’ll make a post about file compression.

And finally we’re going to create the method that we call when using this class to add a log.

Note: As you probably noticed (or not :P ) all other methods (except construct and destruct) are private and therefore can only be called from within the class itself.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 public function insereLog($entrada,$tipo) {
  if($tipo == 1) {
   $fp = fopen(self::$cwd.LOG_FILE_ADMIN , 'a+');
   if(!$fp)
    throw new Exception("It was not possible to create '".LOG_FILE_ADMIN );
   else {
    fwrite($fp,'['.date("Y/m/d - H:i:s").'] '.$entrada."\n");
    if(self::DEBUG)
     echo $entrada."\n";
   }
  }
  elseif($tipo == 2) {
   $fp = fopen(self::$cwd.LOG_FILE_CLIENTES , 'a+');
   if(!$fp)
    throw new Exception("It was not possible to create '".LOG_FILE_CLIENTES );
   else {
    fwrite($fp,'['.date("Y/m/d - H:i:s").'] '.$entrada."\n");
    if(self::DEBUG)
     echo $entrada."\n";
   }
  }
  elseif($tipo == 3) {
   $fp = fopen(self::$cwd.LOG_FILE_WEBSERVICES , 'a+');
   if(!$fp)
    throw new Exception("It was not possible to create '".LOG_FILE_WEBSERVICES );
   else {
    fwrite($fp,'['.date("Y/m/d - H:i:s").'] '.$entrada."\n");
    if(self::DEBUG)
     echo $entrada."\n";
   }
  }
  fclose($fp);
 }

This logging class supports logs for 3 different types of systems; frontoffice (clients), backoffice (administrations) and webservices.

The way you call this function can be done in different ways, in this case, I’ll go over the Inheritance feature we talked before.

Imagine you have a class, lets say, foo

1
2
3
4
5
6
class foo {
 public function hello() {
  // I bet you never seen this before!!! hehe ^_^
  echo 'Hello World';
 }
}

What we can do is…

1
2
3
4
5
6
7
8
9
10
//Logs.class.php is your Log class we just did
require_once 'Logs.class.php';
 
class foo extends Logs {
 public function hello() {
  // I bet you never seen this before!!! hehe ^_^
  echo 'Hello World';
  Logs::insereLog("Mom, I think i just said Hello World. Log it please, thank you!",1);
 }
}

And voila, there you go :) your very own log system out of the box.

Feel free to report me any mistakes, suggestions or doubts you might have.

Have fun and be != be# {‘run remotly’ && Get['4_free'];}


scarletbits.com 125x125 Are My Sites Up? Get Chitika Premium Job Board for Web Designers and Web Developers

Tag Cloud