Categories
Free PHP Classes & Library PHP Tips & Tutorials

Convert Object to Array in PHP

There are quite a few ways to do this and each of them has its strengths and weaknesses. Find out if one suits your needs by trying one of the approaches below.

Casting with (array)

$array = (array) $obj;

Problem is this doesn’t convert complex / multi-dimensional objects well.

get_object_vars()

$array = get_object_vars( $obj );

$array would then be an array of properties and values from $obj that are accessible in the current scope.

Custom function for complex objects

function objectToArray( $object )
    {
        if( !is_object( $object ) && !is_array( $object ) )
        {
            return $object;
        }
        if( is_object( $object ) )
        {
            $object = get_object_vars( $object );
        }
        return array_map( 'objectToArray', $object );
    }

$array = objectToArray( $obj );

This function is conjured by PHPRO.ORG.

JSON – json_encode(), json_decode()

$json  = json_encode($object);
$array = json_decode($json, true);

This is probably the coolest approach delivered by Andy.

Categories
.htaccess Tutorials & Tips Free PHP Classes & Library Information Security PHP Tips & Tutorials

PHP Class for Handling .htpasswd and .htgroup (Member Login & User Management)

Apache is a marvelous web server that offers .htpasswd and .htgroup for controlling restricted access to your website. By help of .htaccess, they work as a member login & user management system that is so simple and easy to deploy. You can even define user groups / roles with it.

Basically,

  • .htpasswd defines pairs of username & password that are user accounts.
  • .htgroup defines groups / roles of user accounts that can be access-controlled as a whole.
  • .htaccess then applies .htpasswd and .htgroup to the current directory, and specifies which groups in .htgroup has access to the current directory.

For example, we have

/home/myuser/.htpasswd

user1:{SHA}kGPaD671VNU0OU5lqLiN/h6Q6ac=
user2:{SHA}npMqPEX3kPQTo+x/+ZckHDrIcQI=
user3:{SHA}q1Fh2LTUjjkncp11m0M9WUH5Zrw=

/home/myuser/.htgroup

admin: user2
editor: user1 user3
writer: user3

/home/myuser/public_html/example.com/member/.htaccess

AuthName "Members Area"
AuthType Basic
AuthUserFile /home/myuser/.htpasswd
AuthGroupFile /home/myuser/.htgroup
<Limit GET POST>
require group admin
require group writer
</Limit>

What they do is only let users in the admin and writer group, that is user2 and user3, to access example.com/member. When someone tries to access example.com/member, Apache would prompt him or her for user name and password, and he or she must be either user2 or user3 to access it – they must enter the correct password set out in .htpasswd for user2 or user3.

user1 isn’t allowed to access example.com/member even if the password is correct. You get the idea.

You can place .htaccess anywhere in your website, and it will control access to the directory it’s in by the defined rules (which groups / roles are allowed to access). Just make sure it is pointing to the right .htpasswd and .htgroup by AuthUserFile and AuthGroupFile.

And you can have multiple .htaccess in different directories of your website, using the same .htpasswd and .htgroup.

This is so simple yet so very handy in creating & managing different users and user roles (.htpasswd, .htgroup) and giving them permissions (.htaccess) in accessing different website assets.

PHP Class

Now that you are familiar with the basic authentication and native user management system in Apache, you can use this two simple PHP classes to automate tasks such as user creation, user deletion, adding user to group, and removing user from group.

class Htpasswd

class Htpasswd {
	
	private $file = '';
	private $salt = 'AynlJ2H.74VEfI^BZElc-Vb6G0ezE9a55-Wj';
	
	private function write($pairs = array()) {
		$str = '';
		foreach ($pairs as $username => $password) {
			$str .= "$username:{SHA}$password\n";
		}
		file_put_contents($this -> file, $str);
	}
	
	private function read() {
		$pairs = array();
		$fh = fopen($this -> file, 'r');
		while (!feof($fh)) {
			$pair_str = str_replace("\n", '', fgets($fh));
			$pair_array = explode(':{SHA}', $pair_str);
			if (count($pair_array) == 2) {
				$pairs[$pair_array[0]] = $pair_array[1];
			}
		}
		return $pairs;
	}
	
	private function getHash($clear_password = '') {
		if (!empty($clear_password)) {
			return base64_encode(sha1($clear_password, true));
		} else {
			return false;
		}
	}
	
	public function __construct($file) {
		if (file_exists($file)) {
			$this -> file = $file;
		} else {
			die($file." doesn't exist.");
			return false;
		}
	}

	public function getUsers() {
		return $this -> read();
	}
	
	public function addUser($username = '', $clear_password = '') {
		if (!empty($username) && !empty($clear_password)) {
			$all = $this -> read();
			if (!array_key_exists($username, $all)) {
				$all[$username] = $this -> getHash($clear_password);
				$this -> write($all);
			}
		} else {
			return false;
		}
	}
	
	public function deleteUser($username = '') {
		$all = $this -> read();
		if (array_key_exists($username, $all)) {
			unset($all[$username]);
			$this -> write($all);
		} else {
			return false;
		}
	}
	
