Category Archives: Technology

Linux Crontab helpful hints

*    *    *    *    *  command to be executed
┬    ┬    ┬    ┬    ┬
│    │    │    │    │
│    │    │    │    │
│    │    │    │    └───── day of week (0 - 6) (Sunday=0 )
│    │    │    └────────── month (1 - 12)
│    │    └─────────────── day of month (1 - 31)
│    └──────────────────── hour (0 - 23)
└───────────────────────── min (0 - 59)

Calculating memory used by PHP to generate that page

Do you know how much memory those loops are using ?
Why is this page taking so long to load ?
Well with this simple PHP code you can daily benchmark different versions of your script to use the least possible amount of Memory.

< ?php echo "Memory Usage: ". (function_exists('memory_get_usage') ? round(memory_get_usage()/1024/1024, 2) : 'Unknown') .'MB'."\n"; ?>

An example of this can be seen by visiting the Precision Badges New Zealand site, and viewing the page source, right down the bottom.

PHP Framework – Day 1

Start of simple, start off clean.

I am going to assume a few things in these posts,
PHP 5.2 or above. ( 5.3 is better )
mySQL is our database of choice.
You understand the basics of setting up a virtual host/development area, and setting up your database.

Setting up your index file.

The ‘index.php’ is going to handle all requests. We will define the necessary contacts and then call out bootstrap file which starts and loads all of our needed classes.

from there, we load our bootstrap file that loads all needed classes.

The Core::Router() function does the routing.
The router function will check based on the 1st and 2nd segment to see if a matching view exists and then parse that view in to the main template file.

Download the source files and have a look trough, I have commented most functions, Follow trough from the index file and follow the includes.

There is no use of the database or sessions yet so just drop this on your web server and run it.

[download id="12"]

Beginners Guide to PHP Happiness.

Lately I have been seeing some nastiness being taught to a group of Junior web developers.
It comprises of maxing all sorts of nasty combinations of mixing your PHP, HTML, classes, queries and stand alone functions into an unorganised pile of mess.

Developing any project, simple of complex in this manor will very quickly become a nightmare, to me, and more so to those student developers.

I am going to put together a series of quick and simple posts to make a clean, simple and effective PHP based framework to act as a learning step for these students.

Webkit custom scroll bars

Webkit browsers such as Safari and Chrome support some superb CSS3 styling.
They are ( even thought I use firefox as my primary browser ) the most advanced browsers.

For a while now I have created custom scroll bars using a Javascript library called Mootools, other libraries such as jQuery and Prototype can do this too, but here is one easy way to do it with CSS alone;

here is the simple code, if you know CSS it will be self explanatory, else I have added some commenting

