[PHP] - Arrays met references combineren

Pagina: 1
Acties:
  • 174 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Momenteel ben ik wat aan het rommelen met objecten die als reference worden toegevoegd aan arrays en de combinatie van verschillende arrays.

Bekijk het volgende voorbeeld eens:
PHP:
1
2
3
4
5
6
7
8
9
$arr1 = array();
$arr1[] =& $obj1;
$arr2[] =& $obj2;

$arr2 = array();
$arr2[] =& $obj3;
$arr3[] =& $obj4;

$arr =& array_merge($arr1, $arr2);


Bevat nou $arr references naar de objecten, of alleen kopiën daarvan? Volgens mij zijn het kopiën.

Zou ik dan een eigen functie moeten schrijven die zoiets doet?
PHP:
1
2
3
4
5
6
7
8
9
10
function my_array_merge($arr1, $arr2) {
  $arr = array();
  foreach ( $arr1 as $key => $val ) {
    $arr[] =& $val;
  }
  foreach ( $arr2 as $key => $val ) {
    $arr[] =& $val;
  }
  return $arr;
}


Zou dat dan wel werken?

Functie is nu dan wel heel simpel, want houdt maar rekening met twee argumenten en niet met string-keys in de arrays ... maar het gaat even om het idee.

Alvast dank voor het meedenken.

Acties:
  • 0 Henk 'm!

  • AtleX
  • Registratie: Maart 2003
  • Niet online

AtleX

Tyrannosaurus Lex 🦖

Waarom denk je dat het kopieën zijn? Btw, het resultaat van array_merge() is wezenlijk anders dan dat van je eigen functie. Bij array_merge() is je array nog maar 2 items groot, bij je eigen functie komen alle 4 de items erin. Je code klopt gewoon niet. 8)7

Zie code:
http://atlex.nl/voorbeelden/php/array_merge.php
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php
error_reporting(E_ALL);

class Foo
{
    var $Bar;
    
    function Foo()
    {
        $this->Bar = "Candy";
    }
} 

$obj1 = new Foo();
$obj2 = new Foo();
$obj3 = new Foo();
$obj4 = new Foo();

$obj4->Bar = "0xDEADBEEF";

$arr1 = array();
$arr1[] =& $obj1;
$arr1[] =& $obj2;

$arr2 = array();
$arr2[] =& $obj3;
$arr2[] =& $obj4; 

echo "From object (before merge): ".$obj4->Bar."<br>";

$arr = array_merge($arr1, $arr2);

$arr[3]->Bar = "0xDEADBABE";

echo "From array: ".$arr[3]->Bar."<br>";
echo "From object: ".$obj4->Bar;

echo "<h2>Source:</h2>";

echo highlight_file(__FILE__, true);
?>

Dat geeft:
From object (before merge): 0xDEADBEEF
From array: 0xDEADBABE
From object: 0xDEADBABE
Het zijn dus references.

[ Voor 148% gewijzigd door AtleX op 21-12-2007 14:36 ]

Sole survivor of the Chicxulub asteroid impact.


Acties:
  • 0 Henk 'm!

  • Priet
  • Registratie: Januari 2001
  • Laatst online: 18:14

Priet

To boldly do what no one has..

Even testen en je weet het:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Een variabele vullen
$obj1->a = "abc";

$arr1 = array();
$arr1[] =& $obj1;
$arr2[] =& $obj2;

$arr2 = array();
$arr2[] =& $obj3;
$arr3[] =& $obj4;

$arr =& array_merge($arr1, $arr2);

// De variabele veranderen
$obj1->a = "def";

// Nu vergelijken of de uitvoer tweemaal 'def' is
print $arr1[0]->a;
print $arr[0]->a;


Even uit het hoofd, maar met zoiets moet het kunnen uitvogelen.

"If you see a light at the end of a wormhole, it's probably a photon torpedo!"


Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Nou ... dat is een beetje het puntje. Dat weet ik niet zeker. Ik heb het vermoeden.

Ik heb een eigen set classes voor het genereren van een XML-tree. Dat werkt prima, maar nu wil ik graag een bestaande structuur DOM-achtig kunnen manipuleren nadat hij is gemaakt.

Zoiets als:
PHP:
1
2
3
4
5
6
7
8
$xml = $this->_createXML();  // willekeurige functie die een XML structuur als resultaat teruggeeft.
$datagroups =& $xml->getElementsByTagName('datagroup');

foreach ( $datagroups as $datagroup ) {
  if ( !$datagroup->getElementsByTagName('tbody') ) {
    $datagroup->parentNode->removeChild('datagroup');
  }
}


