Asszociatív tömbből, asszociatív tömb, ami objektumokat tárol
Üdv !
A címet sajnos nem tudtam jobban megfogalmazni, de majd mindjárt megpróbálom érthetőbben leírni a problémát :)
Szóval, adott egy asszociatív tömb, például egy ilyen :Azt, szeretném elérni, hogy ennek a tömbnek, minden elemét átalakítom egy objektummá. Tehát például a $tomb['elso'] eleme, egy olyan objektum lesz, ami az 1 értéket tárolja, amit mondjuk a getValue() metódussal lehet elérni. A $tomb['negyedik'] eleme, pedig egy olyan objektum, aminek az értéke szintén egy tömb lesz, mégpedig az 'elso', 'masodik', és a 'harmadik' kulcsokkal, ahol minden kulcs szintén egy objektumot reprezentál az előzőeknek megfelelően.
Biztos iszonyat könnyű a feladat, de nekem valahogy nem sikerül a dolog. Próbáltam egy ilyen kóddal :..de itt azt a hibát kaptam, a 'map($value->getValue());' sorra, hogy 'Only variables should be passed by reference'. Szóval nem tudom hogyan lehetne ezt megoldani.
A segítséget előre is kösz.
■ A címet sajnos nem tudtam jobban megfogalmazni, de majd mindjárt megpróbálom érthetőbben leírni a problémát :)
Szóval, adott egy asszociatív tömb, például egy ilyen :
$tomb = array(
'elso' => 1,
'masodik' => 2,
'harmadik' => 5,
'negyedik' => array(
'elso' => 1,
'masodik' => 2,
'hamradik' => array(
'elso' => 5,
'masodik' => 4,
)
)
);
Biztos iszonyat könnyű a feladat, de nekem valahogy nem sikerül a dolog. Próbáltam egy ilyen kóddal :
function map(&$array){
foreach($array as $key => $value){
$value = new Objektum($value);
if(is_array($value->getValue())){
map($value->getValue());
}
}
}
A segítséget előre is kösz.
Jah, és a végén...
nem tudom hogy ez egyáltalán valahogy megoldható-e, ha így nem is. Arra gondoltam hogy minden Objektum elemnek, implementálnia kéne az ArrayAccess interfészt, és így talán lehetséges lenne a fenti szintaxis.
Ez már OO PHP és én nem
Épp ezért, ez nem a legjobb megoldás, de legalább valami.. :)
class Tree { static public
Köszi szépen a megoldásokat
private $container;
public function __construct($input_value){
if(is_array($input_value)){
$this->container = array();
foreach($input_value as $key => $value){
$this->container[$key] = new Node($value);
}
} else {
$this->container = $input_value;
}
}
// A következő metódusok az ArrayAccess interfész implementálásához szükségesek...
public function offsetSet($offset, $value) {
//$this->container[$offset] = $value;
}
public function offsetExists($offset) {
//return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
//unset($this->container[$offset]);
}
public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
// get metódus...
public function getValue(){
return $this->container;
}
}
A fönti Node osztály konstruktora két dolgot csinál :
1. Először is megvizsgálja, hogy az input egy tömb-e. Ha igen, akkor végigmegy rajta és feltölti az objektum konténerét, mégpedig úgy, hogy mindegyik kulcsnak egy-egy újabb Node objetktumot feletet meg, amik egyenként majd mind-mind újra ellenőrzik (a konstruktoruk által) a kapott értéküket, így rekurzívan felépül a teljes Fa (ami igazából több fa, mert annyiról van szó, ahány gyökérből áll a legkülső tömb) a Node objektumok egymásba ágyazásából.
2. Ha paraméterül nem tömböt kap a Node objektum, akkor szimplán eltárolja az értékét.
Ezután már nincs szükségünk, csak a kezelendő tömbre, és egy foreach ciklusra, ami referencia szerint átveszi a tömb egyes elemeit, és mindegyikből egy Node objektumot hoz létre. A többi munkát már maguk a Node objektumok végzik, a konstruktorukkal a fönt ismertetett módon.
'elso' => 1,
'masodik' => 2,
'hamradik' => 3,
'negyedik' => array(
'elso' => 1,
'masodik' => 2,
'harmadik' => array(
'elso' => 1,
'masodik' => 2,
)
)
);
foreach($array as &$value){
$value = new Node($value);
}
Ha ezzel mind megvagyunk, akkor úgyan úgy kezelhetjük a tömböt mint annak előtte, kivéve persze, hogy immár minden index-et kezelhetünk objektumként is. Például :
echo $array['elso']->getValue();
// Ez meg kiírná, hogy Array, mivel egy újabb Node objektumokból álló tömböt kapnánk vissza
echo $array['negyedik']['masodik']->getValue();
// Kiírja hogy 2
echo $array['negyedik']['harmadik']['masodik']->getValue();
Értelem szerűen, ha a Node osztályban nem kommenteztem volna ki az offsetSet, offsetExists, offsetUnset metódusokat akkor működnének a következő műveletek is :
echo isset($array['negyedik']['masodik']) ? 'Létezik' : 'Nem létezik';
unset($array['negyedik']['harmadik']['masodik']);
// Kiírná hogy Nem létezik
echo isset($array['negyedik']['harmadik']['masodik']) ? 'Létezik' : 'Nem létezik';
Sőt, ha a Node osztálynak még __toString metódust is írnánk, akkor még a getValue() metódusra se lenne szükség például kiiratáskor. Ezzel csak az a baj, hogy a Node objektum tárolhat tömböt, és szimpla értéket is, tehát itt azért trükközni kéne a __toString metódussal.
inf3rno, a te megoldásod jó,
Hát annyira nem szeretem a constructor injection-t, aztán azért inkább kitettem staticba. Végülis nem is volt muszáj static-ba tenni, lehetett volna a metódusok közé is a fromArray-t.
A lényeg nem is ez volt, hanem, hogy az "&" használatához azért tapasztalat kell, meg érteni kell, hogy mit csinál az ember.
Hát igen...
A "szép" megoldást, meg természetesen a végeredményre értettem. Lehet hogy másképpen is meg lehetett volna oldani mint így konstruktor által, de a lényeg akkor is az ArrayAccess interfészen van. Azért gondolom abban egyetértünk, hogy a :
sokkal szebb, mint a :
Ha nem értünk egyet, akkor a te megoldásod is ugyan ilyen jó :D Mindenesetre köszi szépen a segítséget. Ez a jó a programozásban, hogy számtalan módon meg lehet oldani egy problémát :)
Szívesen segítettem. A
A referenciához még hozzátennék annyit, hogy foreach-nél lehet a tömb elemeket is referenciázni, ahogy csináltam, csak ilyenkor unset-el el kell vágni a referenciát minden ciklus végén.
A hibaüzenet, amit az elején írtál akkor szokott jönni, ha nincs névhez kötve az érték, amit referencia szerint próbálsz átadni. Ilyen akkor fordul elő, amikor return-nek vagy függvényhívásnak értéket adsz közvetlenül, és nem változót. (Az más kérdés, hogy nekem nem jön be, hogy ezért hibát dob a php, de ez van.)
Nem mondtam, hogy a konstruktor rossz megoldás, hiszem működik. :-) Csak annyit, hogy én nem szeretem. Ha konstruktorba teszek ilyesmit, akkor is inkább külön metódusnak adom át onnan is.
ArrayAccess-t régebben én is szerettem, most már nem jön be annyira. A get és put java Map metódusok, és jobban bejönnek. Ha iterálni is akarsz, akkor az IteratorAggregate interface-t is nézd majd meg.
Nem is tudtam...
Átnéztem kicsit jobban,
Itt is lehetett volna használni az eredeti tömb felülírására.
Értem
Nekem azt tanították, hogy lehetőleg kerüljük azokat az eljárásokat, amik a függvénytörzsön kívül is "munkálkodnak". Persze nyilván, néha szükség van rájuk, de egyébként ez úgy általánosságban szerintem nem egy rossz tanács, és megfontolandó :)
Persze, én sem szívesen