Page 1 of 2

Utility Functions

Posted: Mon Jul 07, 2003 12:27 pm
by McGruff
What are your favourite user-defined functions? Post short utility scripts here.

Code: Select all

<?php
// stripslash an array
function stripper(&$array) {

    foreach ($array as $key=>$value) {
        
        $array[$key] = stripslashes($value);
    }
}

// above fn avoids lots of stripslashing and so tidies up the code
// commonly used on $result arrays eg:

while ($result = mysql_fetch_assoc($query)) {

    stripper($result);
    // ..other code
}

// other utilities I use to tidy up code:

// process vars for db insertion
function dbSafe(&$array) {

    foreach ($array as $key=>$value) {

        $array[$key] = mysql_escape_string($value);
    }
}

// browser safe array
function formSafe(&$array) {

    foreach ($array as $key=>$value) {

        $array[$key] = htmlspecialchars(trim($value));
    }
}

// prepare an array for db storage
function dbSafeArray(&$array) {

    $array = serialize($array);
    $array = mysql_escape_string($array);
}

// restore a serialized array retrieved from db
function dbRestoreArray(&$array) {

    $array = unserialize($array);
    reset($array);
    stripper($array);
}
?>

Posted: Mon Jul 07, 2003 1:08 pm
by daven
My personal favorite is my form element creation class. Saves a lot of annoyance when creating form-driven pages.

Code: Select all

<?php
###################################################
# form_element.php
# class to create form elements
#--------------------------------------------------
# Author: 			Daven Williams
# Last Modified: 	2003-06-20
#--------------------------------------------------
# Individual functions describe how they employ
# the variables ($params, $item_array, $label)
###################################################
// Functions to make form elements
class form_element{
	var $name;
	var $value;
	var $params;
	var $label;
	var $item_array;
	
	function form_element(){
		$name='';
		$value='';
		$params=array();
		$label='';
		$item_array=array();
	}
	// $params is a single item array (used for javascript)
		//	ex: $params[0]='onclick="javascript_function()"'
	function button($name,$value,$params=array()){
		return '<input type="button" name="'.$name.'" value="'.$value.'" '.$params[0].'>';
	}
	// $params is a single dimensional array
		// 	ex: $params[0]='onclick="javascript_function()"', $params[1]='checked';
	function checkbox($name,$value,$params=array()){
		$line='<input type="checkbox" name="'.$name.'" value="'.$value.'"';
		if(count($params)>0){
			for($i=0;$i<count($params);$i++){
				$line.=' '.$params[$i];
			}
		}
		$line.='>';
		return $line;
	}
	function hidden($name,$value){
		return '<input type="hidden" name="'.$name.'" value="'.$value.'">';
	}
	// $params same as in checkbox()
	function radio($name,$value,$params=array()){
		$line='<input type="radio" name="'.$name.'" value="'.$value.'"';
		if(count($params)>0){
			for($i=0;$i<count($params);$i++){
				$line.=' '.$params[$i];
			}
		}
		$line.='>';
		return $line;
	}
	