Na bovenstaande bewerking moeten dus alle datagroup elementen uit $xml zijn verwijderd, die geen 'tbody' element bevatten.

In de huidige opzet gebeurt er echter niets. De getElementsByTagName() functie ziet er als volgt uit:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    /**
     * Iterate the (recursive) chilNodes of this object to find all objects
     * that have the 'tagName' property set to given tagname and return an array
     * with objects found. No objects found means that an empty array is returned.
     *
     * @param       string      $tagname        tagname to look for.
     * @return  array           $arr                array with objects found (if any)
     * @access  public
     */
    public function &getElementsByTagName($tagname) {
        $arr = array();
        $tagname = strtolower($tagname);

        foreach ( $this->childNodes as $childNode ) {
            if ( strtolower($childNode->tagName) == $tagname ) {
                $arr[] =& $childNode;
            }
            $subs =& $childNode->getElementsByTagName($tagname);
            $arr =& array_merge($arr, $subs);
        }
        return $arr;
    } // getElementsByTagName()


Daar komt dus die array_merge om de hoek kijken. Nu ben ik benieuwd of die de references in stand houdt of niet. Ik vermoed van niet. Ook vanwege de opzet van de array_merge functie.

Wanneer je namelijk zelf een functie maakt en daar een variabel aantal argumenten accepteert en die vervolgens met func_get_args() inleest, ook dan krijg je een "copy" van de argumenten, en niet de argumenten zelf (zie http://www.php.net/func_get_args).

Acties:
  • 0 Henk 'm!

  • AtleX
  • Registratie: Maart 2003
  • Niet online

AtleX

Tyrannosaurus Lex 🦖

Zie mijn edit in AtleX in "[PHP] - Arrays met references combineren". ;) Het zijn gewoon references.

Sole survivor of the Chicxulub asteroid impact.


Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Haha ... net zelf ook geprobeerd. Je hebt helemaal gelijk ... inderdaad references.

Hmmm ... waar gaat het DAN mis in mijn code.

Damn ... verder zoeken dan maar.

Acties:
  • 0 Henk 'm!

  • Priet
  • Registratie: Januari 2001
  • Laatst online: 18:14

Priet

To boldly do what no one has..

gvanh schreef op vrijdag 21 december 2007 @ 14:29:
Haha ... net zelf ook geprobeerd. Je hebt helemaal gelijk ... inderdaad references.

Hmmm ... waar gaat het DAN mis in mijn code.

Damn ... verder zoeken dan maar.
Da's niet zo moeilijk, je gebruikt $arr1, 2 3 door elkaar ;)

"If you see a light at the end of a wormhole, it's probably a photon torpedo!"


Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Het gaat dus nu waarschijnlijk om deze functie:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
    /**
     * Iterate the (recursive) chilNodes of this object to find all objects
     * that have the 'tagName' property set to given tagname and return an array
     * with objects found. No objects found means that an empty array is returned.
     *
     * @param        string        $tagname        tagname to look for.
     * @return     array            $arr                array with objects found (if any)
     * @access    public
     */
    public function &getElementsByTagName($tagname) {
        $arr = array();
        $tagname = strtolower($tagname);

        foreach ( $this->childNodes as $childNode ) {
            if ( strtolower($childNode->tagName) == $tagname ) {
                $arr[] =& $childNode;
            }
            $subs = $childNode->getElementsByTagName($tagname);
            $arr = array_merge($arr, $subs);
        }
        return $arr;
    } // getElementsByTagName()
?>


Niet die rare voorbeeldjes die ik uit de losse pols ter illustratie heb neergezet.

Acties:
  • 0 Henk 'm!

  • Arne
  • Registratie: April 2005
  • Laatst online: 02-09-2024
Zomaar een gokje hoor, maar zou het kunnen dat $subs geen referentie is en dit wel zou moeten zijn?

When you only live once, try not to die?


Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Dank voor je reply. Inmiddels opgelost.

Het probleem zat hem in regel 17: $arr[] =& $childNode;

Daardoor werd in elke loop steeds weer dezelfde childNode toegewezen in de array. De hele array werd dus uiteindelijk gevuld met de laatste childNode in de childNodes-array.

Op zich wel logisch eigenlijk. Omdat in PHP5 alle objecten sowieso als reference aan arrays worden toegewezen, was in dit geval de expliciete reference niet nodig. Met $arr[] = $childNode wordt sowieso al een reference naar $childNode in de array opgenomen.
Pagina: 1