PHP Datastorage Class (continued)

In the first part of this two-part article, you started to learn about using alternatives to databases for storing data; specifically, we started to work on creating a class that can handle flat files, session variables, and cookies. This second part picks up right where we left off last time.

Modes 3 – 7

This is where things get interesting. Mode 3 will output a representation of the data using an XSLT style sheet. The data is first converted to a simple XML format and then processed using a style sheet specified by the second argument of the readout method. Producing an attractive representation of the contents of a shopping cart, for instance, is only a matter of crafting the appropriate XSLT style sheet. You can even do simple math with XSLT, which makes handling prices a breeze. Both the Sablotron-based XSLT and DOMXML extensions are supported. Support for the much improved XSL extension in PHP 5 would not be difficult to add.

Mode 4 outputs the afore mentioned XML format. There certainly could be additional possibilities here depending on your needs for XML output.

The mode is 5 readout uses the print_r function to output a raw text version of its data contents. This can be invaluable for debugging purposes.

If the data you are storing lends itself to being viewed in a spreadsheet, mode 6 will output all data in the comma delimited CSV format, which can be read by several spreadsheet applications, including Microsoft Excel, and can be used to load database tables using MySQL or other database systems.

The final mode (mode 7) will output a very simple configuration file format.

#*************
#user_settings
#*************
param1=foo
param2=foobar
param3=barfoo
#*************
#system_settings
#*************
param1=foo
param2=foobar
param3=barfoo

I’ll discuss the actual methods that output these formats in a moment, but first we should probably have a few more ways to get at our data. The get_item method will retrieve a single item (row) or specific field value from the datastore. The first argument is the items key and the second optional argument is a specific field within that row to retrieve.

function get_item($id,$field=””)
{
      if($field == “”)
      {
            if(isset($this->items[$id]))
            {
                  return $this->items[$id];
            }
            else
            {
                  return false;
            }
      }
      else
      {
            if(isset($this->items[$id][$field]))
            {
                  return $this->items[$id][$field];
            }
            else
            {
                  return false;
            }
      }
}

This method returns false if it can’t find the item for which you are looking. It has a number of expansion possibilities using regular expressions or perhaps some sort of query parser. The final output method is by_value.

function by_value($val)
{
      $len = $this->get_count();
      if($len > 0)
      {
            $keys = array_keys($this->items);
            for($i = 0;$i < $len;$i++)
            {
                  if(array_search($val,$this->items[$keys[$i]]))
                  {
                        $ret[$keys[$i]] = $this->items[$keys[$i]];
                  }
            }
            if(count($ret) > 0)
            {
                  return $ret;
            }
            else
            {
                  return false;
            }
      }
      else
      {
            $this->err(“No items in Datastore”);
            return false;
      }
}

This method takes a single argument, which is a string value to search for within the datastore. It returns an array of all rows that contain that value, such as all the rows that contain web page hit counts for a specific company or section of a site.

One final output method that is independent of the readout method is sql_template. The sql_template method accepts an id of an item in the datastore and a specially formatted sql statement that works much like an html template.

function sql_template($id=””,$sql=””)
{
      if($id != “” && $sql != “”)
      {
            if($item = $this->get_item($id))
            {
            $ret = $sql;
                  $keys = array_keys($item);
                  for($i = 0;$i < count($keys);$i++)
                  {
                        $ret = str_replace($keys[$i],$item[$keys[$i]],$sql);
                  }
                  return $ret;
            }
            else
            {
                  $this->err(“Item not found”,1);
                  return false;
            }
      }
      else
      {
            $this->err(“Required arguments not supplied”,1);
            return false;
      }
}

//*********************************
EXAMPLE

sql statement:
“SELECT * FROM [table] WHERE [key_field] = [value]”;

item array in datastore
[table] => products
[key_field] => product_id
[value] >> 25445587

In the above example, if you have an array key called “[table]”, the value associated with that key is dropped in the place of the string “[table]” in the sql template. Square brackets are used most often for templates. Square brackets are also part of sql syntax, but as long as you have your key names matched up with the strings to replace in the template, you shouldn’t have any trouble.

As with the store method you can certainly use readout as well as any of the other output methods multiple times in the same document for different tasks.

{mospagebreak title=Utility Methods}

There are several utility methods in this class that can make your life much easier when using the datastore. The first is is_item. This method allows you to determine if an item with the key you are looking for is there and returns false if it isn’t. You can use is_item to ensure that each key is unique using the following code.

do{
      $temp = rand(1111111,9999999);
}while($data->is_item($temp));
$data->add_new_item($data_array,$temp);

