Sophie

Sophie

distrib > Mandriva > 9.1 > ppc > media > main > by-pkgid > 0afeee9cca140e167a996902b9a677c5 > files > 3116

php-manual-en-4.3.0-2mdk.noarch.rpm

<HTML
><HEAD
><TITLE
>Object Aggregation/Composition Functions</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
REL="HOME"
TITLE="PHP Manual"
HREF="index.html"><LINK
REL="UP"
TITLE="Function Reference"
HREF="funcref.html"><LINK
REL="PREVIOUS"
TITLE="odbc_tables"
HREF="function.odbc-tables.html"><LINK
REL="NEXT"
TITLE="aggregate_info"
HREF="function.aggregate-info.html"><META
HTTP-EQUIV="Content-type"
CONTENT="text/html; charset=ISO-8859-1"></HEAD
><BODY
CLASS="reference"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>PHP Manual</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="function.odbc-tables.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="function.aggregate-info.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="reference"
><A
NAME="ref.objaggregation"
></A
><DIV
CLASS="TITLEPAGE"
><H1
CLASS="title"
>LXX. Object Aggregation/Composition Functions</H1
><DIV
CLASS="PARTINTRO"
><A
NAME="objaggregation.partintro"
></A
><DIV
CLASS="warning"
><P
></P
><TABLE
CLASS="warning"
BORDER="1"
WIDTH="100%"
><TR
><TD
ALIGN="CENTER"
><B
>Warning</B
></TD
></TR
><TR
><TD
ALIGN="LEFT"
><P
>This extension is
<SPAN
CLASS="emphasis"
><I
CLASS="emphasis"
>EXPERIMENTAL</I
></SPAN
>. The behaviour of this extension --
including the names of its functions and anything else documented
about this extension -- may change without notice in a future release of PHP. 
Use this extension at your own risk.</P
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="section"
><H1
CLASS="section"
><A
NAME="objaggregation.intro"
></A
>Introduction</H1
><P
>&#13;      In Object Oriented Programming, it is common to see the composition of
      simple classes (and/or instances) into a more complex one. This is a
      flexible strategy for building complicated objects and object
      hierachies and can function as a dynamic alternative to multiple
      inheritance. There are two ways to perform class (and/or object)
      composition depending on the relationship between the composed
      elements: <SPAN
CLASS="emphasis"
><I
CLASS="emphasis"
>Association</I
></SPAN
> and
      <SPAN
CLASS="emphasis"
><I
CLASS="emphasis"
>Aggregation</I
></SPAN
>.
     </P
><P
>&#13;      An <SPAN
CLASS="emphasis"
><I
CLASS="emphasis"
>Association</I
></SPAN
> is a composition of independently constructed and
      externally visible parts.  When we associate classes or objects, each
      one keeps a reference to the ones it is associated with. When we
      associate classes statically, one class will contain a reference to an
      instance of the other class. For example:
      <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN66083"
></A
><P
><B
>Example 1. Class association</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="php"
>class DateTime {
   
   function DateTime() {
       // empty constructor
   }

   function now() {
       return date("Y-m-d H:i:s");
   }
}

class Report {
   var $_dt = new DateTime();
   // more properties ...

   function Report() {
       // initialization code ...
   }

   function generateReport() {
       $dateTime = $_dt-&#62;now();
       // more code ...
   }

   // more methods ...
}

$rep = new Report();</PRE
></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
      We can also associate instances at runtime by passing a reference in a
      constructor (or any other method), which allow us to dynamically change
      the association relationship between objects. We will modify the example 
      above to illustrate this point:
      <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN66086"
></A
><P
><B
>Example 2. Object association</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="php"
>class DateTime {
   // same as previous example
}

class DateTimePlus {
   var $_format;
   
   function DateTimePlus($format="Y-m-d H:i:s") {
       $this-&#62;_format = $format
   }

   function now() {
       return date($this-&#62;_format);
   }
}

class Report {
   var $_dt;    // we'll keep the reference to DateTime here
   // more properties ...

   function Report() {
       // do some initialization
   }

