Databasic v1.10.2 Released

I have just released a new version of my MySQL database class, Databasic. This new version fixes a few issues with binds, MySQL functions and little bugs here and there. I have also added an "takes x seconds to execute the query" to every query in debug mode, no idea why I didn't add it before!

Update! There was a small bug in version 1.10.1 concerning the execute() method. I just patched it to 1.10.2, enjoy!

Download Databasic v1.10.2
View the complete change log

Custom PHP Functions: Datetime functions

All of these functions can be found within the Titon Utility library.

It is now time for my second post, in my series of "Basic/Common PHP functions that all programmers should know". The first series was about basic PHP strings and with this issue I am going to tackle 5 more functions for date and time. As always, I try to make my functions short but powerful, enjoy!

If you have any ideas for a series you want to see, or a type of function, be sure to send me an email using the contact page (in the footer), thanks!

Days Between

This function finds the difference in days between two dates. Each date must be a unix timestamp; if not my function will try to convert it to one. This could be modified to find the difference in weeks, seconds, etc.

/**
 * Finds difference in days between dates.
 * 
 * @param int $start
 * @param int $finish
 * @return int
 */
public function daysBetween($start, $finish) {
	if (!is_int($start))	$start = strtotime($start);
	if (!is_int($finish))	$finish = strtotime($finish);
	$diff = $finish - $start;
	$days = $diff / (24 * 3600);
	return round($days);
}
Get Age

This is a pretty simple function, in that it will find the persons age depending on the year given and the current year. The birth year could either be a string of '1988' (4 numeric characters) or the full date 1988-02-26.

/**
 * Gets the age of an individual.
 * 
 * @param int $timeStamp
 * @return int
 */
public function getAge($timeStamp) {
	$seconds = time() - strtotime($timeStamp);
	$year = 60 * 60 * 24 * 365;
	return floor($seconds / $year);
}
Get Date/Time in Timezones

Now this is something that could be done in many numerous ways, but mine simply takes the timezone difference (-8, 0, +6, etc) as the second argument, and then returns a unix timestamp. This function does not have any input checking (so make sure your arguments are correct before hand) and does not apply Daylight Savings Time.

/**
 * Gets a unix timestamp in certain timezones.
 * 
 * @param int $timeStamp
 * @param int $timeZone
 * @return int
 */
public function timeInZone($timeStamp, $timeZone = -8) {
	return strtotime(gmdate('Y-m-d h:i:sa', $timeStamp + (3600 * $timeZone)));
}
Date within a Timeframe

This function will take a date and check to see if it was within a certain date range and return a boolean value. My function will attempt to convert non unix timestamps to unix; be sure to pass the data correctly. Also you can leave the 3rd argument empty ($finish date) and the current time() will be used.

/**
 * Checks to see if a timestamp was within a timeframe.
 * 
 * @param int $check
 * @param int $start
 * @param int $finish
 * @return boolean
 */
public function withinTimeframe($check, $start, $finish = '') {
	if (!is_int($check))	$check = strtotime($check);
	if (!is_int($start))	$start = strtotime($start);
	if (empty($finish)) {
		$finish = time();
	} else {
		if (!is_int($finish)) $finish = strtotime($finish);
	}
	if ($check >= $start && $check <= $finish) {
		return true;
	}
	return false;
}
Breakdown a timestamp

Now this next function is quite different then the previous ones, but is pretty powerful. This function breaks down the timestamp to find how many days, weeks, months, etc there are until the current time (using time()). This type of function is good for doing text like: Last comment 5 days, 3 hours ago.

/**
 * Breaksdown a timestamp into an array of days, months, etc since the current time.
 * 
 * @param int $timeStamp
 * @return array
 */
public function timeBreakdown($timeStamp) {
	if (!is_int($timeStamp)) $timeStamp = strtotime($timeStamp);
	$currentTime = time();
	$periods = array(
		'years'         => 31556926,
		'months'        => 2629743,
		'weeks'         => 604800,
		'days'          => 86400,
		'hours'         => 3600,
		'minutes'       => 60,
		'seconds'       => 1
	);
	$durations = array(
		'years'         => 0,
		'months'        => 0,
		'weeks'         => 0,
		'days'          => 0,
		'hours'         => 0,
		'minutes'       => 0,
		'seconds'       => 0
	);
	if ($timeStamp) {
		$seconds = $currentTime - $timeStamp;
		if ($seconds <= 0){
			return $durations;
		}
		foreach ($periods as $period => $seconds_in_period) {
			if ($seconds >= $seconds_in_period) {
				$durations[$period] = floor($seconds / $seconds_in_period);
				$seconds -= $durations[$period] * $seconds_in_period;
			}
		}
	}
	return $durations;
}

