php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #2460 Broken array_push? Or seriously misbehaving multidimensional arrays???
Submitted: 1999-10-06 23:48 UTC Modified: 1999-10-08 21:28 UTC
From: trevorl at discovermusic dot com Assigned:
Status: Closed Package: Other
PHP Version: 4.0 Beta 2 OS: Solaris 7 x86
Private report: No CVE-ID: None
 [1999-10-06 23:48 UTC] trevorl at discovermusic dot com
Okay, this is a really weird one. In my attempt to create a database mapping script I started playing with multidimensional arrays. Currently this script does not do any database access at all, and should be just plain old PHP. 

Here is an example array: 

   $dbs = array(  "dbone"  => array(  "tableone" => array("col1",  "col2",  "col3","col4"),
                                                      "tabletwo" => array("col1",  "col2",  "col3","col4") ),
                         "dbtwo" =>   array( "tableone" => array("col1",  "col2",  "col3","col4"),
                                                      "tabletwo" => array("col1",  "col2",  "col3","col4") )
                        );

With this bit of code, I can walk my array:

   while (list($dbname,$table) = each($dbs)) {
      while (list($tablename,$column) = each($table)) {
         while ($columnname = each($column)) {
            print "$dbname contains $tablename which contains $columnname[1]<br>\n";
         }
      }
   }
   reset($dbs); // Rewind...

And it traverses the entire array, and produces the expected results:

 dbone contains tableone which contains col1 
 ... <trimmed> ...
 dbtwo contains tabletwo which contains col4 

Now I want to add another database element to the array:

 $newdb = array(  "dbthree"  => array(  "tableone" => array("col1",  "col2",  "col3","col4"),
                                                          "tabletwo" => array("col1",  "col2",  "col3","col4") )
                        );

If I use array_push to add it to $dbs: 

   $numpushed = array_push($dbs, $newdb);
   print "Pushed: $numpushed<br>\n";

It reports that it's pushed three elements onto the array, and re-running the script above that walks the array I get results that look like this:

 dbone contains tableone which contains col1 
  ... <trimmed again> ...
 dbtwo contains tabletwo which contains col4 
 0 contains dbthree which contains Array 
 0 contains dbthree which contains Array 

"manually" pushing the new element onto the array by using "$dbs[] = $newdb;" produces the same results, so I really don't think it's the array_push function.

Maybe I'm making a programmatic mistake somewhere, but this is really not the behavior I expected. Below, I'm including the complete script that I've been using that creates this strange behavior. In this script, I also test my ability to modify sub elements of the array (this works just fine), as well as different ways of pulling values out of the arrays, which also work as expected. Anyway, here's the script...

<?php
   $dbs = array(
      "dbone"  => array(
                        "tableone" => array(
                                             "col1",
                                             "col2",
                                             "col3",
                                             "col4"
                                            ),
                        "tabletwo" => array(
                                             "col1",
                                             "col2",
                                             "col3",
                                             "col4"
                                            )
                        ),
      "dbtwo" =>   array(
                        "tableone" => array(
                                             "col1",
                                             "col2",
                                             "col3",
                                             "col4"
                                            ),
                        "tabletwo" => array(
                                             "col1",
                                             "col2",
                                             "col3",
                                             "col4"
                                            )
                        )
      );
      

   /* this creates an array containing "dbone" and "dbtwo" */
   $foo = array_keys($dbs);

   /* this creates an array containing "tableone" and "tabletwo" from "dbone" */
   $bar = array_keys($dbs[$foo[0]]);

   print "$foo[0]<br>\n";                             // prints "dbone"
   print "$bar[0]<br>\n";                             // prints "tableone"

   /* this returns an array of the values from "tableone" of "dbone" */
   $baz = array_values($dbs[$foo[0]][$bar[0]]);


   print "$baz[0]\n<br>\n";                           // prints "col1"
   print "" .$dbs[$foo[0]][$bar[0]][0] ."\n<br>\n";   // prints "col1"

   $gronk = $dbs[$foo[0]][$bar[0]][0];                // assigns "col1" to gronk
   print "$gronk\n<br>\n";                            // prints "col1"

    
   while (list($dbname,$table) = each($dbs)) {
      while (list($tablename,$column) = each($table)) {
         while ($columnname = each($column)) {
            print "$dbname contains $tablename which contains $columnname[1]\n<br>\n";
         }
      }
   }

   reset($dbs); // Rewind...

   $dbs[$foo[1]][$bar[1]][1] = "col69";
   print "new: " .$dbs[$foo[1]][$bar[1]][1] ."\n<br>\n";

   while (list($ndbname,$ntable) = each($dbs)) {
      while (list($ntablename,$ncolumn) = each($ntable)) {
         while ($ncolumnname = each($ncolumn)) {
            print "$ndbname contains $ntablename which contains $ncolumnname[1]\n<br>\n";
         }
      }
   }
