Little Functions

A thread for sharing little functions (100 lines or less) that you use.

This first function is an enhanced version of PHP’s native empty() function in that it behaves in a more intuitive manner. Prior to PHP 5.3 if you create an object and don’t set the magic __isset() function empty could return true even when the value is false.

In addition, with arrays it’s often useful to know if all the values of the array are empty even if the keys have been set. It also returns true if you pass it a multidimensional array where all the values are empty or are arrays of empty values.


function isEmpty( $val ) {
	if (is_array($val)) {
		foreach ( $val as $value ) {
			if ( is_array($value)) {
				$return = isEmpty($value);
			} else {
				$return = empty( $value );
			}
				
			if (!$return) {
				return false;
			}
		}
		
		return true;
	} else {
		return empty($val);
	}
}

So who else has a small function they’d like to share?

The smallest function I ever made and I use it the most :smiley:

easy for a lot of purposes:


function say($txt)
{
    echo $txt, "<br/>\
";
}

Are you kidding? That’s completely stupid. Not only is the name terribly ambiguous, but you are using <br />'s instead of <p>'s.

Here is a few from my utility class:



    /**
     *
     * @param   string  $file
     * @param   string  $data
     * @param   boolean $appendIfExists
     */
    public static function logToFile($file, $data, $appendIfExists = true)
    {
        // Path is like: /log/ENV_YYYY-MM-DD/$file.log
        $file = sfConfig::get('sf_log_dir')
            .'/'.sfConfig::get('sf_environment').'_'.date('Y-m-d')
            .'/'.$file.'.log';
        $dir = dirname($file);

        if (!is_dir($dir))
        {
            mkdir($dir, 0777, true);
        }

        // If appending, add a trailing line break so the entries are readable...
        if ($appendIfExists)
        {
            $data = trim($data)."\
";
        }

        file_put_contents(
            $file,
            $data,
            ($appendIfExists ? FILE_APPEND : 0)
        );
    }


    /**
     * Convert an array or collection (implementing Iterator) to an array of ids.
     *
     * @param   mixed $objs
     * @return  array
     */
    public static function getObjectIds($objs)
    {
        $ids = array();

        foreach ($objs as $obj)
        {
            $ids[] = (integer) $obj->getId();
        }

        return $ids;
    }


    /**
     * Merge a set of options with their defaults.
     *
     * @param   array   $given
     * @param   array   $defaults
     * @return  array
     * @throws  IllegalArgumentException
     */
    public static function mergeOptions(array $given, array $defaults)
    {
        $options = array_merge($defaults, $given);

        if ($illegalOptions = array_diff(array_keys($options), array_keys($defaults)))
        {
            throw new IllegalArgumentException('Unrecognised option(s): '.implode(', ', $illegalOptions));
        }

        return $options;
    }
    /**
     * Generates headers that force a download to happen.
     *
     * @param   string  $filename   The filename to download as.
     * @param   string  $data       Data to be downloaded.
     * @return  void                PHP will stop execution.
     */
    public static function forceDownload($filename, $data)
    {
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="'.$filename.'"');
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Content-Length: '.strlen($data));

        if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE'))
        {
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header('Pragma: public');
        }
        else
        {
            header('Pragma: no-cache');
        }

        echo $data;
        die();
    }


    /**
     * Takes a string and creates a human-friendly URL string.
     *
     * @param   string  The string to convert into a stripped url-friendly version.
     * @param   string  A separator to go between words (defaults to '-'). Must be regex friendly.
     * @param   string  If the string should be made lower-case.
     * @return  string
     */
    public static function strip($value, $separator = '-', $toLower = true)
    {
        // Convert foreign chars to English
        $value = self::foreignCharsToEnglish($value);
        // strtolower isn't UTF8 safe, so do it after the above
        if ($toLower)
        {
            $value = strtolower($value);
        }

        $trans = array(
            '\\s+'                     => $separator,  // Whitespace
            '[^a-zA-Z0-9'.$separator.']' => $separator,          // Non-alphanumerics
            $separator.'+'            => $separator,  // Consecutive seperators to one
            $separator.'$'            => '',          // Seperators at the end of the string
            '^'.$separator            => ''           // Seperators at the start of the string
        );

        foreach ($trans as $search => $replace)
        {
            $value = preg_replace('#'.$search.'#', $replace, $value);
        }

        return $value;
    }


    /**
     * Take a string and convert French, German and Spanish characters
     * to their English equivalents.
     *
     * @param   string $value   The string to convert.
     * @return  string          The string with non-English characters converted to their equivalents.
     */
    public static function foreignCharsToEnglish($value)
    {
        // French
        $value = str_replace(array('À', 'Â', 'à', 'â'), 'a', $value);
        $value = str_replace(array('É', 'È', 'Ê', 'Ë', 'é', 'è', 'ê', 'ë'), 'e', $value);
        $value = str_replace(array('Î', 'Ï', 'î', 'ï'), 'i', $value);
        $value = str_replace(array('Ô', 'ô'), 'o', $value);
        $value = str_replace(array('Ù', 'Û', 'ù', 'û'), 'u', $value);
        $value = str_replace(array('Ç', 'ç'), 'c', $value);

        // German
        $value = str_replace(array('Ä', 'ä'), 'ae', $value);
        $value = str_replace(array('Ö', 'ö'), 'oe', $value);
        $value = str_replace(array('Ü', 'ü'), 'ue', $value);
        $value = str_replace('ß', 'ss', $value);

        // Spanish
        $value = str_replace(array('Ñ', 'ñ'), 'n', $value);
        $value = str_replace(array('Á', 'á'), 'a', $value);
        $value = str_replace(array('Í', 'í'), 'i', $value);
        $value = str_replace(array('Ó', 'ó'), 'o', $value);
        $value = str_replace(array('Ú', 'ú'), 'u', $value);

        return $value;
    }


    /**
     *
     * @param string $string
     * @return string
     */
    public static function stripNonAsciiAndCtrls($string)
    {
        $disallowedChars = array();
        for ($i=0; $i<32; $i++)
        {
            $disallowedChars[] = chr($i);
        }
        for ($i=127; $i<256; $i++)
        {
            $disallowedChars[] = chr($i);
        }
        return str_replace($disallowedChars, '', $string);
    }


    public static function generateRandomKey()
    {
        return base_convert(uniqid(mt_rand(), true), 16, 36);
    }