	// notes:
	// 1.	$params is an array of extra parameters which go in the <select> tag
	//		ex: params[0]='"style=width:275px"', params[1]='onchange="javascript_function()"'
	// 2.	$label is the first <option> to place in the select (useful for null values)
	// 		ex: $label='<option value="">Choose an Item</option>'
	// 3.	$item_array is a two dimensional array of data to populate the select with
	// 		ex: $item_array['dept_ID'][0]=5, $item_array['dept_Name'][0]="Technical"
	function select($name,$value='',$params=array(),$label='',$item_array=array()){
		$line='<select name="'.$name.'"';
		if(count($params)>0){
			for($i=0;$i<count($params);$i++){
				$line.=' '.$params[$i];
			}
		}
		$line.='>';
		$line.=$label;
		if(count($item_array)>0){
			list($id,$disp)=array_keys($item_array);
			for($i=0;$i<count($item_array[$id]);$i++){
				$line.=($item_array[$id][$i]==$value)?
					'<option value="'.$item_array[$id][$i].'" selected>'.$item_array[$disp][$i].'</option>'
					:'<option value="'.$item_array[$id][$i].'">'.$item_array[$disp][$i].'</option>';
			}
		}
		$line.= '</select>';
		return $line;
	}
	function submit($name,$value){
		return '<input type="submit" name="'.$name.'" value="'.$value.'">';
	}
	// params is a one-dimensional array of stuff
		// ex: $params[0]='size="50"', $params[1]='maxlength="50"'
	function text($name,$value='',$params=array()){
		$line='<input type="text" name="'.$name.'" value="'.$value.'"';
		if(count($params)>0){
			for($i=0;$i<count($params);$i++){
				$line.=' '.$params[$i];
			}
		}
		$line.='>';
		return $line;
	}
	// params is an array of options for the text area
		//	ex: $params[0]='cols="50"',$params[1]='rows="20"'
	function textarea($name,$value='',$params=array()){
		$line='<textarea name="'.$name.'"';
		if(count($params)>0){
			for($i=0;$i<count($params);$i++){
				$line.=' '.$params[$i];
			}
		}
		$line.='>'.$value.'</textarea>';
	}
}
?>
Example of use

Code: Select all

<?php
include "./form_element.php";
$e=new form_element();
$text_params=array('size="50"','maxlength="100"');

// makes a form with one text box and two radio buttons
echo '<form name="myform" action="action_page">';
echo $e->text('TheTextElement','hello world',$text_params);
echo $e->radio('radio1','adios',array());
echo $e->radio('radio1','goodbye',array());
echo '</form>';
?>

Posted: Thu Jul 10, 2003 10:01 am
by McGruff
Yeah I've got a variation on that - very handy.

Anyone else want to share some general utilities?

Posted: Thu Jul 10, 2003 10:40 am
by ik
Well, is it contribution to PHP-classes instead of? 8)

The follwing is navigation bar, horisontal (with arbitrary separators) or vertical (tab-column, <p> separated or item-list).

CSS classes are generally using in it to control look.

Code: Select all

//simple formatting utils using in class
function tag_close($s) 
{
  return "</".$s.">";
}

function tag_echo($tag,$var,$arg="")
{
  return tag_open($tag,$arg).$var.tag_close($tag);
}

function ref_echo($key,$val) {
  $s='href='.'"'.$val.'"';
  return tag_echo("a",$key,$s);
}

//Navigation bar
class TNavBar {
  var $items="";
  var $prop="";

  function TNavBar($items, $prop="") {
      $def_prop=array(
	    "direction"=>"h",
		"arg"=>"",
		"type"=>"str",
		"div"=>"|"
	  );
	  $this->prop=$def_prop;
	  $this->items=$items;
	  if ($prop)
	  foreach($prop as $key=>$val) {
		  $this->prop[$key]=$val;
	  } 
  }
  
  function DrawRow() {
    $res="";
   $type=strtolower($this->prop["type"]);
   $arg=$this->prop["arg"];
   $div=$this->prop["div"];

	switch ($type) {
	  case "tab":
		if ($div) $res.=tag_echo("td",$div,$arg);
	    foreach($this->items as $key=>$val) {
	      $res.=tag_echo("td",ref_echo($key,$val),$arg);
		  if ($div) $res.=tag_echo("td",$div,$arg);
		}
		$res=tag_echo("tr",$res);
	    break; 
	 case "str":
        $res= $div;
	    foreach($this->items as $key=>$val) {
          $res.=ref_echo($key,$val).$div;
		}
		break;  
	}
    return $res;
  }

//example
$pages=array("home"=>"index.php",
                 "database"=>"tables.php",
                 "feedback"=>"feedback.php",
                 "software"=>"software.php",
                 "news"=>"news.php"
 );
$prop=array(
		  "direction"=>"v",
		  "type"=>"tab",
		  "arg"=>'class="vnavtab"',
		  "caption"=>"Pages"
);
$main_nav_bar=new TNavBar($pages,$prop);
....
$main_nav_bar->Draw();

Posted: Thu Jul 10, 2003 10:43 am
by ik
Sorry :) It was only half of class code in the previous message.