	public function doesUserExist($username = '') {
		$all = $this -> read();
		if (array_key_exists($username, $all)) {
			return true;
		} else {
			return false;
		}
	}
	
	public function getClearPassword($username) {
		return strtolower(substr(sha1($username.$this -> salt), 4, 12));
	}
	
}

class Htgroup

class Htgroup {
	
	private $file = '';
	
	private function write($groups = array()) {
		$str = '';
		foreach ($groups as $group => $users) {
			$users_str = '';
			foreach ($users as $user) {
				if (!empty($users_str)) {
					$users_str .= ' ';
				}
				$users_str .= $user;
			}
			$str .= "$group: $users_str\n";
		}
		file_put_contents($this -> file, $str);
	}
	
	private function read() {
		$groups = array();
		$groups_str = file($this -> file, FILE_IGNORE_NEW_LINES);
		foreach ($groups_str as $group_str) {
			if (!empty($group_str)) {
				$group_str_array = explode(': ', $group_str);
				if (count($group_str_array) == 2) {
					$users_array = explode(' ', $group_str_array[1]);
					$groups[$group_str_array[0]] = $users_array;
				}
			}
		}
		return $groups;
	}
	
	public function __construct($file) {
		if (file_exists($file)) {
			$this -> file = $file;
		} else {
			die($file." doesn't exist.");
			return false;
		}
	}

	public function getGroups() {
		return $this -> read();
	}
	
	public function addUserToGroup($username = '', $group = '') {
		if (!empty($username) && !empty($group)) {
			$all = $this -> read();
			if (isset($all[$group])) {
				if (!in_array($username, $all[$group])) {
					$all[$group][] = $username;
				}
			} else {
				$all[$group][] = $username;
			}
			$this -> write($all);
		} else {
			return false;
		}
	}
	
	public function deleteUserFromGroup($username = '', $group = '') {
		$all = $this -> read();
		if (array_key_exists($group, $all)) {
			$user_index = array_search($username, $all[$group]);
			if ($user_index !== false) {
				unset($all[$group][$user_index]);
				if (count($all[$group]) == 0) {
					unset($all[$group]);
				}
				$this -> write($all);
			}
		} else {
			return false;
		}
	}

	public function getGroupsByUser($username = '') {
		$all = $this -> read();
		$user_groups = array();
		foreach ($all as $group => $users) {
			if (in_array($username, $users)) {
				$user_groups[] = $group;
			}
		}
		return $user_groups;
	}

}

Usage

First, you should use your own $salt. Change the value of $salt in the Htpasswd class to something else for your own application.

To instantiate the classes:

$passwdHandler = new Htpasswd('/home/myuser/.htpasswd');
$groupHandler = new Htgroup('/home/myuser/.htgroup');

To create and delete a user:

// Add a user with name 'user1' and password 'I prefer to use passphrase rather than password.' if it doesn't exist in .htpasswd.
$passwdHandler -> addUser('user1', 'I prefer to use passphrase rather than password.');
// Delete the user 'user1' if it exists in .htpasswd.
$passwdHandler -> deleteUser('user1');

To check if a particular user exists in .htpasswd:

// Check if user 'user1' exists in .htpasswd.
if ($passwdHandler -> doesUserExist('user1')) {
	// User 'user1' exists.
}

To get the clear text password for a particular user (Apache stores passwords in .htpasswd as encoded strings):

// Get the clear password for user 'user1'.
echo $passwdHandler -> getClearPassword('user1');

To add a user to a group:

// Add user 'user1' to group 'admin' in .htgroup. Group will be automatically created if it doesn't exist.
$groupHandler -> addUserToGroup('user1', 'admin');

To delete a user from a group (user still exists in .htpasswd, just not associated with the group any more):

// Delete user 'user1' from group 'admin' in .htgroup. Group will be automatically removed if it doesn't contain any users.
$groupHandler -> deleteUserFromGroup('user1', 'admin');

To get a list of groups a particular user is assigned to:

/* Get an array of groups that 'user1' is a member of. */
$user_groups = $groupHandler -> getGroupsByUser('user1');

Conclusion

This ain’t concluded. It’s just an END notice. Feel free to let me know your thoughts and how my classes work for you.

Categories
Free PHP Classes & Library PHP Tips & Tutorials

PHP: Crontab Class to Add, Edit and Remove Cron Jobs

Provided that your user account on the server has the privileges to access crontab thus can create or remove cron jobs, you can use this PHP class to integrate crontab in your application. I created it for many of my own projects that need crontab to do scheduled jobs. It’s pretty straightforward.

Don’t know what crontab is and how it works? Read here and here. With this class, you or your users can easily set up crontab jobs and automate tasks by schedule with the web interface.

The Crontab Class

class Crontab {
	
	// In this class, array instead of string would be the standard input / output format.
	
	// Legacy way to add a job:
	// $output = shell_exec('(crontab -l; echo "'.$job.'") | crontab -');
	
	static private function stringToArray($jobs = '') {
		$array = explode("\r\n", trim($jobs)); // trim() gets rid of the last \r\n
		foreach ($array as $key => $item) {
			if ($item == '') {
				unset($array[$key]);
			}
		}
		return $array;
	}
	