   function setDateTime(&#38;$dt) {
       $this-&#62;_dt =&#38; $dt;
   }

   function generateReport() {
       $dateTime = $_dt-&#62;now();
       // more code ...
   }

   // more methods ...
}

$rep = new Report();
$dt = new DateTime();
$dtp = new DateTimePlus("l, F j, Y (h:i:s a, T)");

// generate report with simple date for web display
$rep-&#62;setDateTime(&#38;$dt);
echo $rep-&#62;generateReport();

// later on in the code ...

// generate report with fancy date
$rep-&#62;setDateTime(&#38;$dtp);
$output = $rep-&#62;generateReport();
// save $output in database
// ... etc ...</PRE
></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
     </P
><P
>&#13;      <SPAN
CLASS="emphasis"
><I
CLASS="emphasis"
>Aggregation</I
></SPAN
>, on the other hand, implies 
      encapsulation (hidding) of the
      parts of the composition. We can aggregate classes by using a (static)
      inner class (PHP does not yet support inner classes), in this case the
      aggregated class definition is not accessible, except through the class
      that contains it. The aggregation of instances (object aggregation)
      involves the dynamic creation of subobjects inside an object, in the
      process, expanding the properties and methods of that object.
     </P
><P
>&#13;      Object aggregation is a natural way of representing a whole-part relationship, 
      (for example, molecules are aggregates of atoms), or can be used to
      obtain an effect equivalent to multiple inheritance, without having to
      permanently bind a subclass to two or more parent classes and their
      interfaces. In fact object aggregation can be more flexible, in which we
      can select what methods or properties to "inherit" in the aggregated
      object.
     </P
></DIV
><DIV
CLASS="section"
><H1
CLASS="section"
><A
NAME="objaggregation.examples"
></A
>Examples</H1
><P
>&#13;      We define 3 classes, each implementing a different storage method:
     </P
><P
>&#13;      <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN66096"
></A
><P
><B
>Example 3. storage_classes.inc</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="php"
>&#60;?php
class FileStorage {
    var $data;

    function FileStorage($data) {
        $this-&#62;data = $data;
    }
    function write($name) {
        $fp = fopen(name, "w");
        fwrite($fp, $this-&#62;data);
        fclose($data);
    }
}

class WDDXStorage {
    var $data;
    var $version = "1.0";
    var $_id; // "private" variable

    function WDDXStorage($data) {
        $this-&#62;data = $data;
        $this-&#62;_id = $this-&#62;_genID();
    }