Code: Select all

class TNavBar {
  var $items="";
  var $prop="";

  function TNavBar($items, $prop="") {
      $def_prop=array(
	    "direction"=>"h",
		"arg"=>"",
		"type"=>"str",
		"div"=>"|"
	  );
	  $this->prop=$def_prop;
	  $this->items=$items;
	  if ($prop)
	  foreach($prop as $key=>$val) {
		  $this->prop[$key]=$val;
	  } 
  }
  
  function DrawRow() {
    $res="";
	$type=strtolower($this->prop["type"]);
	$arg=$this->prop["arg"];
	$div=$this->prop["div"];

	switch ($type) {
	  case "tab":
		if ($div) $res.=tag_echo("td",$div,$arg);
	    foreach($this->items as $key=>$val) {
	      $res.=tag_echo("td",ref_echo($key,$val),$arg);
		  if ($div) $res.=tag_echo("td",$div,$arg);
		}
		$res=tag_echo("tr",$res);
	    break; 
	 case "str":
        $res= $div;
	    foreach($this->items as $key=>$val) {
          $res.=ref_echo($key,$val).$div;
		}
		break;  
	}
    return $res;
  }
  
  function DrawColumn() 
  {
    $res="";
	$type=strtolower($this->prop["type"]);
	$arg=$this->prop["arg"];
	$div=$this->prop["div"];
	switch($type) {
	   case "str":
	     foreach($this->items as $key=>$val)		 {
           $res.=tag_echo($div,ref_echo($key,$val),$arg); 
		 }		 
		 break;
	   case "ul":
	     foreach($this->items as $key=>$val)  {
           $res.=tag_echo("li",ref_echo($key,$val),$arg); 
		 }		 
		 break;
	   case "tab":
	     $arg=$this->prop["arg"];
	     if (isset($this->prop["caption"]) && $this->prop["caption"])
		 $res.=tag_echo("th",$this->prop["caption"],$arg);
		 foreach($this->items as $key=>$val) {
           $res.=tag_echo("TR",tag_echo("TD",ref_echo($key,$val),$arg),$arg);
		 }
		 break;
	}
    return $res;  
  }
  
  function DrawHBar()  
  {
    $res="";
	$type=strtolower($this->prop["type"]);
	$arg=$this->prop["arg"];
	$div=$this->prop["div"];
	switch ($type) {
	  case "tab":
	     return tag_echo("table", $this->DrawRow(),$arg);
	  default:
	     return $this->DrawRow();
	}
  }

  function DrawVBar()  
  {
    $res="";
	$type=strtolower($this->prop["type"]);
	$arg=$this->prop["arg"];
	$div=$this->prop["div"];
    switch ($type) {
	  case "tab":
	    return tag_echo("table",$this->DrawColumn(),$arg);
      case "str":
	    return tag_echo($div,$this->DrawColumn());
      case "ul":
	    return tag_echo("ul",$this->DrawColumn());
	}
  }
  
  function Draw()  
  {
	 $direction=strtolower($this->prop["direction"]);
	 switch ($direction) {
	   case "h":
	     return $this->DrawHBar();
	   case "v":
	     return $this->DrawVBar();
	   default:
	     return "";
	 }	 
  }
}

Posted: Thu Jul 10, 2003 10:59 am
by Net_Monkey
If you wanted to modify your original stripper function to make it even more useful, you could use it to handle multi-dimensional arrays with a recursive function call:

Code: Select all

<?php

function stripper($array) {
    foreach ($array as $key => $value) {
        if (is_array($array[$key])) {
            $array[$key] = stripper($array[$key]);
        } else {
            $array[$key] = stripslashes($value);
        }
    }
	
	return $array;
}

?>
Regards,
Pete

Posted: Thu Jul 10, 2003 11:02 am
by McGruff
I should have explained in more detail what I meant by a utility function. The requirements are:

- A utility is a small subfunction you can use widely throughout your scripts, often a short code snippet although something longer like the form element class above would fit the definition.

- A utility tidies up your code, making it easier to read and understand what's going on (the stripper fn I posted for example cuts out a lot of stripslashing - for the magic quote-less among us) - that's the whole point of using utilities.

I was hoping that we'd get a lot of samples here and, possibly, publish some in a code section (with the submitter's permission).

Short(-ish) blocks of code are good for beginning programmers to cut their teeth on, and the idea of writing utilities - easy to understand code with "control" levels and subfunctons - is maybe a first step towards good application design.

Posted: Thu Jul 10, 2003 11:04 am
by McGruff
Net_Monkey wrote:If you wanted to modify your original stripper function to make it even more useful, you could use it to handle multi-dimensional arrays with a recursive function call:

Code: Select all

<?php

function stripper($array) {
    foreach ($array as $key => $value) {
        if (is_array($array[$key])) {
            $array[$key] = stripper($array[$key]);
        } else {
            $array[$key] = stripslashes($value);
        }
    }
	
	return $array;
}

?>
Regards,
Pete
Rgr. I wrote this mainly for processing arrays fetched from database queries. If I had multi-dimensional arrays to deal with as well, I'd maybe create both - a stripper() for one-dimensional arrays and stripperM() for multi-dimensional ones.

Posted: Thu Jul 10, 2003 11:15 am
by nielsene
Here's a sampling of some of the ones I use:

This first one is used to propagate a sessionid across a header redirection, when the user has denied the cookie (so GET style must be used) because PHP does not consider this case for sessionid propagation. I never use GET style for other purposes, so I don't test for a '?' already present in the $url. If you regular use GET, you'll need to add a test in the else to check for an '?', if present append an '&' instead of '?'....

Code: Select all

function localRedirect($url)
{
    if (isset($_COOKIE["PHPSESSID"]))
        header("Location: $url");
    else
        header("Location: $url?" .SID);
}
This second one is used to clean a string of xhtml tags using an explicit list of allowed tags. It also fixes problems where a closing tag was left off. This is one is probably over-commented, but regular expressions often warrant the extra description....

Code: Select all

function sanitizeXHTML($string,$allowedTags=array())
{
  foreach($allowedTags as $tag)
    {
      // handle all allowed, paired tags
      $string = ereg_replace("<$tag(.*)>(.*)</$tag>",
                             "[$tag\\1]\\2[/$tag]",$string);
      // handle all empty tags
      $string = ereg_replace("<$tag(.*) \\>",
                             "[$tag\\1\\]",$string);
    }
  // string all disallowed paired tag, leave tagged text
  $string = ereg_replace("<.*>(.*)</.*>","\\1",$string);
  // string all disallowed empty tags AND all allowed paired without pair
  $string = ereg_replace("<.*>","",$string);
  foreach($allowedTags as $tag)
    {
      // convert paired back to html
      $string = ereg_replace("\[$tag(.*)\](.*)\[/$tag\]",
                             "<$tag\\1>\\2</$tag>",$string);
      // convert empty back to html
      $string = ereg_replace("\[$tag(.*) \\\]",
                             "<$tag\\1\\>",$string);
    }
  return $string;
}

Posted: Thu Jul 10, 2003 11:28 am
by ik
Ok, I see you point.

So, simple tag-formatting utilities (I have already put them).

Code: Select all

<?php

//Service function: Open tag $tag with attrbutes
function tag_open($tag,$arg="") 
{
  $res="\n<".$tag;
  if ($arg) $res.=" ".$arg;
  $res.=">";
  return $res;
}

//Service: Close tag
function tag_close($s) 
{
  return "</".$s.">";
}

//Main function for use: Return full tagged item 
function tag_echo($tag,$var,$arg="")
{
  return tag_open($tag,$arg).$var.tag_close($tag);
}

//Useful special case - for links
function ref_echo($key,$val) {
  $s='href='.'"'.$val.'"';
  return tag_echo("a",$key,$s);
}