	static private function arrayToString($jobs = array()) {
		$string = implode("\r\n", $jobs);
		return $string;
	}
	
	static public function getJobs() {
		$output = shell_exec('crontab -l');
		return self::stringToArray($output);
	}
	
	static public function saveJobs($jobs = array()) {
		$output = shell_exec('echo "'.self::arrayToString($jobs).'" | crontab -');
		return $output;	
	}
	
	static public function doesJobExist($job = '') {
		$jobs = self::getJobs();
		if (in_array($job, $jobs)) {
			return true;
		} else {
			return false;
		}
	}
	
	static public function addJob($job = '') {
		if (self::doesJobExist($job)) {
			return false;
		} else {
			$jobs = self::getJobs();
			$jobs[] = $job;
			return self::saveJobs($jobs);
		}
	}
	
	static public function removeJob($job = '') {
		if (self::doesJobExist($job)) {
			$jobs = self::getJobs();
			unset($jobs[array_search($job, $jobs)]);
			return self::saveJobs($jobs);
		} else {
			return false;
		}
	}
	
}

Public Methods

You may well ignore the private methods that do the internal chores. And keep in mind that any cron job is a text string.

  1. getJobs() – returns an array of existing / current cron jobs. Each array item is a string (cron job).
  2. saveJobs($jobs = array()) – save the $jobs array of cron jobs into the crontab so they would be run by the server. All existing jobs in crontab are erased and replaced by $jobs.
  3. doesJobExist($job = ”) – check if a specific job exist in crontab.
  4. addJob($job = ”) – add a cron job to the crontab.
  5. removeJob($job = ”) – remove a cron job from crontab.

This class has been tested on Rackspace Cloud and Wiredtree. Feel free to post your comments below and let me know how it works on other web hosts.

Categories
Free PHP Classes & Library

PHP Class: Convert Plural to Singular or Vice Versa in English

I was trying to find a PHP function or class that can convert English words / nouns in plural form into their singular form so that wordcrow.com automatically detects and redirects plural lookup to the singular page. After a while searching on Google, I found this class.

This great class (Inflector) was ported from Ruby on Rails to PHP in the Akelos Framework by Akelos Media, S.L. http://www.akelos.com/.

List of Functions

Other than pluralize and singularize, this class has some more functions to convert text strings by certain standards. List below are all the functions this class has:

  • Inflector::pluralize – return the plural form of the given English word, e.g. “search” to “searches”.
  • Inflector::singularize – return the singular form of the given English word, e.g. “searches” to “search”.
  • Inflector::titleize – create a title text from the given string, e.g. “WelcomePage”, “welcome_page” or “welcome page” to “Welcome Page”.
  • Inflector::camelize – return the CamelCased text from the given string, e.g. “send_email” to “SendEmail”, “who’s online” to “WhoSOnline”.
  • Inflector::underscore – return a underscored text from the given string, e.g. “CamelCased” or “ordinary Word” to “underscored_word” that is lowercased.
  • Inflector::humanize – return a human-readable text from the given string, e.g., by replacing underscores with spaces, and by upper-casing the initial character by default.
  • Inflector::variablize – same as camelize but first char is underscored.
  • Inflector::tableize – converts a class name to its table name by rails naming conventions.
  • Inflector::classify – converts a table name to its class name by rails naming conventions.
  • Inflector::ordinalize – converts a natural number to its ordinal form in English, e.g. “2” to “2nd”, “15” to “15th”, “31” to “31st”.

Inflector Class

<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

// +----------------------------------------------------------------------+
// | Akelos PHP Application Framework                                     |
// +----------------------------------------------------------------------+
// | Copyright (c) 2002-2006, Akelos Media, S.L.  http://www.akelos.com/  |
// | Released under the GNU Lesser General Public License                 |
// +----------------------------------------------------------------------+
// | You should have received the following files along with this library |
// | - COPYRIGHT (Additional copyright notice)                            |
// | - DISCLAIMER (Disclaimer of warranty)                                |
// | - README (Important information regarding this library)              |
// +----------------------------------------------------------------------+

/**
* Inflector for pluralize and singularize English nouns.
*
* This Inflector is a port of Ruby on Rails Inflector.
*
* It can be really helpful for developers that want to
* create frameworks based on naming conventions rather than
* configurations.
*
* It was ported to PHP for the Akelos Framework, a
* multilingual Ruby on Rails like framework for PHP that will
* be launched soon.
*
* @author Bermi Ferrer Martinez 
* @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
* @license GNU Lesser General Public License 
* @since 0.1
* @version $Revision 0.1 $
*/
class Inflector
{
    // ------ CLASS METHODS ------ //

    // ---- Public methods ---- //

    // {{{ pluralize()