Off Topic:

Now now, let’s all play nice. More so when all the points raised are purely opinion and not fact.

:wink:

Looks good AlienDev, made even more handy due to the inclusion of PHPDoc blocks.

Can we make these required when posting said requested functions please?

:cool:

My day job is programming Perl, which has this function built in, so for me it is not ambiguous at all… It does exactly the same, echo with a line break.
Guessing that Larry wall, creator of Perl, employee of NASA and Linguist invented this, I don’t think you can call it stupid

And an other note, I don’t use <p> or <br> tags, I use a templating system, so I never echo something out to the web. This is simple in what it does… it is not ment for production…

Don’t jump to conclusions, and don’t call other people’s opinions stupid, everybody diserves respect.



function arrayToComboOptions($array,$current_value='',$ignore_values=''){

        if($ignore_values == '')
            $ignore_values = array(); //init 
            
        $str = '';
        foreach ($array as $key => $value){
	    $selected = "";
            if($key == $current_value)
                $selected = "selected";
            }
            
            if(!in_array($key,$ignore_values)){
                 $str .= '<OPTION value="'.$key.'"'.$selected.'>'.$value.'</option>';
            }
            
        } 
        return $str;
    }

cough PHPDoc ? :wink:

Very simple but very useful… (i think)


function mysql_query_($query){

 $sql = mysql_query($query);

 if(!$sql)
   {
   $error = mysql_real_escape_string(mysql_error());
   $userid = $_SESSION["userid"];
   $query = mysql_real_escape_string($query);
   $url = $_SERVER['REQUEST_URI'];
   
   mysql_query("INSERT INTO query_errorlog (userid, query, mysql_error, url) VALUES ('$userid','$query','$error','$url')");
   
   }
   
  return $sql;

}