As long as is_item finds a key that matches your random number the loop will continue until it finds a unique one.

Another useful method is is_value. This method searches for the value you specify and will return true if it finds it, false if it doesn’t. This method has a mode selector in its arguments as well, to allow future enhancements to the method.

function is_value($val,$mode=0)
{
      if($mode == 0)
      {
            return array_search($val,$this->items);
      }
}

A utility method that is likely to get used in every page that uses the datastore is get_count. This method simply returns the number of items in the items array. If you have no records stored you can determine this and provide the proper feedback to the user.

function get_count()
{
      if($this->items)
      {
            return count($this->items);
      }
      else
      {
            return 0;
      }
}

Once you’re done with the data you have stored and need to initialize it, use the destroy method. This will unset your session variable, erase your flat file or eat your cookie depending on which storage mode you have selected.

function destroy($mode=”blank”)
{
      if($mode == “blank”)
      {
            $mode = $this->mode;
      }
      if($mode == “s”)
      {
            unset($_SESSION[$this->dataname]);
      }
      else if($mode == “f”)
      {
            unset($this->items);
            $this->store(“f”);
      }
      else if($mode == “c”)
      {
            setcookie($this->dataname);
      }
      $this->items = null;
}

One final utility method allows you to delete an item from the items array. delete_item will delete an item with the key that you specify with the first and only argument.

function remove_item($id)
{
      if(isset($this->items[$id]))
      {
            unset($this->items[$id]);
            $this->edited = true;
            return true;
      }
      else
      {
            $this->err(“Could not find and remove $id”);
            return false;
      }
}

As with other parts of the datastore class, there are probably plenty of additional possibilities for modifications and other utility methods to reduce the amount of code you would need to write as part of your application.

{mospagebreak title=The Output Methods in Depth}

Now let’s cover some of the output methods that require a separate method. The first one is mode 1, which outputs an array of query strings containing all stored data. In some situations, such as when transferring data to a server you don’t control, this will come in handy.

function to_query_string()
{
      $keys = array_keys($this->items);
      for($i = 0;$i < count($keys);$i++)
      {
            $ikeys = array_keys($this->items[$i]);
            $q_array[$i] = “”;
            for($k = 0;$k < count($ikeys);$k++)
            {
                  $q_array[$i] .= $ikeys[$k].”=”.$this->items[$keys[$i]][$ikeys[$k]].”&”;
            }
            $q_array[$i] = urlencode(substr($q_array[$i],0,strlen($q_array[$i])-1));
      }
      return $q_array;
}

If we have some data stored then we first get all the keys. Nested loops are used to put together a numerical array where each element contains a query string that represents a row in the datastore. Looping through this array to create links in your application takes very little code. Mode 2 also creates query strings, but this time only the keys are included. This can be used to construct links to get specific items out of the datastore. This could be used to retrieve information about individual items in a shopping cart, for instance.

function id_query()
{
      $keys = array_keys($this->items);
      $qstr = array();
      for($i = 0;$i < count($keys);$i++)
      {
            $qstr[$i] .= “id=”.urlencode($keys[$i]);
      }
      return $qstr
}

Next is mode 3, which outputs XSLT. This method accepts a single argument which is the path to a stylesheet, so process the output. A secondary method called get_xml is called first, to convert the information in the datastore to a simple XML format.

function get_xml($source=”blank”)
{
      if($source == “blank”)
      {
            $source = $this->items;
      }
      if(is_array($source))
      {
            $keys = array_keys($source);
            $xml_str = “<?xml version=”1.0″ encoding=”iso-8859-1″”.”?”.”><itemgroup>”;
            for($i = 0;$i < count($keys);$i++)
            {
                  $xml_str .= “<item id=””.$keys[$i].””>”;
                  $ikeys = array_keys($this->items[$keys[$i]]);
                  for($k = 0;$k < count($ikeys);$k++)
                  {
                        $xml_str .= “<“.$ikeys[$k].”>”.
                        $this->items[$keys[$i]][$ikeys[$k]].
                        “</”.$ikeys[$k].”>”;
                  }
                  $xml_str .= “</item>”;
            }
            $xml_str .= “</itemgroup>”;
            return $xml_str;
      }
      else
      {
            $this->err(“Input is not an array”,1);
      }
}

This method allows an optional argument that permits external conversion of an array of the appropriate format to be converted. This potentially includes an array coming from a database using some of the commonly used functions for retrieving records from MySQL or Postgres databases. The XML format that is produced is below.

