Newsgroup: it.comp.www.php
Titolo: OO RIFERIMENTI [Esperti]

Ho un problema con i riferimenti agli oggetti:
ho un oggetto chiamato Admin con un campo nome.
ho un secondo oggetto Ogg che contiene in un campo un rif all'oggetto Admin.
ho un terzo oggetto Factory che istanzia 3 oggetti di tipo Ogg e per ognuno
gli associa l'oggetto Admin.
Factory nel ciclo inserisce i 3 oggetti in un array (come vector in java)
Passa poi l'array per riferimento al quarto oggetto Main (che fa partire
tutto)
bhè il risultato è strano.
gli oggetti vengono sovrascritti nel passaggio da Factory a main.
qualcuno potrebbe aiutarmi?
se è colpa di php (spero di no) c'è un metodo alternativo per fare la stessa
cosa?
ciao e grazie.
<?php
//oggetto che sarà un riferimento in una variabile di Ogg
class Admin{
 var $nome;
 function Admin($nome){
  $this->nome=$nome;
 }
 function getNome(){
  return $this->nome;
 }
}
class Ogg{
 //riferimento all'oggetto Admin
 var $Admin;
 var $nome;
 function Ogg($nome){
  $this->nome=$nome;
 }
 //metodi per settare il riferimento ad admin
 function & getAdmin(){
  return $this->Admin;
 }
 function setAdmin(& $admin){
  $this->Admin = & $admin;
 }
 //restituisce il valore del nome
 function getNome(){
  return $this->nome;
 }
}
/*
 classe che crea 3 oggetti Ogg e inserisce loro i 3 riferimenti all'oggetto
Admin
*/
class ObjFactory{
 function ObjFactory(){}
 function & getObjList(){
  $ray = array('zero','uno','due');
  $vector = array();
  //lo fa 3 volte per 'uno' 'due' 'tre'
  foreach($ray as $key=>$value){
   //crea l'oggetto inserendo l'index come nome
   $Ogg = new Ogg($key);
   //crea un oggetto Admin inserendo il valore come nome
   $Admin = new Admin($value);
   //associa Admin alla var riferimento di Ogg
   $Ogg->setAdmin($Admin);
   //inserisco l'oggetto creato nel vettore.
   $vector[$key] =  $Ogg;
   /* se levo il riferimento & allora gli oggetti Ogg li gestisce bene
    così non funziona neanche il primo oggetto
    $vector[$key] = & $Ogg;
    l'ultimo oggetto sovrascrive gli altri.
    OUPUT:
    2--due
    2--due
    2--due
   */
  }
  //ritorna il riferimento al vettore (uso & su function)
  return $vector;
 }
}
//classe che fa funzionare tutto
class main{
 function main(){
  $ObjFactory = new ObjFactory();
  $vector = array();
  //vector ora dovrebbe puntare allo stesso vector di ObjFactory
  $vector = & $ObjFactory->getObjList();
  //provo la stampa
  foreach($vector as $key=>$value){
   $Admin = & $value->getAdmin();
   print('<br>'.$value->getNome().'--'.$Admin->getNome());
  }
 }
}
$main = new main();
/*
OUTPUT:
0--due
1--due
2--due
INVECE CHE
0--zero
1--uno
2--due
il riferimento all'oggetto Admin viene stranamente sovrascritto.
come faccio a risolvere questo problema?
spesso ho la necessità di utilizzare i riferimenti di un campo di un oggetto
che risiede in un vettore
ex:
class OGG1{
 var $OGG2  ----------> class OGG2{
}
*/
?>

ho semplificato il codice e individuato meglio l'errore:
il problema è l'array, l'assegnazione di un oggetto con dentro un
riferimento ad un'altro oggetto
messo in un array:
<?php

 function Admin($nome){
  $this->nome=$nome;
 }


 var $nome;