?>
   reset($dbs); // Rewind...
   
   $newdb = array(
      "dbthree"  => array(
                        "tableone" => array(
                                             "col1",
                                             "col2",
                                             "col3",
                                             "col4"
                                            ),
                        "tabletwo" => array(
                                             "col1",
                                             "col2",
                                             "col3",
                                             "col4"
                                            )
                        )
      );
      
/*   $dbs[] = $newdb;*/
   $numpushed = array_push($dbs, $newdb);
   print "Pushed: $numpushed\n<br>\n";

   while (list($ndbname,$ntable) = each($dbs)) {
      while (list($ntablename,$ncolumn) = each($ntable)) {
         while ($ncolumnname = each($ncolumn)) {
            print "$ndbname contains $ntablename which contains $ncolumnname[1]\n<br>\n";
         }
      }
   }

   reset($dbs); // Rewind...

       

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [1999-10-06 23:54 UTC] trevorl at discovermusic dot com
There is an errant "?>" in the text below (above?) which is not in the actual script...
 [1999-10-07 00:24 UTC] andrei at cvs dot php dot net
You should be doing:

$dbs["dbthree"] = array("tableone" =>
                    array("col1",  "col2",  "col3","col4"),
                    array("col1",  "col2",  "col3","col4")));

Another way of doing it is:
$dbs = array_merge($dbs, $newdb);

And array_push() returns the new number of elements int the array,
not the number of pushed elements.
 [1999-10-08 21:28 UTC] trevorl at discovermusic dot com
If anyone is interested, below is the finished script. It can map out a mysql database, and throw the results into a multidimensional array,  without any information about the database except for a connect string.
 
 Enjoy...

<?php

    /* make a connection and find out what databases are available... */ 
    $dbi = mysql_connect("localhost","trevorl","");
    $dblist_results = mysql_query("show databases") or die ("SHOW DATABASE: Query Failed\n<br>\n");
    $numdbs = mysql_numrows($dblist_results);
    $dbtables = 0;
   
    /* run through the databases */
    while ($counter < $numdbs) {
       
       /* take a database, query to find out it's table names... */
       $database[$counter] = mysql_result($dblist_results, $counter, mysql_field_name($dblist_results,0));
       $sec_result = mysql_db_query($database[$counter], "show tables", $dbi);
       $numtables = mysql_numrows($sec_result);
       $tablecounter = 0;
       
       print "Current Database [";
       print $counter+1;
       print "/$numdbs]: $database[$counter]\n<br>";

       /* run through the tables */
       while ($tablecounter < $numtables) {

          /* grab a table */
          $cur_tablename = mysql_result($sec_result, $tablecounter, mysql_field_name($sec_result,0));
          print "&nbsp&nbsp&nbsp|____ Current Table [";
          print $tablecounter+1;
          print "/$numtables]: $cur_tablename\n<br>\n";

          /* now query the table for it's column structure ... */
          $col_result = mysql_db_query($database[$counter], "show columns from $cur_tablename", $dbi);
          $numcols = mysql_numrows($col_result);

          $colcounter = 0;

          while ($colcounter < $numcols) {
            $cur_colname = mysql_result($col_result, $colcounter, mysql_field_name($col_result,0));
            print "&nbsp&nbsp&nbsp|&nbsp&nbsp&nbsp|____ Current Column [";
            print $colcounter+1; 
            print "/$numcols]: $cur_colname\n<br>\n";
            $columns[$colcounter] = $cur_colname;
            $colcounter++;
          }
          $tables["$cur_tablename"] = $columns;
          unset($columns);
          $dbtables++;
          $tablecounter++;
       }
       $databases["$database[$counter]"] = $tables;
       unset($tables);
       mysql_free_result($sec_result);
       $counter++;
    }
    mysql_free_result($dblist_results);

    print "<br>\n";

    while (list($dbname,$table) = each($databases)) {
       if ($table) {
         while (list($tablename,$column) = each($table)) {
            while ($columnname = each($column)) {
               print "Database $dbname contains Table $tablename which contains Column $columnname[1]\n<br>\n";
            }
         }
       }
    }

?>

 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon May 06 18:01:35 2024 UTC