And there you have it, 5 functions dealing with date and time. Stay tuned for the next issue! And again, if you have ideas for functions, send me an email!

My open-source scripts officially released!

So it has taken me nearly a year to get to this point. Over the past year I have been building some very advanced PHP classes and scripts that I wish to release as open-source. The types of scripts range from database handlers, template engines, form validation and cleaning, session management, CakePHP components and behaviors, so on and so forth. For the time being im releasing 3 scripts that I deemed "stable" and "complete". I hope you love them and get as much use out of them as I have. The following 3 scripts are now officially released to the public!

Databasic - A basic wrapper class for the MySQL database engine. Contains methods for connecting to a database, fetching and returning results, building insert and update queries, optimization and more.

Gears - A template engine that loads template files, binds variables to a single file or globally without the need for custom placeholders/variables, allows for parent-child hierarchy and parses the template structure.

Commentia - Commentia is a CakePHP Behavior that automatically runs after a comment is made. Each comment is tested upon a point system to determine and classify it. If a comment has more then 1 point it is automatically approved, if it has 0 points it continues pending, and if it is in the negative point range it is either marked as spam or deleted entirely.

Loading Models specific to certain actions

Recently I was working on a project, where a certain controller had over 15ish+ different models. The problem is that each action needed a different model, and I didn't want to load all those models at once. By using my common sense, loading that many models would put more of a strain on load time by having to initialize each model and bind them to the Controller. I needed a quick way to load a model(s) specific only to a certain action. At first I tried putting $this->user[] = array('Model'); at the top of each action, but that didn't work and it didn't initialize "before" the action like it is supposed to. So what I came up with is a little statement trick that you can place in your beforeFilter(), which will load models specific to certain actions. Enjoy!

/**
 * Executed before each action
 */
public function beforeFilter() {
	parent::beforeFilter();
	// Load action specific models
	switch ($this->params['action']) {
		case 'friends':		$models = array('Friend'); break;
		case 'messages':	$models = array('Message'); break;
		case 'blog':		$models = array('Entry', 'Comment'); break;
	}
	if (!empty($models)) {
		foreach ($models as $model) {
			$this->loadModel($model);
		}
	}
}

Also it would be best to disable models be default in controller. This way it doesn't load a certain model twice, or overwrite the defaults.

class TestController extends AppController {
	public $uses = null;
}

Custom PHP Functions: String functions

All of these functions can be found within the Titon Utility library.

It's now time for some PHP that isn't Cake related. This is the first part in a series of "Basic/Common PHP functions that all programmers should know". This series has to deal with manipulating strings. I try to make my functions short, sweet and powerful, and I hope you learn something from them.

Truncate

This function takes a long string and shortens it to a defined length and adds appends an ellipsis (or custom string) to the end. Instead of chopping a word in half (if the limit finished within it), it moves the pointer up to the previous space.

/**
 * Truncates a string to a certain length.
 * 
 * @param string $text
 * @param int $limit
 * @param string $ending
 * @return string
 */
public function truncate($text, $limit = 25, $ending = '...') {
	if (strlen($text) > $limit) {
		$text = strip_tags($text);
		$text = substr($text, 0, $limit);
		$text = substr($text, 0, -(strlen(strrchr($text, ' '))));
		$text = $text . $ending;
	}
	return $text;
}
Shorten

This function works similarly to truncate(), but instead of chopping off the end of the string, it chops out the middle. This is useful for shortening users long names or websites.

/**
 * If a string is too long, shorten it in the middle.
 * 
 * @param string $text
 * @param int $limit
 * @return string
 */
public function shorten($text, $limit = 25) {
	if (strlen($text) > $limit) {
		$pre = substr($text, 0, ($limit / 2));	
		$suf = substr($text, -($limit / 2));	
		$text = $pre .' ... '. $suf;
	}
	return $text;
}
Obfuscate

Now this function doesn't directly scramble the text and confuse the user, instead it scrambles the source code. This is useful for displaying emails or other strings that you don't want to show up directly in your source code.

/**
 * Scrambles the source of a string.
 * 
 * @param string $text
 * @return string
 */
public function obfuscate($text) {
	$length = strlen($text);
	$scrambled = '';
	for ($i = 0; $i < $length; ++$i) {
		$scrambled .= '&#' . ord(substr($text, $i, 1)) . ';';
	}
	return $scrambled;
}
Slugify

