Hello,

i have little trouble with variables in a class. I create servereal objects with one class and fill the variables. When I later try to read the content of some of those vars. they are empty (Children and intChildren). Here ist the PHP-Source:

<?
class cFolder{

var $Content;
var $Count;
var $Description;
var $Link;
var $Children;

var $Parent;

var $intChildren;

var $myName;

function cFolder($strContent, $lngCount, $strDescription, $strLink, $myint) {
  	$this->Content = $strContent;
$this->Count = $lngCount;
$this->Description = $strDescription;
$this->Link = $strLink;
$this->myName = $myint;   
}

function AddChild($objChild) {
$this->Children[count($this->Children)] = $objChild;
$this->intChildren = count($this->Children);
}

function Initialize($lngLevel, $blnLastNode, $strLeftSide) {
   if ( $lngLevel > 0 ) { /* ETwas HTML-Code */ }
	if ($this->intChildren > 0 ) {
		ror ($i = 0; $i < $this->intChildren; $i++) {
		   $tmp = &$this->Children[$i];
			$tmp->Initialize(($lngLevel + 1), ($this->intChildren-1), $strLeftSide);
	   }
   }

}
}

function GetFolder($strContent, $lngCount, $strDescription, $strLink, $myint) {
$tmp = New cFolder($strContent, $lngCount, $strDescription, $strLink, $myint);
return $tmp;
}

function InsFolder(&$objParent, &$objChild) {
$objChild->Parent = $objParent;
$objParent->AddChild($objChild);
return $objChild;
}

$objFolder[0] = GetFolder(Null, Null, Null, Null, 0);
$objFolder[1] = InsFolder($objFolder[1-1], GetFolder("Eins", 1, "Eins", "Eins", 1));
$objFolder[2] = InsFolder($objFolder[2-1], GetFolder("Zwei", 2, "Zwei", "Zwei", 2));
$objFolder[2] = InsFolder($objFolder[2-1], GetFolder("Drei", 3, "Drei", "Drei", 3));
$objFolder[0]->Initialize(0, 1, "");
?>

Has anybogy an idea?

Thank you very much for your Help.