    /**
    * Pluralizes English nouns.
    *
    * @access public
    * @static
    * @param    string    $word    English noun to pluralize
    * @return string Plural noun
    */
    function pluralize($word)
    {
        $plural = array(
        '/(quiz)$/i' => '1zes',
        '/^(ox)$/i' => '1en',
        '/([m|l])ouse$/i' => '1ice',
        '/(matr|vert|ind)ix|ex$/i' => '1ices',
        '/(x|ch|ss|sh)$/i' => '1es',
        '/([^aeiouy]|qu)ies$/i' => '1y',
        '/([^aeiouy]|qu)y$/i' => '1ies',
        '/(hive)$/i' => '1s',
        '/(?:([^f])fe|([lr])f)$/i' => '12ves',
        '/sis$/i' => 'ses',
        '/([ti])um$/i' => '1a',
        '/(buffal|tomat)o$/i' => '1oes',
        '/(bu)s$/i' => '1ses',
        '/(alias|status)/i'=> '1es',
        '/(octop|vir)us$/i'=> '1i',
        '/(ax|test)is$/i'=> '1es',
        '/s$/i'=> 's',
        '/$/'=> 's');

        $uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep');

        $irregular = array(
        'person' => 'people',
        'man' => 'men',
        'child' => 'children',
        'sex' => 'sexes',
        'move' => 'moves');

        $lowercased_word = strtolower($word);

        foreach ($uncountable as $_uncountable){
            if(substr($lowercased_word,(-1*strlen($_uncountable))) == $_uncountable){
                return $word;
            }
        }

        foreach ($irregular as $_plural=> $_singular){
            if (preg_match('/('.$_plural.')$/i', $word, $arr)) {
                return preg_replace('/('.$_plural.')$/i', substr($arr[0],0,1).substr($_singular,1), $word);
            }
        }

        foreach ($plural as $rule => $replacement) {
            if (preg_match($rule, $word)) {
                return preg_replace($rule, $replacement, $word);
            }
        }
        return false;

    }

    // }}}
    // {{{ singularize()

    /**
    * Singularizes English nouns.
    *
    * @access public
    * @static
    * @param    string    $word    English noun to singularize
    * @return string Singular noun.
    */
    function singularize($word)
    {
        $singular = array (
        '/(quiz)zes$/i' => '\1',
        '/(matr)ices$/i' => '\1ix',
        '/(vert|ind)ices$/i' => '\1ex',
        '/^(ox)en/i' => '\1',
        '/(alias|status)es$/i' => '\1',
        '/([octop|vir])i$/i' => '\1us',
        '/(cris|ax|test)es$/i' => '\1is',
        '/(shoe)s$/i' => '\1',
        '/(o)es$/i' => '\1',
        '/(bus)es$/i' => '\1',
        '/([m|l])ice$/i' => '\1ouse',
        '/(x|ch|ss|sh)es$/i' => '\1',
        '/(m)ovies$/i' => '\1ovie',
        '/(s)eries$/i' => '\1eries',
        '/([^aeiouy]|qu)ies$/i' => '\1y',
        '/([lr])ves$/i' => '\1f',
        '/(tive)s$/i' => '\1',
        '/(hive)s$/i' => '\1',
        '/([^f])ves$/i' => '\1fe',
        '/(^analy)ses$/i' => '\1sis',
        '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis',
        '/([ti])a$/i' => '\1um',
        '/(n)ews$/i' => '\1ews',
        '/s$/i' => '',
        );

        $uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep');

        $irregular = array(
        'person' => 'people',
        'man' => 'men',
        'child' => 'children',
        'sex' => 'sexes',
        'move' => 'moves');

        $lowercased_word = strtolower($word);
        foreach ($uncountable as $_uncountable){
            if(substr($lowercased_word,(-1*strlen($_uncountable))) == $_uncountable){
                return $word;
            }
        }

        foreach ($irregular as $_plural=> $_singular){
            if (preg_match('/('.$_singular.')$/i', $word, $arr)) {
                return preg_replace('/('.$_singular.')$/i', substr($arr[0],0,1).substr($_plural,1), $word);
            }
        }

        foreach ($singular as $rule => $replacement) {
            if (preg_match($rule, $word)) {
                return preg_replace($rule, $replacement, $word);
            }
        }

        return $word;
    }

    // }}}
    // {{{ titleize()

    /**
    * Converts an underscored or CamelCase word into a English
    * sentence.
    *
    * The titleize function converts text like "WelcomePage",
    * "welcome_page" or  "welcome page" to this "Welcome
    * Page".
    * If second parameter is set to 'first' it will only
    * capitalize the first character of the title.
    *
    * @access public
    * @static
    * @param    string    $word    Word to format as tile
    * @param    string    $uppercase    If set to 'first' it will only uppercase the
    * first character. Otherwise it will uppercase all
    * the words in the title.
    * @return string Text formatted as title
    */
    function titleize($word, $uppercase = '')
    {
        $uppercase = $uppercase == 'first' ? 'ucfirst' : 'ucwords';
        return $uppercase(Inflector::humanize(Inflector::underscore($word)));
    }

    // }}}
    // {{{ camelize()

    /**
    * Returns given word as CamelCased
    *
    * Converts a word like "send_email" to "SendEmail". It
    * will remove non alphanumeric character from the word, so
    * "who's online" will be converted to "WhoSOnline"
    *
    * @access public
    * @static
    * @see variablize
    * @param    string    $word    Word to convert to camel case
    * @return string UpperCamelCasedWord
    */
    function camelize($word)
    {
        return str_replace(' ','',ucwords(preg_replace('/[^A-Z^a-z^0-9]+/',' ',$word)));
    }

