Page 1 of 1

Object base class

Posted: Sun Aug 19, 2007 8:07 am
by yacahuma
Hello,

For a long time I have been using this class and it makes my job a lot easier. I would like to share it with you. Comments are welcome

Code: Select all

<?
class Object 
{

  var $updtFields;
 	function Object($record="")
  {
		  $this->arrayToObject($record);
				
	 } 
	 
	 function arrayToObject($record="")
	 {
       if (is_array($record))
			 {
			   $this->updtFields = array();
	   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
				if (isset($record[$k]))
				{
					//echo "SETTING $k ->" . $record[$k] . "<BR>";
					$this->$k = $record[$k];
					$this->updtFields[] = $k;
				}
			 }	
	 }
	   
   function toDebug()
   {
   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
			echo "$k = [" . $this->$k . "]<BR>\n";
		echo '<HR>';	

  }

   function toXML($octags,$vars=0)
   {
	    $bad = array("&","\r\n" );
      $good  = array("&","");
	    $xml='';
	    if ($octags)
			  $xml='<'. get_class($this) . '>';
   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
			  if ($vars ==0  || in_array($k,$vars))
			     $xml .= "<$k>" . str_replace($bad,$good,html_entity_decode ($this->$k, ENT_QUOTES, 'ISO-8859-1')). "</$k>";
					 
	    if ($octags)
			  $xml .= '</'. get_class($this) . '>';
			return $xml;	

  }
  
   function toStr($ch="\n")
   {
	    $str='';
   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
			{
			   if ($k != 'updtFields')
			      $str .= $k .'=' . urlencode($this->$k) . '&';
			}		
			return $str;		

  }
	
   function toUrl()
   {
	   return $this->ToStr('&');
  }

   function exportAllSet( $inglue = '>', $outglue = '}')
   {
       $return = '';
       foreach ($this->toArrayAllSet() as $tk => $tv)
           $return .= $outglue . $tk . $inglue . $tv;
       return substr($return,strlen($outglue));
   }
  
   function export( $inglue = '>', $outglue = '}')
   {
	    $str='';
   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
			   if ($k != 'updtFields')
			      $str .= $outglue . $k . $inglue . $this->$k;
      return substr($str,strlen($outglue));

   }
  
  
   function import($str, $inglue = ">", $outglue = '}')
   {
       $hash = array();
       foreach (explode($outglue, $str) as $pair)
       {           
           $k2v = explode($inglue, $pair);           
           $hash[$k2v[0]] = $k2v[1];           
       }
       $this->arrayToObject($hash);			 
   }

  function toArray($toTrim)
  {
  		$arr = array();
   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
		{
			if (!in_array ($k, $toTrim)) 
				$arr[$k] = $this->$k;
		}	
		return $arr;	
  }
  
  function toArrayAllSet()
  {
  		$arr = array();
   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
		{
			if (in_array ($k, $this->updtFields)) 
				$arr[$k] = $this->$k;
		}	
		return $arr;	
  }
  function toArrayAllSetExcept($toTrim)
  {
  		$arr = array();
   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
		{
			if (in_array ($k, $this->updtFields) && !in_array ($k, $toTrim)) 
				$arr[$k] = $this->$k;
		}	
		return $arr;	
  }

	
  function trim()
  {
   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
			 if (!is_array($this->$k))
			   $this->$k = trim($this->$k);
  }
	
  function protectStr($string)
  {

		$string = str_replace(";", "", $string);
		return $string;

  }
	
	
	function protect()
	{
   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
			$this->$k = Object::protectStr($this->$k);
	}
	function removeAllTags(){
   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
			$this->$k = Object::html2txt($this->$k);
	}
	
	function html2txt($document)
	{
   $search = array('@<script[^>]*?>.*?</script>@si',  // Strip out javascript
               '@<[\/\!]*?[^<>]*?>@si',            // Strip out HTML tags
               '@<style[^>]*?>.*?</style>@siU',    // Strip style tags properly
               '@<![\s\S]*?--[ \t\n\r]*>@'         // Strip multi-line comments including CDATA
   );
   $text = preg_replace($search, '', $document);
   return $text;
  }
	
	 function json_encode()
   {
	   $encode =''; 
   		foreach(array_keys(get_class_vars(get_class($this))) as $k)
			   if ($k != 'updtFields')
			      $encode .= "\"$k\":\"{$this->$k}\",";
		  return '{' . substr($encode,0,strlen($encode)-1) . '}';	

  }//end of toDebug  
	
	
	function validateSchema($schema)
	{
		  $error = array();
			
		foreach(array_keys($schema) as $k)
		{	
				
		   // echo "VALIDATOIR STR[{$k}] = " . $schema[$k] . '<BR>';
		  	list($type,$len,$isnull) = split("," , $schema[$k] );

				$size = strlen($this->$k);
        if ($size == 0 && $isnull == 'Y')
				   return array(true,$error); //no errors
				else if ($size > $len)
				  $error[$k] = 'SIZE';
				else if ($isnull =='N' && $size==0)
				  $error[$k] = 'NULL';
				else if ($type == 'NUMBER')
				  if (!is_numeric($this->$k)) $error[$k] = 'NAN';
				else if ($type == 'VARCHAR2' || $type == 'CHAR')	
				  if (!is_string($this->$k)) $error[$k] = 'NAS';
		} 	//end ogf forech
		
		return array(count($error)==0,$error);

	}
	
	
	function loadData($data,$fields,$sep)
	{
	   $dataArr = split("[$sep]",$data);
		 if (count($dataArr) != count($fields))
		    return false;									
		 $i=0;
		 foreach ($dataArr as $val)
       $this->$fields[$i++] = $val;
		 return true;
	}

} //end of Object
?>

What can you do with it?

