2011
20
Sep

Now I’m Confused

I’m working on a Magento module and I got an error message saying “An error occurred while saving the page.” Right under it I gut a success message saying “The page has been saved.”

2011
19
Sep

Custom CodeIgniter Validation Methods

CodeIgniter’s Form Validation library isn’t bad. It takes a little getting use to but it can be very powerful. Most of the validation that comes with CodeIgniter are pretty much the only ones you will ever need. Every now and then you will need something else. Extending CodeIgniter libraries is very easy. These are some of the custom form validation I’ve had to do in previous projects

First of all, you have to create a library that will extend CodeIgniter’s library. Create a new file named MY_Form_validation.php and put it in the application/libraries/ directory. Here is what that library will look like:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
 
class MY_Form_validation extends CI_Form_validation {
 
	protected $CI;
 
	function __construct()
	{
		parent::__construct();
 
		$this->CI =& get_instance();
	}
}

The first validation method I used for a project where the user would enter a fraction and I didn’t really want to convert a decimal to a fraction. So I just created a validation method.

/**
 * Fraction
 *
 * @access  public
 * @param   string  $str
 * @return  bool
 */
public function fraction($str)
{
	$this->CI->form_validation->set_message('fraction', 'The %s field must be a valid fraction.');
 
	return ( ! preg_match("/^(\d++(?! */))? *-? *(?:(\d+) */ *(\d+))?.*$/", $str)) ? FALSE : TRUE;
}

Usage example:

$this->form_validation->set_rules('screen_size', 'Screen Size', 'fraction');

This was a fun validation to make. When a user signs up or is changing their password, their password must be PCI compliant. For a password to be PCI compliant, it must meet the following:
1) Must be between 6 and 99 characters in length
2) Must not contain two consecutively repeating characters
3) Must contain at least one upper-case letter
4) Must contain at least one lower-case letter
5) Must contain at least one number
6) Must contain at least one special character

Please note that the validation message is really long. You may want to simplify it a little before using it

/**
 * PCI compliance password
 *
 * @access  public
 * @param   $str
 * @return  bool
 */
public function pci_password($str)
{
	$special = '!@#$%*-_=+.';
 
	$this->CI->form_validation->set_message('pci_password', 'For PCI compliance, %s must be between 6 and 99 characters in length, must not contain two consecutively repeating characters, contain at least one upper-case letter, at least one lower-case letter, at least one number, and at least one special character ('.$special.')');
 
	return (preg_match('/^(?=^.{6,99}$)(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*['.$special.'])(?!.*?(.)\1{1,})^.*$/', $str)) ? TRUE : FALSE;
}

Usage example:

$this->form_validation->set_rules('password', 'Password', 'pci_password');

CodeIgniter already has a validation method for required. But I needed one to be required if a different field had a value. A couple weeks later I needed to have method to make a field required if another field had a certain value.

/**
 * Required if another field has a value (related fields) or if a field has a certain value
 *
 * @access  public
 * @param   string  $str
 * @param   string  $field
 * @return  bool
 */
public function required_if($str, $field)
{
	list($fld, $val) = explode(',', $field, 2);
 
	$this->CI->form_validation->set_message('required_if', 'The %s field is required.');
 
	// $fld is filled out
	if (isset($_POST[$fld]))
	{
		// Must have specific value
		if ($val)
		{
			// Not the specific value we are looking for
			if ($_POST[$fld] == $val AND ! $str)
			{
				return FALSE;
			}
		}
 
		return TRUE;
	}
 
	return FALSE;
}

Usage example:

$this->form_validation->set_rules('bar', 'Bar', 'required_if[foo]'); // required if field 'foo' has a value
$this->form_validation->set_rules('foobar', 'Foo Bar', 'required_if[foo,bar]'); // required if field 'foo' has a value of 'bar'

There are a lot of examples of this validation floating around. It requires that a value being passed has a unique value in the database. This one also takes into account the database prefix.

/**
 * Unique
 *
 * @access	public
 * @param	string
 * @param	field
 * @return	bool
 */
public function unique($str, $field)
{
	list($table, $column) = explode(',', $field, 2);
 
	$this->CI->form_validation->set_message('unique', 'The %s that you requested is already in use.');
 
	$query = $this->CI->db->query("SELECT COUNT(*) AS dupe FROM {$this->CI->db->dbprefix($table)} WHERE {$column} = '{$str}'");
	$row = $query->row();
 
	return ($row->dupe > 0) ? FALSE : TRUE;
}

Usage example:

$this->form_validation->set_rules('email', 'Email', 'unique[DBTABLE,DBFIELD]');	// DBTABLE is the database table and DBFIELD is the database field to validation against

I took the previous validation a step further so that the field value must be unique in the database EXCEPT for a certain record ID. This one is really good for if you have an existing user in the system and they are updating their profile. You want to make sure that their email address is unique. If you run the previous unique validation it will fail because the email address is already in use by the user currently being edited. So we need to exclude that users ID from the validation. This one also takes into account the database prefix.