This function takes a string and makes it SEO and URL friendly (for example in the address bar for my blog posts). It lowercase's all words, replaces spaces with a dash, removes foreign/illegal characters and follows the guidelines for the best possible SEO. For example "Hello, my name is Miles Johnson!" would convert to "hello-my-name-is-miles-johnson".

/**
 * Rewrite strings to be URL/SEO friendly.
 *
 * @param string $text
 * @return string
 */
public function slugify($text) {
	$text = trim(strtolower($text));
	$text = str_replace(array('-', ' ', '&'), array('_', '-', 'and'), $text);
	$text = preg_replace('/[^a-zA-Z0-9\-_]/is', '', $text);
	$text = urlencode($text);
	return $text;
}
Listing

This final function takes an array of items and turns them into an ordered list with the last item having the word "and" in front of it instead of a comma. Very good for making lists.

/**
 * Creates a comma separated list with the last item having an "and".
 *
 * @param array $items
 * @param string $and
 * @return string
 */
public function listing($items, $and = 'and') {
	if (is_array($items)) {
		$lastItem = array_pop($items);
		$items = implode(', ', $items);
		$items = $items .' '. $and .' '. $lastItem;
	}
	return $items;
}

Now that's all I have for now, and I know you will use this in your code constantly just like I do! Be patient for my next series which will be dealing with basic date/time functions.

Underworld - Rise of the Lycans

I thought it would be time for something, non web related. A quick review (sort of) and my thoughts about Underworld - Rise of the Lycans. Enjoy!

This series has been one of my favorites I thoroughly enjoyed. Albeit this type of movie and genre are the types of movies that spark my interest and inner child. Me and my dad would rent these movies and watch them all the time (no idea why we haven't bought them yet, lol!). So I may seem a little bit bias towards the movie, and its predecessors, but I'm just a fan who enjoys it. It has many likenesses to Van Helsing, which is another favorite of mine.

Now I will agree that the previous two movies left a lot to be asked about the Lycan and Vampire history. You learned a little bit more with the second movie in that you find out who the original Lycan and Vampire are and where they came from. What you didn't know is the details behind the feud (vague references to Lucian and Sonya's love) and how they got to this point. With the Rise of the Lycans, set hundreds of years before the first, you learn everything you need to know about Lucian, Viktor, and the bloodlines.

The next paragraph will be a quick rundown of the plot, spoilers ahead! The movie is set within a castle, that is built into the side of the mountain (very Helms Deepish), which is surrounded by a large field and forest. Lucian is born from a pure breed Lycan (who was slain quickly after), but instead of killing the child, Viktor keeps and raises him. Although he keeps him chained and bound, Viktor later decides to use Lucian to infect other humans, which in return are used as slaves and labor to mine the mountain and guard the castle during the day. A love story is intermingled between Sonya (Viktors daughter) and Lucian. They try to keep it secret but Tanis (a Vampire historian) spots them at one point and tries to use this to his advantage. While Sonya is out protecting a caravan of human nobles (humans pay the vampires for protection), a large group of Lycans ambush the caravan and Lucian knowing of this escapes and saves them (Lucian also meets Raze for the first time here). For his betrayal, Viktor orders Lucian to be tortured and killed. Sonya hears of this news, makes a deal with Tanis so that Lucian can escape in return for a Vampire council seat. Lucian escapes with a few other Lycans and awaits for the arrival of Sonya. Lucian is told that Sonya has been put in prison because Viktor has found out about her love for Lucian. While the other Lycans prepare for battle, Lucian sets off to rescue Sonya. Sonya tells Viktor during their confrontation that she is pregnant with a hybrid. Viktor is furious and sends them off to prison. After their capture and trial, they are sentenced to death. The next scene involves the death of Sonya by sunlight, Lucian grabbing her amulet and attempting to escape in his Lycan form (which we have seen as a flashback in the previous movies). During his escape, Lucian is badly wounded and roars loudly which awakens the pure breed Lycans. This sets the war in motion, with the strong advance of the Lycans on the castle and coven. The castle is overrun by the Lycans, the council was slain and Lucian sets off to kill Viktor. Lucian succeeds in driving a sword through Viktors mouth and throwing him into the river (which made me think wtf? seeing as how hes in the other movies). In the last scenes you see Viktor on board a boat, along with Tanis (presumably the only other survivor). Viktor proceeds to "get into" his coufin, alongside the other elders.