/* were a webkit browser, lets style our scroll bar */
@media screen and (-webkit-min-device-pixel-ratio:0) {

	html{
		/* hide overall scrolling */
		overflow: auto;
	}
	body {
		/* absolute position our 'body' and allow for the width of the scroll bar */
		position: absolute;
		left: 0;
		top: 0;
		right: 10px;
		bottom: 0;
		padding-right: 10px;
		overflow-x: auto;
		overflow-y:scroll;
	}


	::-webkit-scrollbar {
		/* set the width of the scroll bar */
		width: 10px;
	}

	::-webkit-scrollbar-button:start:decrement, 
	::-webkit-scrollbar-button:end:increment {
		/* hide the arrows */
		display: block;
		height: 10px;
	}

	::-webkit-scrollbar-track-piece {
		/* set the style/colour of the scroll bar background */
		background: 
		-webkit-gradient(
			linear, 
			0 0, 
			100% 0, 
			from(rgba(0,0,0,0.2)), 
			to(rgba(0,0,0,0.12))
		);
		-webkit-box-shadow: 0 1px 0 0 rgba(255,255,255,0.35);
		-webkit-border-radius: 5px;
	}

	::-webkit-scrollbar-thumb:vertical{
		/* this is the acutal scrooll bar, set the colours here to match your site */
		/* I have used grey's (#464646 & #383838 & #cccccc) */
		background: 
		-webkit-gradient(
			linear, 
			0 0, 
			100% 0, 
			from(#464646),
			to(#383838)
			);
			-webkit-border-radius: 6px;
			border: 3px solid #cccccc;
			-webkit-background-clip: padding-box;
		}
		::-webkit-scrollbar-track-piece:horizontal{
			background: none;
			-webkit-box-shadow:none;
		}
		::-webkit-scrollbar:horizontal{
			height: 16px;
		}
		::-webkit-scrollbar-thumb:horizontal{
			height: 12px;
			-webkit-border-radius:12px;
			background: 
			-webkit-gradient(
				linear, 
				0 0, 
				0 100%, 
				from(rgba(0,0,0,0.1)), 
				to(rgba(0,0,0,0.25))
			);
			border: 6px solid transparent;
			-webkit-background-clip: padding-box;
			
		}
	}
}

Mootools Gallery ZoomBox Plugin

I needed a simple lightweight Mootools Gallery Lightbox, and after a few googles, I found nothing that suited my needs with out all the extra ‘captions’ and grouping and bloat.

This is a simple zoom from start position type lightbox that uses only the Mootools Core version 1.2.4 at this time but should work with 1.3.x

I have used it on the Glass Effects web page which you can view for a demo.

You will notice on my class, I am adding a CSS class ‘shadow’ to the large image, this is used for basic styling and you can do any CSS you want to it. ( or none at all )

Here is how it is built up;

HTML:

< div id="photos">
	< ul>
		< li>< a href="http://www.glasseffects.co.nz/assets/volume1/2_large.jpg" class="zoomBox" title="Glass Effects - Painted toi toi image on glass splashback">< img src="http://www.glasseffects.co.nz/assets/volume1/2_small.jpg" alt="Glass Effects - Painted toi toi image on glass splashback" />< /a>< /li>
		< li>< a href="http://www.glasseffects.co.nz/assets/volume1/3_large.jpg" class="zoomBox" title="Glass Effects - Uniformed lines on Effects glass splashback">< img src="http://www.glasseffects.co.nz/assets/volume1/3_small.jpg" alt="Glass Effects - Uniformed lines on Effects glass splashback" />< /a>< /li>
		< li>< a href="http://www.glasseffects.co.nz/assets/volume1/5_large.jpg" class="zoomBox" title="Glass Effects - Textured Effect splashback using GlassArt colour #25 Iridium">< img src="http://www.glasseffects.co.nz/assets/volume1/5_small.jpg" alt="Glass Effects - Textured Effect splashback using GlassArt colour #25 Iridium" />< /a>< li>
		< li>< a href="http://www.glasseffects.co.nz/assets/volume1/6_large.jpg" class="zoomBox" title="Glass Effects - Stencilled Effect – toi toi. GJ Gardner Show Home, Tauranga">< img src="http://www.glasseffects.co.nz/assets/volume1/6_small.jpg" alt="Glass Effects - Stencilled Effect – toi toi. GJ Gardner Show Home, Tauranga" />< /a>< /li>
		< li>< a href="http://www.glasseffects.co.nz/assets/volume1/7_large.jpg" class="zoomBox" title="Glass Effects - Painted glass for bar. GlassArt colour #49 Red Red Red">< img src="http://www.glasseffects.co.nz/assets/volume1/7_small.jpg" alt="Glass Effects - Painted glass for bar. GlassArt colour #49 Red Red Red" />< /a>< /li>
	< /ul>
< /div>

JS ( In Page ):


window.addEvent('domready', function() {

	/* Any other JS needed for your page */
	
	var myZoomBox = new zoomBox();


	/* to set options */
	
	var myZoomBox = new zoomBox({
		zb_class:     '.mootools-ftw',
		zb_element:   'big_image',
		zb_loader:    './loading.gif'
	});

});

ZoomBox Class:

// Create the Mootools ZoomBox Class
var zoomBox = new Class({
	
	Implements : Options,
	// Editable Settings
    options: {
		zb_class:     '.zoomBox',                    // class of anchors/images to find on page.
		zb_element:   'zb_image',                    // id of zppmBox pop-up div
		zb_loader:    '/assets/images/loading.gif',  // path to loading image
		scale_image:  true,                          // scale large image if it is bigger than our screen size, bool true/false
		win_width:    1024,                          // basic window width, ignore
		win_height:   768                            // basic window height, ignore
    },

	initialize: function(options){
		// set options and internal settings
		this.setOptions(options);
		this.setWindowSize();
		this.currentIndex;
		this.images = new Array();
		this.positions = new Array();
		
		// create our loading image
		this.zb_loading = new Element('img', { 
			'id'    : 'zb_loading', 
			'src'   : this.options.zb_loader,
			'styles': { 
				'position': 'absolute',
				'display' : 'none',
				'left'    : 0,
				'top'     : 0
			}
		}).inject(document.body, 'bottom');

		// scan page for our class.
		this.thumbs = $$(this.options.zb_class);
		
		var self = this;
		
		// attach each image.
		this.thumbs.each(function(zb, index) {
			self.attach(zb, index);
		});
		
		// add event listener if the user resizes their window to scale max size of images.
		window.addEvent('resize', self.setWindowSize.bindWithEvent(this));
		
	},
	
	
	// attach out image and add event listeners.
	attach: function(zb, index) {
		var self     = this;
		// is we manually attach a new element this is needed.
		if(index == undefined) {
			index = (self.length + 1);
		}
		// set our basic width/heights.
		var zb_fx;
		var zb_src   = zb.get('href');
		var zb_org   = zb.getElements('img')[0];
		self.positions[index] = {};
		self.positions[index].zb_left = zb_org.getPosition().x;
		self.positions[index].zb_top  = zb_org.getPosition().y;
		// add out click event.
		zb.addEvent('click', function(clk) {
			new Event(clk).stop();
			// no point opening it, if its already open !
			if(!document.id(self.options.zb_element) || !document.id(self.options.zb_element).get('src').match(zb.get('href'))) {
				// add out loading gif to the image about to be opened.
				self.zb_loading.setStyles({
					'display' : '',
					'top'     : self.positions[index].zb_top,
					'left'    : self.positions[index].zb_left
				});
				// if we have one open, let it be gone
				if(document.id(self.options.zb_element)) {
					self.close(self.currentIndex);
				}
				// set current index.
				self.currentIndex = index;
				// create and place on top of the thumbnail. but keep it hidden.
				self.images[index] = new Element('img', { 
					'id'    : self.options.zb_element, 
					'src'   : zb_src,
					'styles': { 
						'position': 'absolute',
						'opacity' : 0,
						'left'    : self.positions[index].zb_left,
						'top'     : self.positions[index].zb_top
					}
				})
				.addClass('shadow') // we don't need this. but its basic styling for large image.
				.inject(document.body, 'bottom') // inject at teh bottom of our page.
				.addEvent('click', function(clk) {
					// bind out close even on clicking the new large image
					new Event(clk).stop();
					self.close(index);
				})
				// bind a load event so once the large image has loaded, we open it.
				.addEvent('load', function() {
					// get our large image size
					var zb_width  = self.images[index].getWidth();
					var zb_height = self.images[index].getHeight();
					// see if we need to scale it, so the image fits on screen.
					if(self.options.scale_image) {
						if(self.options.win_width < zb_width) {
							zb_width  = (self.options.win_width - 50);
							zb_height = (zb_width / zb_height) * zb_width;
						} 
						if(self.options.win_height < zb_height) {
							zb_height = Math.floor(self.options.win_height - 50);
							zb_width  = Math.floor((zb_height / zb_width) * zb_height);
						}
					}
					// set the imahe the size of the thumbnail
					self.images[index].setStyles({
						'width'   : zb_org.getWidth(),
						'height'  : zb_org.getHeight(),
						'cursor'  : 'pointer'
					});
					// hide teh loading gif/indicator 
					self.zb_loading.setStyle('display', 'none');
					// animate it BIG ! and center it on the screen
					var zb_fx = new Fx.Morph(self.images[index]).start({
						'top'     : ((self.options.win_height / 2) - (zb_height / 2)) + window.getScroll().y,
						'left'    : ((self.options.win_width / 2) - (zb_width / 2)),
						'width'   : zb_width,
						'height'  : zb_height,
						'opacity' : 1
					});
				});
			} else {
				// we have used it before, lets load it up.
				self.images[index].fireEvent('load');
			}
			// bind the 'escape' key to close the current image.
			window.addEvent('keyup', function(key) {
				if(key.code == 27) {
					self.close(index);
				} 
			});
		});
	},
	
	close: function(index) {
		var self = this;
		var zb_fx = new Fx.Morph(self.images[index], { 
			onComplete: function() {
				document.id(self.options.zb_element)
					.fade(0)
					.dispose();
			} 
		}).start({
			'top'     : self.positions[index].zb_top,
			'left'    : self.positions[index].zb_left,
			'width'   : 100,
			'height'  : 100,
			'opacity' : 0
		});
		window.removeEvents('keyup');
	},
	
	setWindowSize: function() {
		
		this.options.win_width = window.getWidth();
		this.options.win_height = window.getHeight();
		
	}
	
});

Download the Full Script:
[download id="11"]

Update for Sheldon.Lendrum Search Rank checker

I have made an update to my search rank checker for http://sheldon.lendrum.co.nz to paginate the results. With over 4500 records, the list was getting a bit long.

I have paginated it by rank’s rather than equal pages.

Check it out – http://sheldon.lendrum.co.nz/search-rank-for-sheldonlendrumconz/,

Use PHP to find your mobile browser

I needed a quick way to include different files based on the if the visitor to a site is on a mobile device or a regular browser/computer.

Every browser has a user agent depending on the operating system, browser and system.

below are some common use agents, they can be found by echoing the server variable HTTP_USER_AGENT

< ?php echo $_SERVER['HTTP_USER_AGENT']; ?>

FireFox

Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7

Safari Mac

Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-en) AppleWebKit/523.10.3 (KHTML, like Gecko) Version/3.0.4 Safari/523.10 