Salomo

    Hi salomo,

    I think your problem is to with passing and returning references. PHP4 is not 'fully' OOP (will be better in PHP5), so you have to be sure to be following the 'reference' rules. (See the manual references).

    I'm not absolutely sure exactly what you're trying to achieve so I haven't really tried to follow your code through but here's my basic template class for a parent-child tree. I'm sure it's not perfect but it works for me.

    I'm sure you would be able to adapt it for your needs.

    class MyClass {
    	var $_name = '';
    	var $_parent = null;
    	var $_children = array();
    
    function MyClass($name){ 
    	$this->_name = $name;
    }
    function getName(){ return $this->_name; }
    
    function &getParent(){ return $this->_parent; }
    function setParent(&$par){ $this->_parent =& $par; }
    
    function getParentName(){ return $this->_parent? $this->_parent->getName(): ''; }
    
    function &getChild($name){	return $this->_children[$name];	}
    function addChild($name){
    	$this->_children[$name] =& new MyClass($name);
    	$this->_children[$name]->setParent($this);
    }
    function numChildren(){ return count($this->_children); }
    
    
    function info(){
    	$retval = '<hr>Name: '.$this->getName()
    		  .'<br>Parent: '.$this->getParentName()
    		  .'<br>Num Children: '.$this->numChildren();
    	if($this->numChildren()){
    		$retval .= '<br>Children:';
    		foreach($this->_children as $name => $child){
    			$retval .= ' '.$child->getName();
    		}
    	}
    	return $retval;
    }
    }
    $a =& new MyClass('A');
    $a->addChild('B');
    $a->addChild('C');
    $a->addChild('D');
    
    
    $b =& $a->getChild('B');
    $b->addChild('E');
    $b->addChild('F');
    
    $e =& $b->getChild('E');
    
    
    echo $a->info();
    echo $b->info();
    echo $e->info();
    

    Paul.

      Hi Paul,

      thanks a lot for your answer an the code. Unfortunately I'm not very used to php. So I have a lot of difficulties to adpet my code to the one you gave me and vice versa. Could you have a look at the source again? The Problem ist not filling the vars but their retrieval in the class-funktion 'Initialize()'.
      The first object (the on reated with GetFolder (Null, Null, Null, Null, 0) works perfectly. Only the once in the lower levels do not.
      Is it possible, that php use a copy of the object itself? Al Information are available except Children and intChildren?
      Many thanks for your held once again.

      Salomo

        Hi salomo,

        It would help if you describe, in words exactly what you are trying to achieve and I'll have another look.

        Paul.

          Hi Paul,

          thanks for your answer.

          I wan't to create a dynamic tree.

          To do so i wan't to use a class-object for every element.

          In those class-object is wan't to save the parent-object and every child-object (if there is one, of course).

          There is a function called initialize, which generates the correct HTML-code an calls itself for each child-object.

          I must apologize thatr I my english ist not the best.

          Is this the INformation you need?

          Greetings

          Salomo

            Hi salomo,

            Yes that's good ... I'll have to have a look a little later on.

            Paul.

            PS. Your English is a helluva lot better than mein Deutsch!

              Ok salomo, here we go ...

              Seems to me that you are getting in a twist because of the way references work in PHP. You have to get these straight in your mind before you carry on.

              I've tried to adapt your code to do (roughly) what you want it to do ...
              1) Build a tree of links
              2) Display them in a co-ordinated HTML scheme.

              Copy and paste it into a new page and run it first, before you try and understand the code.
              Then have a look at the resulting page source, to see what's happening in the HTML.
              Then have a look at the code ... and read the comments. 😉

              It is actually simpler than your code and I think you are going to have to understand this properly to continue.

              (By the way, there are lot's of other similar ways to achieve the same result).

              There are a couple of things to note ...
              We don't actually have to reference the 'parent' at all.
              The use of the '&' in the addChild function and in conjunction with '='.
              * I've left the HTML very basic so you can see what's going on ... I could probably help you with this side later.

              <?php
              /////////////////////////////////////////////////////////////////////////
              class cFolder {
              	// Declare variables ... and initialise
              	// (Sorry, can't help using my own naming convention)
              	var $_name = ''; 			// == '' => root
              	var $_content = ''; 
              	var $_count = '';			// Not sure what this is
              	var $_description = ''; 
              	var $_link = ''; 
              	var $_children = array(); 	// Empty array => count() == 0
              
              // Constructor
              function cFolder($name = '', $content = '', $count = '', $description = '', $link = ''){ 
              	$this->_name = $name;
              	$this->_content = $content;
              	$this->_count = $count;
              	$this->_description = $description;
              	$this->_link = $link;
              }
              
              // Notice we let addChild create new cFolder's and return references
              function &addChild($name, $content, $count, $description, $link){
                $this->_children[] =& new cFolder($name, $content, $count, $description, $link);
                return $this->_children[count($this->_children) - 1];
              }
              
              // Here we build the output. This needs to be recursive, in that 'parents'
              // call their children's html_output() functions. What the HTML is, I don't know
              // so I've put in a basic table-tree.
              function html_output(){
              
              	// Open the table for this element
              	$retval = '
              <table bgcolor="#D8D8D8" border="0" cellpadding="2" cellspacing="0">
              ';
              		// Check to see if this is not the root and display details
              		// in it's own row ... this is what get's seen.
              		if($this->_name != ''){
              			$retval .= '
              	<tr>
              		<td bgcolor="white" nowrap><strong>'.$this->_name.'</strong></td>
              		<td bgcolor="white" nowrap>
              			'.$this->_content.'/
              			'.$this->_count.'/
              			'.$this->_description.'
              			&nbsp;&nbsp;
              			<a href="javascript:alert(\'Goto page '.$this->_name.'\')">
              				<strong>'.$this->_link.'</strong>
              			</a>
              		</td>
              	</tr>
              ';		}
              
              	// Now check for children and display their html
              	$numchildren = count($this->_children);
              
              	if(0 < $numchildren){
              		for($i = 0; $i < $numchildren; $i++){
              
              			// Create a new row for each child
              			// The first td is used for indentation purposes
              			// only, the second needs to span the row correctly
              			// and contains a new 'recursive' table
              			$retval .= '
              <tr>
              	<td valign="top" nowrap>+&nbsp;-&nbsp;-&nbsp;</td>
              	<td>
              		'.$this->_children[$i]->html_output().'
              	</td>
              </tr>';
              		}
              	}
              	// Finish the table for this element and all it's children
              	$retval .= '
              </table>
              ';
              		return $retval;
              	}
              }
              /////////////////////////////////////////////////////////////////////////
              ?>
              <html>
              <head>
              <title>cFolder Test</title>
              </head>
              <body>
              <h4>cFolder Test</h4>
              <?php
              /////////////////////////////////////////////////////////////////////////
              // Create a root folder
              $root =& new cFolder(); 
              
              // Add children to the root
              $root->addChild(1, "Eins", 1, "Eins", "Eins");
              // Use the return object to reference the child "Zwei" immediately
              $child =& $root->addChild(2, "Zwei", 2, "Zwei", "Zwei"); // Keep a copy for later
              // Add children to "Zwei"
              $child->addChild(21, "ZweiEins", 21, "ZweiEins", "ZweiEins"); 
              $child->addChild(22, "ZweiZwei", 22, "ZweiZwei", "ZweiZwei"); 
              
              // Use the return object to reference the child "Drei" immediately
              $child =& $root->addChild(3, "Drei", 3, "Drei", "Drei"); 
              // Add children to "Drei"
              $child->addChild(31, "DreiEins", 31, "DreiEins", "DreiEins"); 
              
              // If you want to create more levels, be careful to use a new
              // reference for the new level
              $grandchild =& $child->addChild(32, "DreiZwei", 32, "DreiZwei", "DreiZwei"); 
              // Add children to "DreiZwei"
              $grandchild->addChild(321, "DreiZweiEins", 321, "DreiZweiEins", "DreiZweiEins"); 
              $grandchild->addChild(322, "DreiZweiZwei", 322, "DreiZweiZwei", "DreiZweiZwei"); 
              
              // $child is still "Drei"
              // Add more children to "Drei"
              $child->addChild(33, "DreiDrei", 33, "DreiDrei", "DreiDrei"); 
              
              // Display the html
              echo $root->html_output();
              
              ?>
              </body>
              </html>
              

              See how you get on,

              Paul 🙂

                Hello Paul,

                1 Million times thank you.

                That works very good. But ...
                Yes ... one little thing still makes trouble ...
                In your code you asume (as my example has shown) that I seem to know in which order and depth those element appear. Unfortunately this not the way it will have to work. The data results from a database-query and looks different each time.

                Still there is one rule: Child-Object will always apear after their corresponding parent-object. But I do nor know how many Elements there will be and how deep the chunk will go (of course there is the limit from the database which is at the moment 5 levels, but that might change and I would - how could it be another way - prefer not to be forced to change the code when i have to change the levels in the database.)

                May I ask you for your help once more?

                I wish you a good night and look forward to here from you.

                Salomo

                  Salomo,

                  It's a pleasure to help people!! 🆒

                  OK ... for the dynamic query ... post an example of the SQL you use to query the database a couple of rows of data so that I can see what it looks like.

                  Make sure not to put any 'sensitive' info up to the forum (passwords, people's addresses, etc)

                  Paul.

                    Hi Paul,

                    there is no difference between the "static" elements I used in my code-snipped. I thought it might be easier for others to try the code when I put some of the data direct into it.

                    Of course the Level of each Element is available in the database-result and link will not be "Eins" but a real URL etc. 😉

                    Is that enough Info or do you really need the db-query?

                    Salomo

                      Salomo,

                      If the tree elements are going to be different on each call of the page, due to a db query, then we're going to have to decide when branching occurs as we step through the resulting list from the query.

                      So I'm going to need the SQL (or something very similar) and some sample data (false if necessary) to show which 'parent' has which 'child'.

                      Paul.

                        Hi Paul,

                        OK, one results from the db look like this (I use an ID for each result so i can explain what I'm thinking of but the ID is not available in the db-result!):

                           +-------+--------+----------+----------+-------+-------+
                        ID | State | County | City     | District | Level | Count |
                           +-------+--------+----------+----------+-------+-------+
                        1  | 02    | 02000  | 00000000 | 000      |     1 |     3 |
                        2  | 02    | 02000  | 21336500 | 000      |     2 |     3 |
                        3  | 02    | 02000  | 21336500 | 012      |     3 |     1 |
                        4  | 02    | 02000  | 21336500 | 098      |     3 |     2 |
                        5  | 03    | 03100  | 00000000 | 000      |     1 |     5 |
                        6  | 03    | 03100  | 55874900 | 000      |     2 |     2 |
                        7  | 03    | 03100  | 55874900 | 025      |     3 |     2 |
                        8  | 03    | 04300  | 59452200 | 000      |     2 |     3 |
                        9  | 03    | 04300  | 59452200 | 019      |     3 |     2 |
                        10 | 03    | 04300  | 59452200 | 056      |     3 |     1 |
                           +-------+--------+----------+----------+-------+-------+
                        

                        But the tree has to be build based only on the Level-Information because the other columns in the result can change.

                        Result 1 has result 2 as child and the tree-root as parent
                        Result 2 has result 1 as parent and result 3 and result 4 as child
                        Results 3 and 4 have result 2 as parent and no childs

                        Result 5 has result 6 and result 8 as childs and the root-tree as parent
                        Result 6 has result 7 as child and result 6 as parent
                        Result 7 has no childs and result 6 as parent
                        Result 8 has result 9 and result 10 as childs and result5 as parent
                        Result 9 and result 10 have no childs and result 8 as parent

                        The results are ordered by parents and their childs.
                        Example:

                        ID  Level  Childs (ID)  Parent (ID)
                        1   1      2            0 (tree-root)
                        2   2      -            1
                        3   2      4,5          1   
                        4 3 - 3 5 3 - 3 6 1 7,11 0 7 2 8,10 6 8 3 9 7 9 4 - 8 10 3 - 7 11 2 - 6

                        The following will not happen:

                        ID  Level  Childs (ID)  Parent (ID)
                        1   1      2            0
                        2   2      -            1  
                        3 1 1 0 This result should be ID 4 4 2 - 1 This result should be ID 3

                        Is that enough information?
                        Many thanks again for your help an patience

                        Salomog

                          Hi Paul,

                          I think I got the solution ... but - how could it be- there is a little problem.

                          Here is the code for the function to create a new object, the object is as you wrote it:

                                $child[0] =& new cFolder(0,0,Null,Null,Null,Null); 
                                $last_level = -1;
                          
                            function GetFolder($intLevel, $intName, $strContent, $lngCount, $strDescription, $strLink) {
                               global $last_level;
                               global $child;
                          
                               if ( ($last_level != $intLevel) && ($intLevel > 0)) {
                                  $child[$intLevel] =& $child[$intLevel-1]->addChild($intLevel, $intName, $strContent, $lngCount, $strDescription, $strLink);
                               }
                               else {
                                  if (is_object($child[($intLevel-1)])) { 
                                     $child[$intLevel-1]->addChild($intLevel, $intName, $strContent, $lngCount, $strDescription, $strLink);
                                  }
                                  else {
                                     echo "<h3>Fehler: \$child[" . ($intLevel-1) ."] is not available.</h3>";
                                  }
                               }
                              $last_level = $intLevel;
                            }
                          

                          I use the following data:

                          $objFolder[1] = GetFolder(1, 1, "Eins", 1, "Eins", "Eins");
                          $objFolder[2] = GetFolder(2, 2, "Zwei", 2, "Zwei", "Zwei");
                          $objFolder[3] = GetFolder(2, 3, "Drei", 1, "Drei", "Drei");
                          $objFolder[2] = GetFolder(3, 4, "Vier", 2, "Vier", "Vier");
                          $objFolder[3] = GetFolder(3, 5, "Fuenf", 1, "Fuenf", "Fuenf");
                          $objFolder[1] = GetFolder(1, 6, "Sechs", 1, "Sechs", "Sechs");
                          $objFolder[1] = GetFolder(1, 7, "Sieben", 1, "Sieben", "Sieben");
                          

                          As you see element 4 and 5 should be children of element 3 but they are shown as children of element 2:

                          What i expect:      What i get:
                           +--1               +-- 1
                           |  +-- 2           |   +-- 2
                           |  +---3           |   |    +-- 4
                           |      +-- 4       |   |    +-- 5
                           |      +-- 5       |   +-- 3    
                          +-- 6 +-- 6 +-- 7 +-- 7

                          If I use the following data, the output is correct:

                          $objFolder[1] = GetFolder(1, 1, "Eins", 1, "Eins", "Eins");
                          $objFolder[2] = GetFolder(2, 2, "Zwei", 2, "Zwei", "Zwei");
                          $objFolder[3] = GetFolder(3, 3, "Drei", 1, "Drei", "Drei");
                          $objFolder[2] = GetFolder(3, 4, "Vier", 2, "Vier", "Vier");
                          $objFolder[3] = GetFolder(2, 5, "Fuenf", 1, "Fuenf", "Fuenf");
                          $objFolder[1] = GetFolder(1, 6, "Sechs", 1, "Sechs", "Sechs");
                          $objFolder[1] = GetFolder(1, 7, "Sieben", 1, "Sieben", "Sieben");
                          
                          What i get:
                           +-- 1
                           |   +-- 2
                           |   |   +-- 3
                           |   |   +-- 4
                           |   +-- 5 
                           +-- 6
                           +-- 7
                           

                          This is creates the correct output too:

                          $objFolder[1] = GetFolder(1, 1, "Eins", 1, "Eins", "Eins");
                          $objFolder[2] = GetFolder(2, 2, "Zwei", 2, "Zwei", "Zwei");
                          $objFolder[3] = GetFolder(3, 3, "Drei", 1, "Drei", "Drei");
                          $objFolder[2] = GetFolder(2, 4, "Vier", 2, "Vier", "Vier");
                          $objFolder[3] = GetFolder(3, 5, "Fuenf", 1, "Fuenf", "Fuenf");
                          $objFolder[1] = GetFolder(1, 6, "Sechs", 1, "Sechs", "Sechs");
                          $objFolder[1] = GetFolder(1, 7, "Sieben", 1, "Sieben", "Sieben");
                          
                          What I get:
                           +-- 1
                           |   +-- 2
                           |   |   +-- 3
                           |   +-- 4
                           |       +-- 5    
                          +-- 6 +-- 7

                          Do you have any idea how to adapt the GetFolder-function so the output is correct?

                          Salomo

                            OK ... more is nor always better ...

                            Here is the solution:

                            The GetFolder-funktion has to look like this:

                            function GetFolder($intLevel, $intName, $strContent, $lngCount, $strDescription, $strLink) {
                               global $child;
                               $child[$intLevel] =& $child[$intLevel-1]->addChild($intLevel, $intName, $strContent, $lngCount, $strDescription, $strLink);
                            }
                            

                            At last it seems to work ...

                            Thanks a lot for all the help

                            Salomo

                              Hi Salomo,

                              Glad you got it going!

                              Paul. 🙂

                                Write a Reply...