Now that you are hopefully caught up, lets begin. I love watching sequels that piece together previous movies storyline, and this did it beautifully. It showed the events of the birth of Lucian and how it led up to the war between the bloodlines. What I enjoyed most was Viktors character and his power as the Vampire elder. He stays true to the Vampire laws, even when it comes to condemning his daughter to death. Although the first 2/3rds of the movie is about Lucian and Sonya and explains a lot of the previous storyline, you do not see much action or fighting between the bloodlines. It is not until the end when the Lycans commence their attack on the castle, that you see much bloodshed; and boy do you see bloodshed.

The battle upon the castles walls is very reminiscent of LOTR's Helms deep, but why try something different when the previous idea worked so well. You see the Vampires upon the walls unleash arrows and ballistas at the hundreds of Lycans rushing forward. But with little to no effect to the numbers of Lycans, the Vampires are easily overwhelmed on the walls and torn apart. Nearly all the Lycans scale the wall and commence to pounce and shred all the Vampires in sight. During this battle, Raze frees all the remaining imprisoned Lycans, who then join the battle. The Death Dealers are sent into battle, but cannot hold of the large numbers and the ferocity of the Lycans. I always enjoy these types of battles, simply because its something you would never see in a real life.

Now I would say this isnt the greatest movie, but it is a great movie. It brings the storyline together well, has a good story itself, embodies some awesome fight scenes and makes good use of Animatronics and CG. I highly recommend this to anyone who enjoys the Underworld series or movies set in this type of fantasy genre.

Other things I loved about this movie:

  • The Vampires armor - Im a huge fan of medieval settings
  • The Lycans apperance, movements and their ability to tear things apart
  • How the castle was built to protect the Vampires from sunlight

One thing though that is not explained, is the deal that Lucian makes to fake his death (the part of his skin with the tattoo). Hopefully this is explained in another movie that continues after this point.

Method for grabbing named parameters

So I never worked much with named parameters before in CakePHP, but recently I needed a way to filter data. It seemed passing many arguments to the action wasn't the best or correct approach. My initial thought was to find a method that can easily grab the param, but after much searching and looking at the API and Cookbook, no such method exists. The next alternative was doing a long ugly shorthand if statement that looked something like this (assuming our param and URL is /search/filter:username/):

$filter = (isset($this->params['named']['filter'])) ? $this->params['named']['filter'] : '';

Now seeing that CakePHP is in 1.2 Stable, you would assume they would have a simple method to fix this. But no worries, I have created a method that is very easy to use and add to your application. To add it to your application, you would place it in your AppController.

/**
 * Used to get the value of a named param
 * @param mixed $var
 * @param mixed $default
 * @return mixed
 */
public function getNamedParam($var, $default = '') {
	return (isset($this->params['named'][$var])) ? $this->params['named'][$var] : $default;
}

The first argument $var would be the name of the param (e.g., "filter" in our example above) and the second argument $default is the value you can return if the param does not exist. To use the method, simply call it from anywhere in your controller like so:

$filter = $this->getNamedParam('filter');

I have also created a second method for grabbing the value of query string param (Example URL: /search/?filter=username). I hope this has been helpful to someone, it has certainly been helpful and easily readable to me.

/**
 * Used to get the value of a get query
 * @param mixed $var
 * @param mixed $default
 * @return mixed
 */
public function getQueryParam($var, $default = '') {
	return (isset($this->params['url'][$var])) ? $this->params['url'][$var] : $default;
}

XAMPP in Windows: Enabling mod_rewrite

Below I will quickly and easily show you how to enable Apache's mod_rewrite in XAMPP Windows. If you are unclear on what mod_rewrite is, it basically takes a long query string url and shortens it to be SEO and user friendly. Now if you are also a CakePHP user, having mod_rewrite enabled is the best course of action. But it seems that mod_rewrite is not enabled with the initial install of XAMPP. Do not worry, it's extremely easy to enable the module, and here's how it's done.

I'm assuming you have installed the xampp directory into the root or C:/ drive. The first thing to do is to open the configuration file located at C:/xampp/apache/conf/httpd.conf. Locate the text below and remove the # from the beginning of it (# acts as a comment and negates the module from loading).

#LoadModule rewrite_module modules/mod_rewrite.so

The final step is to find all instances of AllowOverride None and replace them with AllowOverride All. Now to get mod_rewrite working, you will need to restart your Apache server. You can simply do this by clicking "Stop/Start" next to the Apache module of your XAMPP Control Panel.