Safari Windows

Mozilla/5.0 (Windows; U; Windows NT 6.0; en) AppleWebKit/522.13.1 (KHTML, like Gecko) Version/3.0.2 Safari/522.13.1 

Nexus One

Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD56C) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17

Apple iPhone

Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3

Apple iPod Touch

Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A100a Safari/419.3 

Internet Explorer

Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.2; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)

PHP mobileAgent() Function

Here is my function, is it simple PHP function, is expects one paramerter, and array or expected user agents, but by leaving it blank, the function will use the default user agents.

Update: I have added more mobile user agents for older Android models, Blackberrry’s and the iPhone simulator. .

< ?php
	function mobileAgent($custom_agents = array()) {

		$agents = array_merge($custom_agents, array(
			'iphone',           // Apple iPhone
			'ipod',             // Apple iPod touch
			'aspen',            // iPhone simulator
			'nexus',            // Nexus One Android
			'dream',            // Pre 1.5 Android
			'android',          // 1.5+ Android
			'cupcake',          // 1.5+ Android
			'blackberry9500',   // Storm
			'blackberry9530',   // Storm
			'opera mini',       // Opera mobile
			'webos',            //  Nokia Browser
			'incognito',        // Other iPhone browser
			'webmate'           // Other iPhone browser
		));
		$user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
		foreach($agents as $agent) if(strpos($user_agent, $agent)) return TRUE;
		return FALSE;

	}
?>

Usage

	< ?php if(mobileAgent()): ?>
	
	
	< ?php else: ?>
	
	< ?php endif; ?>