    // }}}
    // {{{ underscore()

    /**
    * Converts a word "into_it_s_underscored_version"
    *
    * Convert any "CamelCased" or "ordinary Word" into an
    * "underscored_word".
    *
    * This can be really useful for creating friendly URLs.
    *
    * @access public
    * @static
    * @param    string    $word    Word to underscore
    * @return string Underscored word
    */
    function underscore($word)
    {
        return  strtolower(preg_replace('/[^A-Z^a-z^0-9]+/','_',
        preg_replace('/([a-zd])([A-Z])/','1_2',
        preg_replace('/([A-Z]+)([A-Z][a-z])/','1_2',$word))));
    }

    // }}}
    // {{{ humanize()

    /**
    * Returns a human-readable string from $word
    *
    * Returns a human-readable string from $word, by replacing
    * underscores with a space, and by upper-casing the initial
    * character by default.
    *
    * If you need to uppercase all the words you just have to
    * pass 'all' as a second parameter.
    *
    * @access public
    * @static
    * @param    string    $word    String to "humanize"
    * @param    string    $uppercase    If set to 'all' it will uppercase all the words
    * instead of just the first one.
    * @return string Human-readable word
    */
    function humanize($word, $uppercase = '')
    {
        $uppercase = $uppercase == 'all' ? 'ucwords' : 'ucfirst';
        return $uppercase(str_replace('_',' ',preg_replace('/_id$/', '',$word)));
    }

    // }}}
    // {{{ variablize()

    /**
    * Same as camelize but first char is underscored
    *
    * Converts a word like "send_email" to "sendEmail". It
    * will remove non alphanumeric character from the word, so
    * "who's online" will be converted to "whoSOnline"
    *
    * @access public
    * @static
    * @see camelize
    * @param    string    $word    Word to lowerCamelCase
    * @return string Returns a lowerCamelCasedWord
    */
    function variablize($word)
    {
        $word = Inflector::camelize($word);
        return strtolower($word[0]).substr($word,1);
    }

    // }}}
    // {{{ tableize()

    /**
    * Converts a class name to its table name according to rails
    * naming conventions.
    *
    * Converts "Person" to "people"
    *
    * @access public
    * @static
    * @see classify
    * @param    string    $class_name    Class name for getting related table_name.
    * @return string plural_table_name
    */
    function tableize($class_name)
    {
        return Inflector::pluralize(Inflector::underscore($class_name));
    }

    // }}}
    // {{{ classify()

    /**
    * Converts a table name to its class name according to rails
    * naming conventions.
    *
    * Converts "people" to "Person"
    *
    * @access public
    * @static
    * @see tableize
    * @param    string    $table_name    Table name for getting related ClassName.
    * @return string SingularClassName
    */
    function classify($table_name)
    {
        return Inflector::camelize(Inflector::singularize($table_name));
    }

    // }}}
    // {{{ ordinalize()

    /**
    * Converts number to its ordinal English form.
    *
    * This method converts 13 to 13th, 2 to 2nd ...
    *
    * @access public
    * @static
    * @param    integer    $number    Number to get its ordinal value
    * @return string Ordinal representation of given string.
    */
    function ordinalize($number)
    {
        if (in_array(($number % 100),range(11,13))){
            return $number.'th';
        }else{
            switch (($number % 10)) {
                case 1:
                return $number.'st';
                break;
                case 2:
                return $number.'nd';
                break;
                case 3:
                return $number.'rd';
                default:
                return $number.'th';
                break;
            }
        }
    }

    // }}}

}

?>

Usage Examples

/* Singular to plural / Plural to singular */

echo Inflector::pluralize('search'); // outputs searches
echo Inflector::singularize('cases'); // outputs case
echo Inflector::pluralize('query'); // outputs queries
echo Inflector::singularize('queries'); // outputs query
echo Inflector::pluralize('ability'); // outputs abilities
echo Inflector::singularize('abilities'); // outputs ability
echo Inflector::pluralize('analysis'); // outputs analyses
echo Inflector::singularize('analyses'); // outputs analysis
echo Inflector::pluralize('information'); // outputs information
echo Inflector::singularize('information'); // outputs information
echo Inflector::pluralize('mouse'); // outputs mice
echo Inflector::singularize('mice'); // outputs mouse

/* CamelCase to underscore / underscore to CamelCase */

echo Inflector::underscore('SpecialGuest'); // outputs special_guest
echo Inflector::camelize('special_guest'); // outputs SpecialGuest
echo Inflector::underscore('FreeBSD'); // outputs free_bsd
echo Inflector::camelize('free_bsd'); // outputs FreeBsd
echo Inflector::underscore('HTML'); // outputs html
echo Inflector::camelize('html'); // outputs Html

/* Underscore to "human-text" / "Human-text" to Underscore */

echo Inflector::humanize('employee_salary'); // outputs Employee salary
echo Inflector::underscore('Employee salary'); // outputs employee_salary

/* Examples of titleize() */