<?xml version=”1.0″ encoding=”iso-8859-1?>
<itemgroup>
<item>
      <itemcode>255445856</itemcode>
      <model_number>FG405</model_number>
      <description>Colorful widget that makes a lot of noise</description>
      <retail>5.03</retail>
      <discount>4.02</discount>
      <promo>0</promo>
</item>
<item>
<!–second item–>
</item>
</itemgroup>

The code for the from_xslt method is below.

function from_xslt($file)
{
      if(file_exists($file))
      {
            if(function_exists(“xslt_process”))
            {
                  $resource = fopen($file,”r”);
                  $str = fread($resource,filesize($file));
                  $result = null;
                  $xres = $this -> get_xml();
                  $args = array(‘/_xml’ => $xres,’/_xsl’ => $this -> $str);
                  xslt_process($resource,’/_xml’,’/_xsl’,$result,$args);
                  xslt_free($resource);
                  return $result;
            }
            else if(function_exists(“domxml_xslt_stylesheet_file”))
            {
                  if($xmldoc = domxml_open_mem($this->get_xml()))
                  {
                        $xsldoc  = domxml_xslt_stylesheet_file ($file);
                        $result = $xsldoc->process($xmldoc);
                  }
                  else
                  {echo(“error parsing xml document”);}
            }
      }
}

You will need XSLT support in your PHP distribution to use this method. The choices are the PHP 4x Sablotron XSLT engine or the DOMXML extension. The DOM extension is no longer supported in PHP 5, a new XSL extension based on the libxslt library is used instead. This method could easily be modified if you are using the newest version.

Mode 4 outputs just the XML format mentioned above.

The last two output formats are CSV and configuration. The CSV output uses the get_csv method. There is one optional argument to the readout method that is passed on only to this method

function readout($mode,$file=””,$headers=true,$del=”:”)
{

If headers is set to true, the first row in the csv file will be the keys for each item in each row of the datastore. If it is set to false then only the data will be included. This format can be viewed in Microsoft Excel or used as an import format for a database.

function make_csv($headers,$source=”blank”)
{
      if($source = “blank”)
      {
            $source = $this->items;
      }
      $head = “”;
      $data = “”;
      if(is_array($source))
      {
            $keys = array_keys($source);
            for($i = 0;$i < $this->get_count();$i++)
            {
                  $keys2 = array_keys($source[$keys[$i]]);
                  for($j = 0;$j < count($keys2);$j++)
                  {
                        if($i == 0)
                        {
                              $head .= $keys2[$j].”,”;
                        }
                        $data .= $source[$keys[$i]][$keys2[$j]].”,”;
                  }
                  $data .= “rn”;/**/
            }
            if($headers)
            {
                  $csv_str = $head.”rn”.$data;
            }
            else
            {
                  $csv_str = $data;
            }
            return $csv_str;
      }
      else
      {
            $this-err(“input is not an array”,1);
      }
}

The final output format is the config format. It produces the configuration format mentioned before. The fourth argument of the readout method is the delimiter to be used between the key value pairs.

function make_config($del)
{
      $keys = array_keys($this->items);
      $out = “”;
      for($i = 0;$i < count($keys);$i++)
      {
            $out .= “#*************rn#”.$keys[$i].”rn#*************”;
            $subkeys = array_keys($items[$keys[$i]]);
            for($j = 0;$j < count($subkeys);$j++)
            {
                  $out .= $subkeys[$j].$del.$this->items[$keys[$i]][$subkeys];
            }
      }
      return $out;
}

This format can be modified to fit different needs. The datastore itself can be used as a configuration system. The versatility is there if you need it.

{mospagebreak title=A Snack for the Road}

Finally, if you are going to use cookies to store data, the constructor method should have the following code in it at the last If block.

else if($mode == “c”)
{
      if(isset($_COOKIE[$this-dataname]))
      {
            $this->items = unserialize($_COOKIE[$this->dataname]);
      }
      else
      {
            setcookie($this->dataname);
      }
}

If the cookie is not yet set, then it is set, otherwise we retrieve the data from it just as we would with any of the other storage methods. This code simply sets a cookie by the default or the name specified. If you wish to supply additional parameters, such as expiration time, these optional arguments would need to be added to the constructor. You might also want to provide a backup plan in case the user has cookies disabled.

Wrapping it Up

Because all of this functionality is wrapped in a class, it can be included and extended by other classes easily.You can then let the err method do the work. You can also have multiple instances of the datastore in a document. Adding database connection capability through an abstraction class would give you a complete data storage solution, and the datastore could be used to provide preset connections and queries. If you come up with a good use make sure to share it.

[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye