Feed Aggregator v1.4

A CakePHP Component that will take a list of feeds and aggregate them into a single array based on their timestamp.

5 custom PHP functions: Strings

Tuesday, January 27th 2009, 12:33am
Topics: Tutorials, PHP & MySQL
Tags: String, Function, Php, Custom
Views: 37,795, Comments: 17

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.

Update! Second series has been posted: Date/Time

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
 */
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
 */
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
 */
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".



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
 */
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.

17 Comments

10 / 2 = ?
Allowed: [code] [b] [i] [u]
  • Mingan
    prazskycyk...ogspot.com
    Jan 27th 2009, 05:55
    1 Nice functions, may me useful.

    There's one thing I want to mention. I'm Czech and Czech alphabet isn't really URL-friendly. Therefore I have to use some sort of "slugify" function. My favourite choice is friendly_url by Jakub Vrána (http://php.vrana.cz/vytvoreni-pratelskeho-url.php) using iconv. Although I must admit there can be problems with implementation of iconv library and its different versions. Anyway this function can be used as an alternative to the one you created.
  • Lee
    Feb 10th 2009, 17:47
    2 Nice functions there dude. However your slugify one has an error:

    Warning: preg_replace() [function.preg-replace]: Compilation failed: nothing to repeat at offset 6 in friendly_urls.php on line 28
  • Miles Johnson
    www.milesj.me
    Feb 10th 2009, 19:57
    3 @Lee - I replaced the one above with a more updated one, although that might not fix the problem. I just tested it on my localhost and its working.

    It is most likely caused from the $map variable. You need to be saving your php/files as UTF-8 so that those special characters aren't encoded incorrectly. If that doesn't work, comment out the $map variable and the first preg_replace().
  • Sean Delaney
    www.seande...aney.co.uk
    Feb 11th 2009, 01:47
    4 These code snippets are going to be very useful!

    Bookmarked!

  • guyblade
    Apr 22nd 2009, 01:01
    5 Your truncate function will cause a 26 or 27 character string to be longer when truncated than when left alone.

  • Wittedruif
    www.markva...meerten.nl
    May 8th 2009, 05:47
    6 @miles, greet functions thanks. I might see myself using the slugify function.

    I got the same error as Lee. Turns out its a regular expression error. The question marks in the map are not escaped and breaks down the expression.

    Change '/è|é|ê|?|ë/' => 'e',
    to '/è|é|ê|\?|ë/' => 'e',

    Change '/ù|ú|?|û/' => 'u',
    to '/ù|ú|\?|û/' => 'u',

    And that makes it work for me.
  • Miles Johnson
    www.milesj.me
    May 8th 2009, 14:09
    7 @guyblade - This is correct in some instances, but rarely does an ellipsis take up much room.

    @Wittedruif - I think the problem is my blog post is not displaying the characters correctly, the ? should be a character not a ?. I think ill upload a file somewhere to download the correct one.
  • Wittedruif
    www.markva...meerten.nl
    May 9th 2009, 01:50
    8 @lee, I was wondering what those question marks were for. They obvious have to be an e and u like the a. Maybe I can find them myself. Thanks for the reply.
  • alain
    May 29th 2009, 15:37
    9 a better truncate function:

    /**
     * Return a fragment of a text, up to $length characters long, with an ellipsis after it.
     *
     * @param string $text      Text to be truncated.
     * @param integer $length   Max length of text.
     * @param string $ellipsis  Sign to print after truncated text.
     * @return string Fragment
     * @access public
     */
        function fragment($text, $length, $ellipsis = '...') {
            $soft = $length - 5;
            $hard = $length + 5;
            $rx = '/(.{' . $soft . ',' . $hard . '})[\s,\.:\/="!\(\)<>~\[\]]+.*/';
    
            if (preg_match($rx, $text, $r)) {
                $out = $r[1];
            } else {
                $out = substr($text, 0, $length);
            }
            $out = $out . (strlen($out) < strlen($text) ? $ellipsis : null);
            return $out;
        }
  • Miles Johnson
    www.milesj.me
    May 30th 2009, 02:14
    10 @alain - I wouldn't say its a better function, just an alternative. Although it seems like it would be slower since your doing regex.
  • david
    Jun 8th 2009, 08:12
    11 With the truncate function if you have set the limit too small it's possible you end up with the ellipsis as the output. If the word just ends on the limit it will be removed which isn't good i think.
    For the first scenario you could add a check for the presence of spaces in the limited string. For the second scenario you could add a check if a space is present directly behind the limit.

    Why not use the strtr function in the slugify function, it's faster, and then you don't have to use the array_keys and array_values functions. The reworked function.

    function slugify($text) {
    	$map = array(
    		'à' => 'a',
                    'á' => 'a',
                    'å' => 'a',
                    'â' => 'a',
    		'è' => 'e',
                    'é' => 'e',
                    'ê' => 'e',
                    'ë' => 'e',
    		/* removed i/o/u to save myself some time */
    		'ç' => 'c',
    		'ñ' => 'n',
    		'ä' => 'ae',
    		'ö' => 'oe',
    		'ü' => 'ue',
    		'Ä' => 'Ae',
    		'Ü' => 'Ue',
    		'Ö' => 'Oe',
    		'ß' => 'ss',
                    /* now that we are replacing bring the str_replace values */
    		'-' => '_',
                    ' ' => '-',
                    '&' => 'and'
    	);
    		
    	$text = strtr($text,$map);
            $text = preg_replace('/[^-a-zA-Z0-9&\s_]/i' , '', $text);
    	$text = trim(strtolower($text));
    	$text = urlencode($text);
    	
    	return $text;
    }
  • buggedcom
    www.buggedcom.co.uk
    Jun 8th 2009, 22:40
    12 You're slugify character map could benefit from more character replacements. This is the function I use

    function convertAccentedCharacters($string)
    {
    	return strtr($string, 'ŠŒŽšœžŸ¥µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ', 'SOZsozYYuAAAAAAACEEEEIIIIDNOOOOOOUUUUYsaaaaaaaceeeeiiiionoooooouuuuyy'); 
    }
  • jaimeeee
    jaimeeee.com
    Jun 20th 2009, 12:52
    13 The listing function is also great, but there is one bug, I start using it, but my arrays sometimes are just 1 item, so it always showed the "and" before the only item, i tried this:
    function listing($items, $and = 'and') {
    	if (is_array($items)) {
    		$lastItem = array_pop($items);
    		$items = implode(', ', $items);
    		$items = $items ? $items .' '. $and .' '. $lastItem : $lastItem;
    	}
    	return $items;
    }
    
  • Borellus
    www.borellus.com
    Jun 23rd 2009, 11:38
    14 Nce one, thies may come in hand one day :)
  • hire php developer
    www.itgodz.com
    Jul 16th 2009, 02:53
    15 hey nice code thanks