?>
I have found tag_echo() very useful (I'm lazy to remember which tags are currently opened), especially with recursive use.

i.e to draw table we have:

Code: Select all

<?php

//two-dim array
$data=...
$res="";

for($i=0;$i<count($data);$i++) 
{
   $s="";
   foreach($data[i] as $key=>$val)
   {
        $s.=tag_echo("td"$val);
    }
    $res.=tag_echo("tr",$s);
}

$res=tag_echo("table",$res);
echo $res;

?>

Posted: Thu Jul 10, 2003 11:38 am
by Net_Monkey
McGruff wrote:Rgr. I wrote this mainly for processing arrays fetched from database queries. If I had multi-dimensional arrays to deal with as well, I'd maybe create both - a stripper() for one-dimensional arrays and stripperM() for multi-dimensional ones.
Why do with two functions what you can do with one? I really am curious -- I tend to write one function and then include a simple if to check and see if it's a normal string or several string values as array elements. Then I just loop if it's an array. In this case, it seems more efficient to have a check that determines the type of data that was supplied and then continues through.

As for your intent to deal with fetched arrays from queries, I actually made the modifications (to handle multi-dim arrays) for the same reason. I have a class I use that returns my recordset as a simple multi-dimensional array. Makes my life a lot easier if my boss ever decides he wants to add another database back-end option other than MySQL (which we've started talking about)...

Regards,
Pete

Posted: Thu Jul 10, 2003 11:43 am
by ik
Net_Monkey wrote:
McGruff wrote:
As for your intent to deal with fetched arrays from queries, I actually made the modifications (to handle multi-dim arrays) for the same reason. I have a class I use that returns my recordset as a simple multi-dimensional array. Makes my life a lot easier if my boss ever decides he wants to add another database back-end option other than MySQL (which we've started talking about)...

Regards,
Pete
Yeah, so do I. For me the main reason to do sois that fetch functions are DBMS-depending. So it's better to put result to conventional multidim array as soon as possible and to deal with universal structure.

Posted: Thu Jul 10, 2003 11:43 am
by McGruff
NetMonkey: Why do with two functions what you can do with one?
Well, I guess it's a little more efficient by saving on unecessary IF steps in the one-dimensional array case - not that it probably matters much in practice.

I used to be notorious for being over-obsessed with effiency - guess I haven't quite got it out of my system :wink:

Good point about supporting dbs other than mysql.

Posted: Thu Jul 10, 2003 11:56 am
by Net_Monkey
McGruff wrote:Well, I guess it's a little more efficient by saving on unecessary IF steps in the one-dimensional array case - not that it probably matters much in practice.

I used to be notorious for being over-obsessed with effiency - guess I haven't quite got it out of my system :wink:

Good point about supporting dbs other than mysql.
heh... That's OK. I need to get better at writing efficient code in the first place (I usually realize there's a problem and have to go back and re-work things). I've been improving, but I know there's more I can do.

As far as supporting other DBs, I'm up for whatever works. MySQL has served us quite well the last few years, so there hasn't been any reason to change. With some of the discussions I've seen about PostgreSQL here, we started talking about possibly adding it as an option...

Posted: Thu Jul 10, 2003 12:02 pm
by Net_Monkey
ik wrote:Yeah, so do I. For me the main reason to do sois that fetch functions are DBMS-depending. So it's better to put result to conventional multidim array as soon as possible and to deal with universal structure.
That was my precise reasoning. I didn't do it till I'd learned more about programming, but the DB class was the first one I wrote -- followed quickly by a template class.

The driving force behind doing it at the time was because we also have a single Windows server and there was talk about possibly writing db-driven apps that would interface with the MS SQL Server. I wrote the class so I could port programs I wrote to the Windows box and just rewrite the DB class to use mssql_* functions.

Of course, I've since learned that the Windows PHP version tends to interpret things a little different than our Linux box, so I've never had to port anything to the Windows platform -- it's all been custom... :)