    function store() {
        if ($this-&#62;_id) {
            $pid = wddx_packet_start($this-&#62;_id);
            wddx_add_vars($pid, "this-&#62;data");
            $packet = wddx_packet_end($pid);
        } else {
            $packet = wddx_serialize_value($this-&#62;data);
        }
        $dbh = dba_open("varstore", "w", "gdbm");
        dba_insert(md5(uniqid("",true)), $packet, $dbh);
        dba_close($dbh);
    }

    // a private method
    function _genID() {
        return md5(uniqid(rand(),true));
    }
}

class DBStorage {
    var $data;
    var $dbtype = "mysql";

    function DBStorage($data) {
        $this-&#62;data = $data;
    }

    function save() {
        $dbh = mysql_connect();
        mysql_select_db("storage", $dbh);
        $serdata = serialize($this-&#62;data);
        mysql_query("insert into vars ('$serdata',now())", $dbh);
        mysql_close($dbh);
    }
}

?&#62;</PRE
></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
     </P
><P
>&#13;     We then instantiate a couple of objects from the defined classes, and
     perform some aggregations and deaggregations, printing some object information
     along the way:
     </P
><P
>&#13;      <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN66101"
></A
><P
><B
>Example 4. test_aggregation.php</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="php"
>&#60;?php
include "storageclasses.inc";

// some utilty functions

function p_arr($arr) {
    foreach($arr as $k=&#62;$v)
        $out[] = "\t$k =&#62; $v";
    return implode("\n", $out);
}

function object_info($obj) {
    $out[] = "Class: ".get_class($obj);
    foreach(get_object_vars($obj) as $var=&#62;$val)
        if (is_array($val))
            $out[] = "property: $var (array)\n".p_arr($val);
        else
            $out[] = "property: $var = $val";
    foreach(get_class_methods($obj) as $method)
        $out[] = "method: $method";
    return implode("\n", $out);
}


$data = array(M_PI, "kludge != cruft");

// we create some basic objects
$fs = new FileStorage($data);
$ws = new WDDXStorage($data);

// print information on the objects
echo "\$fs object\n";
echo object_info($fs)."\n";
echo "\n\$ws object\n";
echo object_info($ws)."\n";

// do some aggregation

echo "\nLet's aggregate \$fs to the WDDXStorage class\n";
aggregate($fs, "WDDXStorage");
echo "\$fs object\n";
echo object_info($fs)."\n";

echo "\nNow let us aggregate it to the DBStorage class\n";
aggregate($fs, "DBStorage");
echo "\$fs object\n";
echo object_info($fs)."\n";

echo "\nAnd finally deaggregate WDDXStorage\n";
deaggregate($fs, "WDDXStorage");
echo "\$fs object\n";
echo object_info($fs)."\n";

?&#62;</PRE
></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
     </P
><P
>&#13;      We will now consider the output to understand some of the side-effects
      and limitation of object aggregation in PHP.
      First, the newly created <TT
CLASS="varname"
>$fs</TT
> and <TT
CLASS="varname"
>$ws</TT
>
      objects give the expected output (according to their respective class
      declaration). Note that for the purposes of object aggregation,
      <SPAN
CLASS="emphasis"
><I
CLASS="emphasis"
>private elements of a class/object begin with an underscore 
      character ("_")</I
></SPAN
>, even though there is not real distinction between
      public and private class/object elements in PHP.
     </P
><P
>&#13;      <DIV
CLASS="informalexample"
><A
NAME="AEN66109"
></A
><P
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="programlisting"
>$fs object
Class: filestorage
property: data (array)
    0 =&#62; 3.1415926535898
    1 =&#62; kludge != cruft
method: filestorage
method: write

$ws object
Class: wddxstorage
property: data (array)
    0 =&#62; 3.1415926535898
    1 =&#62; kludge != cruft
property: version = 1.0
property: _id = ID::9bb2b640764d4370eb04808af8b076a5
method: wddxstorage
method: store
method: _genid</PRE
></TD
></TR
></TABLE
><P
></P
></DIV
>
     </P
><P
>&#13;      We then aggregate <TT
CLASS="varname"
>$fs</TT
> with the
      <B
CLASS="classname"
>WDDXStorage</B
> class, and print out the object
      information. We can see now that even though nominally the
      <TT
CLASS="varname"
>$fs</TT
> object is still of
      <B
CLASS="classname"
>FileStorage</B
>, it now has the property
      <TT
CLASS="varname"
>$version</TT
>, and the method <B
CLASS="function"
>store()</B
>,
      both defined in <B
CLASS="classname"
>WDDXStorage</B
>. One important thing
      to note is that it has not aggregated the private elements defined in
      the class, which are present in the <TT
CLASS="varname"
>$ws</TT
> object. Also
      absent is the constructor from <B
CLASS="classname"
>WDDXStorage</B
>, which
      will not be logical to aggegate.
     </P
><P
>&#13;      <DIV
CLASS="informalexample"
><A
NAME="AEN66122"
></A
><P
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="programlisting"
>Let's aggregate $fs to the WDDXStorage class
$fs object
Class: filestorage
property: data (array)
    0 =&#62; 3.1415926535898
    1 =&#62; kludge != cruft
property: version = 1.0
method: filestorage
method: write
method: store</PRE
></TD
></TR
></TABLE
><P
></P
></DIV
>
     </P
><P
>&#13;      The proccess of aggregation is cummulative, so when we aggregate
      <TT
CLASS="varname"
>$fs</TT
> with the class <B
CLASS="classname"
>DBStorage</B
>,
      generating an object that can use the storage methods of all the
      defined classes.
     </P
><P
>&#13;      <DIV
CLASS="informalexample"
><A
NAME="AEN66128"
></A
><P
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="programlisting"
>Now let us aggregate it to the DBStorage class
$fs object
Class: filestorage
property: data (array)
    0 =&#62; 3.1415926535898
    1 =&#62; kludge != cruft
property: version = 1.0
property: dbtype = mysql
method: filestorage
method: write
method: store
method: save</PRE
></TD
></TR
></TABLE
><P
></P
></DIV
>
     </P
><P
>&#13;      Finally, the same way we aggregated properties and methods dynamically,
      we can also deaggregate them from the object. So, if we deaggregate the
      class <B
CLASS="classname"
>WDDXStorage</B
> from <TT
CLASS="varname"
>$fs</TT
>, we
      will obtain:
     </P
><P
>&#13;      <DIV
CLASS="informalexample"
><A
NAME="AEN66134"
></A
><P
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="programlisting"
>And deaggregate the WDDXStorage methods and properties
$fs object
Class: filestorage
property: data (array)
    0 =&#62; 3.1415926535898
    1 =&#62; kludge != cruft
property: dbtype = mysql
method: filestorage
method: write
method: save</PRE
></TD
></TR
></TABLE
><P
></P
></DIV
>
     </P
><P
>&#13;      One point that we have not mentioned above, is that the process of
      aggregation will not override existing properties or methods in the
      objects. For example, the class <B
CLASS="classname"
>FileStorage</B
> defines a
      <TT
CLASS="varname"
>$data</TT
> property, and the class
      <B
CLASS="classname"
>WDDXStorage</B
> also defines a similar property 
      which will not override the one in the object acquired during
      instantiation from the class <B
CLASS="classname"
>FileStorage</B
>.
     </P
></DIV
></DIV
><DIV
CLASS="TOC"
><DL
><DT
><B
>Table of Contents</B
></DT
><DT
><A
HREF="function.aggregate-info.html"
>aggregate_info</A
>&nbsp;--&nbsp;
     returns an associative array of the methods and properties from
     each class that has been aggregated to the object.
    </DT
><DT
><A
HREF="function.aggregate-methods-by-list.html"
>aggregate_methods_by_list</A
>&nbsp;--&nbsp;
     selective dynamic class methods aggregation to an object
    </DT
><DT
><A
HREF="function.aggregate-methods-by-regexp.html"
>aggregate_methods_by_regexp</A
>&nbsp;--&nbsp;
     selective class methods aggregation to an object using a regular
     expression
    </DT
><DT
><A
HREF="function.aggregate-methods.html"
>aggregate_methods</A
>&nbsp;--&nbsp;
     dynamic class and object aggregation of methods
    </DT
><DT
><A
HREF="function.aggregate-properties-by-list.html"
>aggregate_properties_by_list</A
>&nbsp;--&nbsp;
     selective dynamic class properties aggregation to an object
    </DT
><DT
><A
HREF="function.aggregate-properties-by-regexp.html"
>aggregate_properties_by_regexp</A
>&nbsp;--&nbsp;
     selective class properties aggregation to an object using a regular
     expression
    </DT
><DT
><A
HREF="function.aggregate-properties.html"
>aggregate_properties</A
>&nbsp;--&nbsp;
     dynamic aggregation of  class properties to an object
    </DT
><DT
><A
HREF="function.aggregate.html"
>aggregate</A
>&nbsp;--&nbsp;
     dynamic class and object aggregation of methods and properties
    </DT
><DT
><A
HREF="function.aggregation-info.html"
>aggregation_info</A
>&nbsp;--&nbsp;Synonym for <A
HREF="function.aggregate-info.html"
><B
CLASS="function"
>aggregate_info()</B
></A
></DT
><DT
><A
HREF="function.deaggregate.html"
>deaggregate</A
>&nbsp;--&nbsp;
     removes the aggregated methods and properties from an object
    </DT
></DL
></DIV
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="function.odbc-tables.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="function.aggregate-info.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>odbc_tables</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="funcref.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>aggregate_info</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>