echo Inflector::titleize('ActiveRecord'); // outputs Active Record
echo Inflector::titleize('action web service'); // outputs Action Web Service

/* Examples of ordinalize() */

echo Inflector::ordinalize(1); // outputs 1st
echo Inflector::ordinalize(2); // outputs 2nd
echo Inflector::ordinalize(3); // outputs 3rd
echo Inflector::ordinalize(4); // outputs 4th
echo Inflector::ordinalize(5); // outputs 5th
echo Inflector::ordinalize(20); // outputs 20th
echo Inflector::ordinalize(21); // outputs 21st
Categories
Free PHP Classes & Library PHP Tips & Tutorials

A Simple PHP Contact Form Script

Update: Other than using the code outlined on this page, you may also want to download the Kavoir Contact Form script to be readily usable on your website.

It’s also a free one and a rather easy one too. You should be able to do it yourself. To create a working contact form, you need the front end and the back end. The front end presents the contact form to the website user and the back end accepts the data sent from the form by the user and take any necessary actions such as relaying the message to your email.

Visit FormKid.com for hosted free contact form solution.

Front end (HTML)

Simply copy this HTML form and paste it into your web pages where you want it to be, such as on the sidebar so a visitor can send you a contact message on any page.

<form action="/cf.php" method="post">
	<p><label for="input-email">Your Email: </label><br/><input type="text" name="email" id="input-email" size="40"/></p>
	<p><label for="input-message">Your Message: </label><br/><textarea type="text" name="message" id="input-message" rows="10" cols="40"></textarea></p>
	<p><button type="submit" name="submit">Send</button></p>
</form>

You may also want to style this form a little bit to make it look fancier. But make sure you don’t change any of the properties inside the tags such as action=”…” and name=”…”.

Back end (PHP)

Copy and paste these PHP code into a file named cf.php, change youremail@yoursite.com to your own email address that you wish to receive the messages. Put the file at the root directory of your domain so that everyone can access it at http://www.yoursite.com/cf.php.

<?php

if (isset($_GET['success'])) {

	?><p><span style="color:green;">Message successfully sent.</span> Thank you!</p><?php

} else {

	if (!empty($_POST['email']) && !empty($_POST['message'])) {

		$to = 'youremail@yoursite.com'; // your email address, can be @gmail.com, etc.
		$subject = 'Contact from yoursite.com'; // change yoursite.com to your own domain name
		$message = $_POST['message']."\r\n\r\nSender IP: ".$_SERVER["REMOTE_ADDR"];
		$headers = 'From: '.$_POST['email']."\r\n".
					'Reply-To: '.$_POST['email']."\r\n";
		mail($to, $subject, $message, $headers);

		header("Location: /cf.php?success"); // redirects the sender to success page so he or she doesn't accidentally send multiple identical messages

	} else {

		?><p><span style="color:red;">Error detected.</span> Please make sure you have filled all fields. Press back button to go back.</p><?php

	}

}

?>

Should be functioning properly. Thus far this contact form script has been successfully tested on Rackspace Cloud, DreamHost and Linode.

There are a lot more that can be done to create a sophisticated contact form. For starters, you can implement a spam catcher and a file upload control that sends the user uploaded file as attachment to your email. You could also have on-page error detection but that’d need a lot more coding.

Categories
Free PHP Classes & Library PHP Tips & Tutorials

PHP: Email Attachment Class

You can send emails very easily with PHP by the help of mail() function, but how does one send attachment attached to that email?

You’ll still use mail() function, but with a little more twists in the header argument – yes, the content of the attached file is actually encoded into the header of the email, can you believe that. Big head.

Unfortunately, it’s a pain in the ass every time you have to get through all the chores needed to attach and encode the file into the email header. You have to know the size of the file, base64_encode() it, chunk_split() it and set all the configurations required in the header so that the email client can recognize that something’s in the header and can extract it out as an attachment.

Anyway, I’ve made this class AttachmentEmail that you can email an attachment with PHP more easily. All the chores are taken care of. It’s written in a hurry so the structure can sure be better. Other than this, it works like a charm.

The Class:

class AttachmentEmail {
	private $from = 'yours@email.com';
	private $from_name = 'Your Name';
	private $reply_to = 'yours@email.com';
	private $to = '';
	private $subject = '';
	private $message = '';
	private $attachment = '';
	private $attachment_filename = '';

	public function __construct($to, $subject, $message, $attachment = '', $attachment_filename = '') {
		$this -> to = $to;
		$this -> subject = $subject;
		$this -> message = $message;
		$this -> attachment = $attachment;
		$this -> attachment_filename = $attachment_filename;
	}

	public function mail() {
		if (!empty($this -> attachment)) {
			$filename = empty($this -> attachment_filename) ? basename($this -> attachment) : $this -> attachment_filename ;
			$path = dirname($this -> attachment);
			$mailto = $this -> to;
			$from_mail = $this -> from;
			$from_name = $this -> from_name;
			$replyto = $this -> reply_to;
			$subject = $this -> subject;
			$message = $this -> message;

			$file = $path.'/'.$filename;
			$file_size = filesize($file);
			$handle = fopen($file, "r");
			$content = fread($handle, $file_size);
			fclose($handle);
			$content = chunk_split(base64_encode($content));
			$uid = md5(uniqid(time()));
			$name = basename($file);
			$header = "From: ".$from_name." <".$from_mail.">\r\n";
			$header .= "Reply-To: ".$replyto."\r\n";
			$header .= "MIME-Version: 1.0\r\n";
			$header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";
			$header .= "This is a multi-part message in MIME format.\r\n";
			$header .= "--".$uid."\r\n";
			$header .= "Content-type:text/plain; charset=iso-8859-1\r\n";
			$header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
			$header .= $message."\r\n\r\n";
			$header .= "--".$uid."\r\n";
			$header .= "Content-Type: application/octet-stream; name=\"".$filename."\"\r\n"; // use diff. tyoes here
			$header .= "Content-Transfer-Encoding: base64\r\n";
			$header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
			$header .= $content."\r\n\r\n";
			$header .= "--".$uid."--";

			if (mail($mailto, $subject, "", $header)) {
				return true;
			} else {
				return false;
			}
		} else {
			$header = "From: ".($this -> from_name)." <".($this -> from).">\r\n";
			$header .= "Reply-To: ".($this -> reply_to)."\r\n";

			if (mail($this -> to, $this -> subject, $this -> message, $header)) {
				return true;
			} else {
				return false;
			}

		}
	}
}

The Usage:

For example, there’s this file residing on your web server at the path: /home/racker/gift.jpg and you want it attached to an email you are sending to Marry:

$sendit = new AttachmentEmail('marry@example.com', 'Merry Christmas!', 'Hi', '/home/racker/gift.jpg');
$sendit -> mail();

The last argument ($attachment_filename) can be left empty if a filename is included in the second to last argument ($attachment). Otherwise you have to make clear what the file name is so the class can grab it and send it via attachment.

It returns true if the delivery is successful, otherwise false.

Categories
Free PHP Classes & Library PDF Tips & Tutorials

Generating PDF documents with PHP

I generate, oh no, I mean PHP generates the PDF version of all the blog posts I have here by this library, but I think this one‘s a lot easier!

Giving it a try sometime later, thanks Dan for the find!

Yeah, yeah, I know I know, I could have posted this to twitter by nature of microblogging. I’m just trying to be more casual and to be myself for a while.

I hate most of the social medias that are no more than just pompous distractions providing little value if at all.

Update: Better libraries to accomplish the job of converting HTML/CSS to PDF documents might be HTML2PDF and PrinceXML.

Categories
Free PHP Classes & Library PHP Tips & Tutorials

PHP: File Upload Script (HTML Form + PHP Handler Class)

It’s sometimes cumbersome to handle uploaded files – checking if it is really uploaded, moving and renaming. Why not writing all these chores into a class and make our own file upload script?

First we are going to create a simple class to handle uploaded files and move them to some place we designate for convenient access.

The PHP Class (PHP5, Uploaded.class.php)
<?php
class Uploaded {
	private $field_name = '';
	// $field_name is the name of the input in uploading form
	public function __construct($field_name) {
		$this -> field_name = $field_name;
	}
	// $path is the path to the directory where
	// the uploaded file you want stored.
	// $primary_name is the primary part of the
	// file name you want the new name of the uploaded file to be
	// such as 'song' with 'song.mp3'. The extensions part of the
	// new name will be determined from that of the uploaded one.
	public function getFileName($path, $primary_name = '') {
		if (empty($path)) {
			return false;
		}
		if (empty($primary_name)) {
			// Use microtime() as temporary file name if no $primary_name is given
			$primary_name = microtime();
		}
		if (is_uploaded_file($_FILES[$this -> field_name]['tmp_name'])) {
			$client_name = basename($_FILES[$this -> field_name]['name']);
			$ext = substr($client_name, strrpos($client_name, '.'));
			$server_name = $primary_name.$ext;
			if (file_exists($path.$server_name)) {
				// deleting any existing files with the same name here
				// so that the old file can be updated this way.
				unlink($path.$server_name);
			}
			if (move_uploaded_file($_FILES[$this -> field_name]['tmp_name'], $path.$server_name)) {
				// The new name of the uploaded file will be returned
				// for access and retrieval of it.
				return $server_name;
			}
		}
		return false;
	}
}
?>

To adapt this class to PHP4, read this.

The HTML
<form enctype="multipart/form-data" method="post" action="upload.php">
	<input type="file" name="photo" />
	<button type="submit" name="submit">Submit</button>
</form>

Fair enough, now we know browsers are going to send upload.php a file accessible in $_FILES via ‘photo’.

The PHP (upload.php)

Now we will use the Uploaded class (Uploaded.class.php) to handle the file sent from the HTML uploading form above.

<?php
require_once('Uploaded.class.php');
if (isset($_POST['submit'])) {
	$myPhoto = new Uploaded('photo');
	$photoFileName = $myPhoto -> getFileName('uploaded/photos/', 'new_name');
}
?>

The uploaded file will now be all ready and accessible in uploaded/photos/new_name.ext (ext is whatever file extension the original file has) with $photoFileName containing its new name.