CakePHP 1.2 Stable Released

It seems the good ole developers over at CakePHP have released an update to their 1.2 Final version, a now 1.2 Stable. As always I enjoy and appreciate how quickly the Cake team fixes, rewrites and optimizes the Cake engine. They have come a long way and with the help of the community, the Forge and the Bakery. The best thing is their use of Trac and the ability of the community to report bugs and even suggest features and code to be added. I have many ideas and have even written my own code that hopefully one day I can submit to Trac, and maybe perhaps join the team!

Anyways though, I highly recommend upgrading your Cake to the 1.2 Stable, simply because they found a security flaw with the Security and Auth Component. For more information on that flaw, the announcement, and the download, please click the following links:

Displaying form errors as a list in CakePHP

When a form is submitted in CakePHP, any errors that fail the model validation are displayed after each respective input field. But if you're like me and really dislike that structure and output, and would rather have your errors displayed in a list above the form (an example would be my contact form), then this is how you would achieve it. In the example we will be doing a login for the UsersController (do note that I am not using the AuthComponent, this is just a rough example). Lets begin by creating a file and placing it in your views/elements/errors.ctp folder.

<?php // views/elements/errors.ctp
if (!empty($errors)) { ?>
<div class="errors">
    <h3>There are <?php echo count($errors); ?> error(s) in your submission:</h3>
    <ul>
        <?php foreach ($errors as $field => $error) { ?>
        <li><?php echo $error; ?></li>
        <?php } ?>
    </ul>
</div>
<?php } ?>
Validation in the Model

For any form validation to work, we must declare a validation scheme within the respective model, in our case its the User model. Since this is a login form, the only validation we will need is for a username and password. The rules we will be applying is that both the username and password must not be empty. Once we have the validation setup, the next step is to setup the UsersController.

<?php
class User extends AppModel {
	public $validate = array(
		'username' => array(
			'notEmpty' => array(
				'rule' => 'notEmpty',
				'message' => 'Your username is required'
		)),
		'password' => array(
			'notEmpty' => array(
				'rule' => 'notEmpty',
				'message' => 'Your password is required'
		)),
	);
}
?>
Setting up the Controller

In the login action we will be using the RequestHandlerComponent to check for a form submission (this is a better approach then doing isset/!empty on $this->data). If a post is successful, we will save the form data to the User model to run it against the validation. Lastly, we need to be able to display the errors in the view, so we will set() them to $errors by calling the $this->User->validationErrors. The $errors variable is then passed to the errors.ctp element template, which in turn displays all the errors found.

<?php // controllers/users_controller.php
public function login() {
    if ($this->RequestHandler->isPost()) {
        $this->User->set($this->data);
        if ($this->User->validates()) {
        	if ($this->User->verifyLogin($this->data)) {
				// Process information
			}
        } else {
			// Didn't validate
		}
    }
    $this->set('errors', $this->User->validationErrors);
}
// models/user.php
public function verifyLogin($data) {
	$user = $this->find('first', array(
		'conditions' => array(
			'User.username' => $data['User']['username'],
			'User.password' => md5($data['User']['password'])
		)
	));
	if (!empty($user)) {
		return $user;
	} else {
		$this->invalidate('', 'No user was found with those login credentials');
	}
	return false;
} ?>

The two most important things to note is $validationErrors and the invalidate() method. The $validationErrors property is a list of all the error messages in the form for the corresponding input fields; it's called from each respective model. The method invalidate() is used to trigger a custom error that is not part of the $validate scheme for the model. Now lets look back at the controller where the verifyLogin() method is called. If that method fails (returns false), the login fails and no processing is made. On the other hand if the method returns true, lets continue and log them in.

Displaying my errors in the View

Now that we have the validation set, the errors template created and the form processing complete, the last task is to display the errors in the view. Since the controller is already setting the errors into the view, we just need to include the element, and to do that we will use the $this->element() method within the view. Just place this element in the location you want your errors to display.

<?php echo $this->element('errors', array('errors' => $errors)); ?>

Now if you have tested the form, you will notice that the errors are still showing up after the input field. To fix this, we have to disable the errors on the input by setting it to false.

<?php echo $form->input('username', array('error' => false)); ?>
Conclusion

This was a bit more lengthy then I expected, but I hope it enlightened you on how to use and display form errors. You also received a bit more knowledge on how the invalidate() and invalidFields() method work (hopefully ;)). If you have any questions please comment or send me an email, or take a gander at the CakePHP API and Cookbook.