You aren’t escaping $_SERVER[‘REQUEST_URI’] – SQL injection! Also, if $userid is an integer, it shouldn’t have quotes around it (only MySQL allows this, so it will break if you change to Pg or something else).

Thanks for that - don’t know how I missed that one, glad you pointed it out! I didn’t know about integers not needing quotes - will sort that out…

Got some more here.

include_javascripts_timestamped() is especially useful IMO, because you can set a far-future expiry date and not have to care about browsers not updating when they need to.


// There is also a include_stylesheets_timestamped(), but I'll leave that out
function include_javascripts_timestamped()
{
    $web = /* get the web dir from config */;
    $javascripts = get_javascripts();

    $html = '';
    foreach ($javascripts as $file)
    {
        if (substr($file, 0, 7) === 'http://')
        {
            $ts = false;
        }
        elseif ($file[0] === '/')
        {
            $ts = filemtime($web.$file);
        }
        else
        {
            $ts = filemtime($web.'/js/'.$file);
        }

        $file = $file.($ts ? '?ts='.$ts : '');
        $html .= '<script type="text/javascript" src="'.$file.'"></script>'."\
";
    }

    echo $html;
}


/**
 *
 * @param BaseRecord $obj
 * @return string <a> tag
 */
function link_to_record(BaseRecord $obj)
{
    switch (get_class($obj))
    {
        case 'Member':
            return '<a href="'.url_for_record($obj).'">'.$obj->getUsername().'</a>';

        case 'Story':
            return '<a href="'.url_for_record($obj).'">'.$obj->getTitle().'</a>';

        default:
            throw new InvalidArgumentException('Can\\'t link to '.get_class($obj));
    }
}


/**
 *
 * @param BaseRecord $obj
 * @param array $options
 * @return string The URL to use in links
 */
function url_for_record(BaseRecord $obj, array $options = array())
{
    switch (get_class($obj))
    {
        case 'Member':
            $route = '@profile?username='.$obj->getUsername();
            break;

        case 'Story':
            $action = (isset($options['action']) ? $options['action'] : 'index');
            $route = '@story?id='.$obj->getId().'&action='.$action;
            break;

        default:
            throw new InvalidArgumentException('Can\\'t make URL for '.get_class($obj));
    }

    return url_for($route, $options);   // change this to however you create URLs in your own code
}

Pretty obvious that’s a debugging function :rolleyes:
I used to use this, but xdebug ftw


function dump($var, $verbose = false)
{
    echo '<pre>';
    if($verbose) { var_dump($var); }
    else { print_r($var); }
    echo '</pre>';
}

I’ve posted this on the forum before but it’s still one of my more useful little functions - I use it every day.


function trace() {
	if (!headers_sent()) {
		header("HTTP/1.0 520 Programmer debug trace");
		header("Content-Type: text/plain");
	}
	
	echo "Trace: \
\
";
	
	foreach (func_get_args() as $item) {
		if (is_array($item) || is_object($item)) {
			print_r($item);
		} else if (is_bool($item)) {
			echo ($item) ? 'true' : 'false';
		} else if (is_null($item)) {
			echo 'Null Var';
		} else {
			echo $item;
		}
		
		echo "\
";
	}
	
	echo "\
\
-----------------------------------------------\
GET:\
";
	print_r($_GET);
	
	echo "\
\
-----------------------------------------------\
POST:\
";
	print_r($_POST);
	
	echo "\
\
-----------------------------------------------\
Stack Trace:\
";
	
	debug_print_backtrace();

	echo "\
\
-----------------------------------------------\
Included Files:\
";
	
	print_r(get_included_files());
	
	exit;
}

This function replaces the technique of inserting echo or print_r in your code followed immediately by exit. It can be overloaded so you can check as many or as few variables as you need. After printing out those variables with print_r or echo (as appropriate) it then does a print_r of the $_GET var, $_POST var, Debug Strack and the included files.

One other wrinkle is that if your code hasn’t sent output yet the trace function will send the headers needed to put the browser in text mode to make reading the print_r results easier.

For today an improved stristr.


<?
/**
 * Find a string in a string. Unlike the native function, this returns
 * boolean only. Also if the needle is an array each value of the array
 * is considered for a match and return true if a match occurs.
 *
 * @param string $haystack
 * @param mixed $needle
 */
function stringInString( $haystack, $needle ) {
	if (is_array($needle)) {
		foreach ($needle as $value) {
			if (stristr($haystack, $value)) {
				return true;
			}
		}
	}
	
	return stristr($haystack, $needle) ? true : false;
}?>


// Remove string from a string
function str_remove( $search, $var = '' ) {
	if ( strpos( $var, $search ) === 0 ) {
		$var = str_replace( $search, '', $var );
	}
	return $var;
}
// Usage
$url = str_remove( 'http://', $url );


// Remove null & emtpy value & corresponding keys from array
function unset_empty_value( $arr ) {
	if ( !is_array( $arr ) ) return;
	foreach($arr as $key => $value) {
		if (!isset($value) || empty($value)) {
			unset($arr[$key]);
		}
	}
	return $arr;
}
// Usage
$url = explode('/', clean($_GET['url']));
// Print_r would give you say Array ( [0] => url0 [1] => ) 
$url = array_remove( $url );
// Array ( [0] => url0) 


// Limit array to a count - for usage with numeric keys
function array_limit( $limit, $arr ) {
	if ( !is_array($arr) ) return;
	foreach ( $arr as $key=>$value ) { 
		if ( $key > $limit ) {
			unset( $arr[$key] );
		}
	}	
	return $arr;
}
$url = array_limit( 1, $url ); //  Limit url array to domain.com/url0/url1


// Initialize an array with defined keys and empty values
function init_array( $arr, $data ) {
	if (!is_array($arr) && !is_array($data)) return;
	foreach ($data as $k=>$v) {
		$arr[$v] = '';
	}
	return $arr;
}
$a = array('a','b');
$post = array();
if (!$_POST) $post = init_array( $post, $a );
else $post = $_POST;
echo '<input type="text" value="'. $post['a'] .'" /><br />';


// Remove invalid keys from array against comparison array
function unset_invalid_key( $auditedArray, $definedArray ) {
	if ( !is_array( $auditedArray ) ) return;
	foreach ($auditedArray as $k=>$v) {
		if (!in_array($k, $definedArray)) {
			unset($k, $v);
		}
		if (isset($k) && isset($v)) {
			$arr[$k] = $v;
		}
	}
	$arr = unset_empty_value($arr);  // from above
	return $arr;
}
$_POST = array( 'blah' =>'bad stuff', 'a' => 'good stuff');
$fields = unset_invalid_key( $_POST, $a );
// $fields = array( 'a' => 'good stuff');

[ot]@centered effect,
some of your functions could be replaced with native php functions if you’re interested.[/ot]

I am, do tell!

To create a thumbnail from flash video with ffmpeg:


class My_Controller_Action_Helper_FlvThumbnail extends Zend_Controller_Action_Helper_Abstract
{
    public function direct($flv, $thumbnail) {
        $command = "ffmpeg -v 0 -y -i $flv -vframes 1 -ss 10 -vcodec mjpeg -f rawvideo -s 210x140 -aspect 16:9 $thumbnail";
        return shell_exec($command);
    }
}

[ot]> I am, do tell!

[FONT=“Monaco,monospace”]unset_empty_value($array)
array_filter($array)

array_limit($num, $array)
array_slice($array, 0, $num)

init_array(???, $keys)
array_fill_keys($keys, “”)

unset_invalid_key($array, $allowed_keys)
array_intersect_key($array, array_flip($allowed_keys))[/FONT]
[/ot]

Why not use [fphp]str_replace[/fphp] or [fphp]str_ireplace[/fphp] directly? The savings on typed characters doesn’t justify the overhead of the function.

Salathe got the other examples where a native function works just as well.