class Main{
 function Main(){
  $ray = array('zero','uno','due');
  $vector = array();
  //lo fa 3 volte per 'zero' 'uno' 'due'
  foreach($ray as $key=>$value){
   //crea l'oggetto inserendo l'index come nome
   $Ogg = new Ogg($key);
   //crea un oggetto Admin inserendo il valore come nome
   $Admin = new Admin($value);
   //associa Admin alla var riferimento di Ogg
   $Ogg->setAdmin($Admin);
   //inserisco l'oggetto creato nel vettore.
   $vector[$key] =  $Ogg;
   print('<br>inserito in vettore Ogg:'.$Ogg->getNome().'con rif ad
Admin:'.$Admin->getNome());
  }
  print('<br>verifica i dati nel vettore con index 0');
  print('<br>dovrebbe darmi: 0--zero');
  $value = & $vector[0];
  $Admin = & $value->getAdmin();
  print('<br>Risultato:'.$value->getNome().'--'.$Admin->getNome());
 }
}
$M = new Main();
/*
OUTPUT:
0--due
invece che
0--zero
il riferimento all'oggetto Admin viene stranamente sovrascritto.
il problema arriva quando metto gli oggetti nell'array.
addirittura se assegno all'array $vector[$key] =  & $Ogg;
il riferimento all'oggetto, viene sovrascritto anche il primo oggetto
OUTPUT:
2--due //ora il primo mi da 2 invece che 0
invece che
0--zero


in pratica per spiegarmi meglio:
è l'array, non gestisce bene i riferimenti agli oggetti.
in php si può fare una cosa del genere?
creo Oggetto1
creo Oggetto2
in un campo di Oggetto2 assegno un riferimento a Oggetto1
passo poi Oggetto2 in un vettore.
$vettore[] = & Oggetto2;
lo faccio 3 volte
ma alla fine vettore si ricorda solo dell'ultimo oggetto inserito
cioè il terzo
se invece faccio $vettore[] = Oggetto2;
cioè per copia allora l'array gestisce bene il primo oggetto2 ma il suo
riferimento viene invece sovrascritto!

ho risolto con la serializzazione
ma mi sembra una soluzione un pò estrema (per quanto riguarda lo spreco di
risorse).
.....
$vector[$key] =  serialize($Ogg);
....
$value = & $vector[0];
$value = unserialize($value);
$Admin = & $value->getAdmin();
print('<br>Risultato:'.$value->getNome().'--'.$Admin->getNome());
altre idee?

    $Ogg->setAdmin($Admin);
$Ogg->setAdmin(&$Admin);
-- 
Roberto Lupi

 Roberto Lupi
ciao grazie per la risposta,
che stupido si in effetti $admin = variabile passata per rif
e non viceversa
purtroppo il risultato è lo stesso.
inserito in vettore Ogg:0con rif ad Admin:zero
inserito in vettore Ogg:1con rif ad Admin:uno
inserito in vettore Ogg:2con rif ad Admin:due
verifica i dati nel vettore con index 0
dovrebbe darmi: 0--zero
Risultato:0--due
e se metto
alla riga 59
 $vector[$key] = & $Ogg;
mi da " 2-due " sovrascrivendo entrambi gli oggetti.
ho provato serializzando e in effetti funziona
ho creato una classe Vector stile java che mi gestisce le serializzazioni.
cmq strano
spero in php5

 mi da " 2-due " sovrascrivendo entrambi gli oggetti.
Mi sono scordato un pezzo:
   $Admin =& new Admin($value);
-- 
Roberto Lupi
Codice completo:
<?php
//oggetto che sarà un riferimento in una variabile di Ogg
class Admin{
 var $nome;
 function Admin($nome){
  $this->nome=$nome;
 }
 function getNome(){
  return $this->nome;
 }
}
class Ogg{
 //riferimento all'oggetto Admin
 var $Admin;
 var $nome;
 function Ogg($nome){
  $this->nome=$nome;
 }
 //metodi per settare il riferimento ad admin
 function & getAdmin(){
  return $this->Admin;
 }
 function setAdmin($admin){
  $this->Admin = &$admin;
 }
 //restituisce il valore del nome
 function getNome(){
  return $this->nome;
 }
}
/*
 classe che crea 3 oggetti Ogg e inserisce loro i 3 riferimenti 
all'oggetto
Admin
*/
class Main{
 function Main(){
  $ray = array('zero','uno','due');
  $vector = array();
  //lo fa 3 volte per 'zero' 'uno' 'due'
  foreach($ray as $key=>$value){
   //crea l'oggetto inserendo l'index come nome
   $Ogg = new Ogg($key);
   //crea un oggetto Admin inserendo il valore come nome
   $Admin =& new Admin($value);
   //associa Admin alla var riferimento di Ogg
   $Ogg->setAdmin(&$Admin);
   //$Admin->nome= rand();
   //inserisco l'oggetto creato nel vettore.
   $vector[$key] =  $Ogg;
   print('<br>inserito in vettore Ogg:'.$Ogg->getNome().'con rif ad
Admin:'.$Admin->getNome());
  }
  print('<br>verifica i dati nel vettore con index 0');
  print('<br>dovrebbe darmi: 0--zero');
  //print_r($vector);


 --
ti ringrazio ora funziona
ma mi dici cos'è?
$Admin =& new Admin($value);
$Admin non è per definizione già un riferimento?
nn è un puntatore a una zona di memoria?
e & new Admin cos'è?
a questo punto vedo che funziona anche
$Admin = & new Admin($value);
$Ogg->setAdmin($Admin);
ma a questo punto, se Admin è un puntatore nn dovrebbe essere uguale questo?
$Admin = new Admin($value);
$Ogg->setAdmin(&$Admin);
grazie molte!
:)
ps: se io ho $Admin = & new Admin(); [Admin=0xabc123123]
e faccio $var = & $Admin; [Var = 0x???????]
in teoria dovrebbe risolvere il puntatore di un puntatore no?
nn è più corretto
$Admin = & new Admin();
$var =  $Admin;
cioè
$Admin = & new Admin($value);
$Ogg->setAdmin($Admin);
e non
$Admin = & new Admin($value);
$Ogg->setAdmin(&$Admin);
thnx.

 nn č piů corretto
Forse ti puo` essere utile:
References in PHP are a means to access the same variable content by
different names. They are not like C pointers, they are symbol table
aliases. Note that in PHP, variable name and variable content are
different, so the same content can have different names. The most close
analogy is with Unix filenames and files - variable names are directory
entries, while variable contents is the file itself. References can be
thought of as hardlinking in Unix filesystem. 
(dal manuale php - language.references.html)
C'e` una sezione del manuale che parla di referenze nei costruttori,
spiegando anche cose come =& new. Nella copia del manuale che ho scaricato
da 
php.net
 questa pagina non c'e`, pero` la trovi nella versione del
manuale di php su 
zend.com
.
http://www.zend.com/manual/language.oop.newref.php
-- 
---Palantir---
ICQ:57482808   
Hi! I'm a .signature virus! Copy me into your ~/.signature, please!

 --
no non può essermi utile è utilissimo!
ti ringrazio moltissimo!
adesso mi leggo tutta sta roba sui puntatori, mi dimentico cos'è il C e java
e penso da phppista .
;)
grazie ancora a te e a Roberto.

allora ecco cosa ho capito
risulta un pň anomalo ho usato le variabili ma č lo stesso con gli oggetti e
il "& new"
ti prego di verificare le mie conclusioni
a questo punto mi viene da dire
uso SEMPRE & davanti al new e risolvo tutti i miei problemi no?
cosě ragiono in riferimenti al costruttore sempre e comunque no?
ecco il codice: (le freccine sono puntatori)
<?php
$a = '';
//b  ------------> 2
$b = 2;
//a  -----------> b --------------> 2
$a = & $b;
//mi da il valore che punta b
print('<br>'.$a);
//b  -----------> 123
$b = 123;
//mi da il valore che punta b
//a  -----------> b --------------> 123
print('<br>'.$a);
/*
OUTPUT:
2
123
*/
//####################################################
//ora se faccio
print('<br>uso unset');
$a = '';
//b  ------------> 2
$b = 2;
//a  -----------> b --------------> 2
$a = & $b;
//mi da il valore che punta b
print('<br>'.$a);
//se faccio unset b: b ----- X ----- 2
//quindi zend engine rimedia cosě
//a  ---------------------------------> 2
unset($b);
//b  -----------> 123
$b = 123;
//mi da il valore che punta a cioč 2 e NON 123
//a  ---------------------------> 2
print('<br>'.$a);
/*
OUTPUT:
2
2
*/
//####################################################
//ora se uso &
print('<br>uso &');
$a = '';
//b  ------------> 2
$b = 2;
//c  ------------> 3
$c = 3;
//a  -----------> b --------------> 2
$a = & $b;
//mi da il valore che punta b
print('<br>'.$a);
//b  ------- X ------ 2  ma
//b  -----------> c --------------> 3
//zend quindi fa una specie di unset automatic e quindi "rimedia"
//a ------------------------------------> 2
$b = & $c;
//mi da il valore che punta $a cioč 2 e NON di $b
//a  ---------------------------> 2
print('<br>'.$a);
/*
OUTPUT:
2
2
*/
?>