Categories
Free PHP Classes & Library PHP Tips & Tutorials

PHP: Resize Image and Store to File

While there are a lot of methods for you to resize images with php, we will be using extension gd this time. Make sure you or your hosting company has installed it in the php distribution by running

<?php
if (extension_loaded('gd')) { // return true if the extension’s loaded.
	echo 'Installed.';
} else {
	if (dl('gd.so')) { // dl() loads php extensions on the fly.
		echo 'Installed.';
	} else {
		echo 'Not installed.';
	}
}
?>

If the output is ‘Installed.’, let’s proceed to resize some images in php.

This image resize script is meant for shot photos because it works better with bitmap images such as .jpg and .bmp. If you need to keep transparency in the output, the code below will not help you.

PHP Resize Image Class

Basically, this class is created with the source image ($originalFile, the full path to the image) to be resized. When you initiate method resize() which takes in 2 parameters, new width ($newWidth) and the target file ($targetFile, full path to the destination image file) that would be storing the resized image, it goes like this:

  1. Get the original width and height of the image.
  2. Calculate the new height given the new width – you could easily tweak the code yourself to resize the image by a new height.
  3. Resize the image by the help of gd.
  4. Store the resized image in $targetFile, optionally erasing the old file before dumping the data because chances are you just want to resize the image and don’t need the old version anymore. However, if it’s just a temporary resize, make $targetFile different from $originalFile.
Class (PHP5):
class ImgResizer {
	private $originalFile = '';
	public function __construct($originalFile = '') {
		$this -> originalFile = $originalFile;
	}
	public function resize($newWidth, $targetFile) {
		if (empty($newWidth) || empty($targetFile)) {
			return false;
		}
		$src = imagecreatefromjpeg($this -> originalFile);
		list($width, $height) = getimagesize($this -> originalFile);
		$newHeight = ($height / $width) * $newWidth;
		$tmp = imagecreatetruecolor($newWidth, $newHeight);
		imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
		if (file_exists($targetFile)) {
			unlink($targetFile);
		}
		imagejpeg($tmp, $targetFile, 85); // 85 is my choice, make it between 0 – 100 for output image quality with 100 being the most luxurious
	}
}
Class (PHP4):
class ImgResizer {
	var $originalFile = '';
	function ImgResizer($originalFile = '') {
		$this -> originalFile = $originalFile;
	}
	function resize($newWidth, $targetFile) {
		if (empty($newWidth) || empty($targetFile)) {
			return false;
		}
		$src = imagecreatefromjpeg($this -> originalFile);
		list($width, $height) = getimagesize($this -> originalFile);
		$newHeight = ($height / $width) * $newWidth;
		$tmp = imagecreatetruecolor($newWidth, $newHeight);
		imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
		if (file_exists($targetFile)) {
			unlink($targetFile);
		}
		imagejpeg($tmp, $targetFile, 85);
	}
}
Class usage
<?php

$work = new ImgResizer('img/me.jpg'); // me.jpg (800x600) is in directory ‘img’ in the same path as this php script.
$work -> resize(400, 'img/me.jpg'); // the old me.jpg (800x600) is now replaced and overwritten with a smaller me.jpg (400x300).

// To store resized image to a new file thus retaining the 800x600 version of me.jpg, go with this instead:
// $work -> resize(400, 'img/me_smaller.jpg');

?>

As I have said, you might want to resize the image by a new height and calculate the width instead of going the other way around as I’ve done thus far, and it’s easy to make your tweak in the class above because height and width are fundamentally the same in dimensions, and no one’s more privileged over the other.

Categories
Free PHP Classes & Library PHP Tips & Tutorials

What is PHP framework & Who are the Best PHP Frameworks?

Basically, PHP frameworks are programming layers that are promoted above PHP itself and that are much easier and quicker to deploy, normalizing and packaging 80% of the routines one is expected to work on without them, such as database interfaces. Therefore they free you from the chores of coding from very scratch line by line and do the common tasks that are shared among most of the projects for you.

Like many other frameworks, PHP frameworks such as the Code Igniter and CakePHP are built upon the MVC model. MVC stands for Model, View and Controller.

Model is essentially a prototype of all similar entities bearing shared descriptive properties. In the database, a table can almost always be interpreted as a model.

View prescribes how the data(models) are presented(in the browser, as webpages for example). In most cases, a view is a webpage template.

Controller is the control hub that can be directly manipulated to control other stuff, namely models and views. It’s where the logic lies in your PHP applications.

3 major PHP frameworks:

1. Code Igniter, is well documented and has a shorter learning curve, thus more appealing to beginners.
2. CakePHP, is more of cup of tea for veteran PHP developers. As intuitive to use as CI, but not as well documented and the learning curve might be a little too long.
3. Smarty, I don’t know much about this one and only tried it once. It’s more like a templating system than a framework, I think. If you don’t plan to add registration functionalities, session management and things like that, you can go with Smarty, though CI and cake can also do a good job in templating.

Update: There’s also a 4th greatly renowned php framework that is Zend Framework. All seems well done and I’m gonna try it out for one of my recent projects soon.