/**
 * Unique except. Check if a specific value is in use except when the value is attached to a specific row ID
 *
 * @param	string
 * @param	field
 * @return	bool
 */
public function unique_exclude($str, $field)
{
	list($table, $column, $fld, $id) = explode(',', $field, 4);
 
	$this->CI->form_validation->set_message('unique_exclude', 'The %s that you requested is already in use.');
 
	$query = $this->CI->db->query("SELECT COUNT(*) AS dupe FROM {$this->CI->db->dbprefix($table)} WHERE {$column} = '$str' AND {$fld} <> {$id}");
	$row = $query->row();
 
	return ($row->dupe > 0) ? FALSE : TRUE;
}

Usage example:

$this->form_validation->set_rules('email', 'Email', 'unique[DBTABLE,DBFIELD,IDFIELD,ID]');	// DBTABLE is the database table, DBFIELD is the database field, IDFIELD is the primary key for the table, and ID is the unique ID for the user
2011
17
Sep

Cross Browser Support for inline-block in CSS

I’ve been using this method for cross browser inline-block displays for a while and thought everyone else knew about it too. One of my co-workers was shocked to find out they had been doing it wrong for so long. So I thought I would share it in case someone else didn’t know about it.

Inline-block is very powerful. It is very useful for horizontal lists and even makes vertical alignment work properly. Unfortunately, it’s supported pretty poorly. *cough*Internet Explorer*cough*

Older versions of Firefox support inline-block with a special “-moz” tag. But not the one you think. It uses ‘-moz-inline-stack’ instead of ‘-moz-inline-block’. And when I say older versions I mean anything before version 4 I believe. So really, you don’t have to add it if you don’t want to. I don’t. But if you keep it, make sure ‘display:-moz-inline-stack’ comes BEFORE ‘display:inline-block’ so newer versions of Firefox can use the standard style.

IE supports inline-block, but only for elements that are natively inline, such as span and strong. When ‘zoom: 1′ is set, it triggers hasLayout and magically IE supports inline-block. The *property is an IE hack that does not get run for non-IE browsers.

So, without further adieus, cross-browser inline-block support:

.myStyle {
	display: -moz-inline-stack;  /* optional */
	display: inline-block;
	zoom: 1;  /* triggers hasLayout for IE */
	*display: inline;  /* target IE7 only */
}
2011
16
Sep

Blocks in Magento

One of the things Magento got right is blocks. It’s one of the few things I am continually impressed by. There are a lot of ways to add a static block to the page.

XML is probably the most common place to add a static block. You find whatever block you want to add your static block into and you add something like:

<block type="cms/block" name="YOUR_BLOCK_ID" before="-">
	<action method="setBlockId"><block_id>YOUR_BLOCK_ID</block_id></action>
</block>

Adding a static clock through layout XML can be very useful if you need to add a static block to a sidebar on a single page for example instead of all pages.

<reference name="left">
	<block type="cms/block" name="YOUR_BLOCK_ID">
		<action method="setBlockId"><block_id>YOUR_BLOCK_ID</block_id></action>
	</block>
</reference>

Adding you static block through PHP may be the least common way. This, however, can be very useful if you want to define areas in your theme where a menu or a widgets could go. To add a static block in PHP you would use:

echo $this->getLayout()->createBlock('cms/block')->setBlockId('YOUR_BLOCK_ID')->toHtml();

Adding a static block through a short code is very powerful. It allows you to add a static block into a CMS page or even your products.

{{block type="cms/block" block_id="YOUR_BLOCK_ID"}}
2011
15
Sep

To the shores of Tripoli

Before the uprising in Libya, even though it is part of the Marine Corps Hymn, I really doubt most Marines knew were Tripoli was located. ‘To the shores of Tripoli’ in the Marine Corps Hymn stems from the Battle of Derne. It is the first recorded land battle fought overseas by the United States. It was after this battle that 1st Lt. O’Bannon was presented the Mameluke sword, which is still worn by Marine officers today.

More Marines are aware that ‘The Halls of Montezuma’ is from the Battle of Chapultepec, only because it is from this battle that we get the blood stripe that NCOs wear to commemorate the Marines that died during this battle. I doubt most Marines know that the Battle of Chapultepec was fought during the Mexican-American War were US forces fought Mexican forces holding Chapultepec Castle located west of Mexico City.

2011
18
Jul

Setting Up Virtual Hosts in Zend Server CE on OS X

What is a virtual host? Virtual hosting is a method for hosting multiple domain names on a computer using a single IP address. Shared hosting uses this same method for all of the sites they host. Aren’t those URLs you use in Zend Server getting pretty ugly? Would you like to change http://localhost/my/awesome/website into http://www.super-awesome.local You can!

Last time we talked about general Zend Server setup. This time, we will be going through setting up virtual hosts on your local machine. This again will involve Terminal.

This assumes you have Zend Server set up and running. If it is not, go here.

Continue reading “Setting Up Virtual Hosts in Zend Server CE on OS X” »