for example you can create a Customer Class

Code: Select all

<?
include 'lib/ObjectLib.php';

class Customer extends Object
{
  var $name;
  var $phone;
  var $ssn;
}
?>

If you have a form and you name all the form varibles exactly as the variables you could do fill your class like this

Code: Select all

//create a new Customer
$customer = new Customer($_POST);

//have problems? , just show all your data
$customer->toDebug();

//remove all spaces from user data
$customer->trim();

//Sometime you might want to send data from one page to another using a link, you can do this
<a href="senddata.php?<?=$customer->toUrl()?>">Send Data</a>

//Let say you want to export your data
$export = $customer->export();

//export your object to XML
echo htmlentities($a->toXML(true));

//export to XML only selected fields
echo htmlentities($a->toXML(true,array('name','phone')));

//validate your data 
just add this to your class
function isValid()
{

  $schema = array(
  ,'name'=>'VARCHAR2,20,N'
  ,'phone'=>'VARCHAR2,20,N'
  ,'ssn'=>'NUMBER,22,N'
);

       return $this->validateSchema($schema);
		
}//is valid

then you can 
list($isValid,$error) = $customer->isValid();

IMPORTANT NOTE: I have not dont this but it will be very easy to just add regular expressions to the validateSchema() so that your schema could look like
,'name'=>'REGEXP',<REGEX HERE>'



//NEED TO LOAD DATA FROM A TEXT FILE??
$d = new Customer();
$data='Jose;787-555-8888;988-98-99888';//this could be in a file
 $fields = array('name','phone','ssn');

//$d->PROCESS_CODE = "ADFF";
if ($d->load($data,$fields,';'))
{
   $d->toDebug();
   list($isValid,$error) = $d->isValid();
	 if (!$isValid)
	 {
	   die ("INVALID DATA ON");
	 }
	   
}
else
{
  echo "INVALID DATA SOURCE";
}


Well that's about it. This class is extremely easy to use. Let me know if you like it.

Posted: Sun Aug 19, 2007 6:18 pm
by Christopher
Well it certainly has some very nice functionality. However I am not sure that it is appropriate to put all those features into one class. Nor am I sure I like the idea of base object classes in PHP in general. I would prefer to see this broken up into a number of classes that deal with specific functionality. The you could extent to get just the specific functionality that you need. I would guess that you rarely use more than 10%-20% of the functionality of your base class in any class that inherits it.

Broken up these classes might be of real interest to a number of people here.

you will be surprised

Posted: Sun Aug 19, 2007 6:47 pm
by yacahuma
You will be surprise of how many I use in just one program. Maybe is the nature of what I do. You have a good point,
but every function has very little code. In terms of OO I think all this functions relate to the data in the object. They are all data transformation functions. That's why I put them all in just one place. Also since I use so many methods of the base class, it was easier to just have it in one place.

I understand all the concept of OO , but I over the years I developed my own sense of what OO means. I guess the simplest way to put it is that if I can do something with one line instead of a bunch of lines needed to create new objects that will talk to other objects, I will go with the on line method, even if is not purely OO.
I guess the perfect example will be this. It was from a question I had on bthe swift forum

Code: Select all

swift code...
$log =& Swift_LogContainer::getLog();
$log->setLogLevel(Swift_Log::LOG_EVERYTHING);
$swift =& new Swift( ... );
echo "<pre>" . htmlentities($swift->log->dump(true)) . "</pre>";

phpmailer code...
$mail->SMTPDebug = true;

I am not saying one is better than the other. I just prefer oneliners.


I also have a code generator that creates update, list, and edit pages. The code generator is in the form of a html page. You enter the username, password, table name and PK. It uses adodb for the database stuff.

Re: you will be surprised

Posted: Mon Aug 20, 2007 3:05 pm
by superdezign
yacahuma wrote:You will be surprise of how many I use in just one program.
It's not a matter of how many are used in a program, but how many are used in the particular object that is extended from it.
yacahuma wrote:In terms of OO I think all this functions relate to the data in the object. They are all data transformation functions. That's why I put them all in just one place. Also since I use so many methods of the base class, it was easier to just have it in one place.
That would imply library of functions would be used, not a base class. Maybe a class dedicated to data transformation that had a lot of static functions would be more appropriate.
yacahuma wrote:[..]even if is not purely OO. I guess the perfect example will be this. It was from a question I had on bthe swift forum

Code: Select all

swift code...
$log =& Swift_LogContainer::getLog();
$log->setLogLevel(Swift_Log::LOG_EVERYTHING);
$swift =& new Swift( ... );
echo "<pre>" . htmlentities($swift->log->dump(true)) . "</pre>";

phpmailer code...
$mail->SMTPDebug = true;

I am not saying one is better than the other. I just prefer oneliners.
That's not an example of what you said at all. This is just making it so that outside of the class, less commands are needed. Inside the class, the same amount of stuff is being done. The example let's you turn the debugging on or off, and the class handles the rest. Swift's example makes you specify how much logging you want to be done, and let's you handle the display. When a developer makes other other developers lack control, they are bound to receive complaints :P


Basically, there are certain things that a base object could be good for. Maybe for saving data between objects, or logging errors. But for what you are accomplishing, an outside class would be better.

Posted: Mon Aug 20, 2007 5:06 pm
by RobertGonzalez
I agree with arborint. A single superclass that involves functionality on several levels seems a bit contrary to good OO design.

I could see a simple base class with several extending classes that are called when needed rather than forcing that functionality into the code without the need for it.

Posted: Mon Aug 20, 2007 5:53 pm
by Christopher
I do think there is some nicel functionality in there though. If it were broken up into base classes for debug, data access, XML, JSON, etc. they might be pretty useful classes and of interest to some people around here.