Arraywaarde uit andere class ophalen
Ik loop al een tijdje tegen het volgende probleem aan: stel ik heb een class waar bv. een configuratie is opgeslagen in een array. In een andere klass wil ik één waarde van die array echo-en. Dat doe ik dus met $class->variabele['array-key']. Echter, PHP haalt dan eerst de $class->variabele (de complete array) op, voor de goede waarde bij de key te zoeken.
Dit kan tot geweldige performanceverlies leiden heb ik al gemerkt, dus er moet een manier zijn om dit te voorkomen. Nu kan het wel door een extra methode in te bouwen, bv. getConf($key), die in class X al de key pakt en returned, maar dat vind ik nogal een lelijke manier.
Als voorbeeldje:
Suggesties?
Dit kan tot geweldige performanceverlies leiden heb ik al gemerkt, dus er moet een manier zijn om dit te voorkomen. Nu kan het wel door een extra methode in te bouwen, bv. getConf($key), die in class X al de key pakt en returned, maar dat vind ik nogal een lelijke manier.
Als voorbeeldje:
Code (php)
Gewijzigd op 01/01/1970 01:00:00 door Mark PHP
Wat je kan proberen is de SPL interface ArrayAccess te implementeren in je X class. Dan kan je gewoon echo $x['name']; doen en dan wordt denk ik niet heel de array opgehaald.
Waarom zou je niet getConf ($key) gebruiken, ik denk dat dat toch de beste oplossing is voor jou probleem.
Is het performanceverlies echt zo groot? Kan ik me bijna niet voorstellen.
Waarom zou je niet getConf ($key) gebruiken, ik denk dat dat toch de beste oplossing is voor jou probleem.
Is het performanceverlies echt zo groot? Kan ik me bijna niet voorstellen.
Ik wist niet dat PHP dat deed, lijkt me ook vrij nutteloos je zou een variabel (mits public) gewoon aan moeten kunnen spreken op zijn key als het een array is zonder de key door te lopen.
zoals je zei dus, maar dit lijkt me logischer.
Dit lijkt mij de makkelijkste manier om een variabelen door te geven.
zoals je zei dus, maar dit lijkt me logischer.
Dit lijkt mij de makkelijkste manier om een variabelen door te geven.
Ik zal er even over nadenken. Probleem is dat het goed mogelijk is om meerdere arrays te hebben, bv. configuratie en properties. Dan is ArrayAccess lastig.
Hetzelfde geldt eigenlijk voor zo'n aparte methode, aangezien het een Registry class is (en je dus eigenlijk niet weet wat voor variabelen er zijn opgeslagen).
Over het performance verlies, ik had eerst een class Countries, en daar zaten 200+ landen in zo'n array. Als je dan elke keer de hele array moet ophalen om één land weer te geven, kan het nogal lang duren om er bijvoorbeeld 25 weer te geven (halve seconde).
@Jurgen: gaat denk ik ook niet werken, stel ik moet 25 waarden hebben, dan wordt het wel een lang verhaal.
Hetzelfde geldt eigenlijk voor zo'n aparte methode, aangezien het een Registry class is (en je dus eigenlijk niet weet wat voor variabelen er zijn opgeslagen).
Over het performance verlies, ik had eerst een class Countries, en daar zaten 200+ landen in zo'n array. Als je dan elke keer de hele array moet ophalen om één land weer te geven, kan het nogal lang duren om er bijvoorbeeld 25 weer te geven (halve seconde).
@Jurgen: gaat denk ik ook niet werken, stel ik moet 25 waarden hebben, dan wordt het wel een lang verhaal.
Gewijzigd op 01/01/1970 01:00:00 door Mark PHP
Volgens mij zit het probleem ergens anders. PHP is slim genoeg om niet zomaar een array te kopiëren. $x->conf[$i] is maar een heel klein beetje langzamer dan $a = &$x->conf; $a[$i]. Waarschijnlijk om de reden dat hij bij de eerste syntax eerst $x in het geheugen opzoekt, en dan pas de array. Bij de tweede is $a de array $x->conf.
Getest met een array van 100.000 strings van ongeveer 900 karakters per item. Met geen van beide manieren duurde het langer dan een tiende seconde om ieder element in de array op die manier te benaderen.
Weet je zeker dat je de array niet 25 keer opnieuw aanmaakt? (oplossing: static keyword gebruiken) Of dat je een bestand met de array 25 maal include?
Getest met een array van 100.000 strings van ongeveer 900 karakters per item. Met geen van beide manieren duurde het langer dan een tiende seconde om ieder element in de array op die manier te benaderen.
Weet je zeker dat je de array niet 25 keer opnieuw aanmaakt? (oplossing: static keyword gebruiken) Of dat je een bestand met de array 25 maal include?
Het zit als volgt:
Doordat de magic __get 'config' teruggeeft, neem ik aan dat deze de hele array retourneerd.
Toen ik een getCountry() implementeerde in mijn Countries class, was het script namelijk veel en veel sneller.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class Registry {
private $store = array(
config => array('host' => 'localhost')
);
//constructor etc.
public function __get($key) {//$key geeft 'config'
return isset($this->store[$key]) ? $this->store[$key] : false;
}
}
class Retrieve {
public function __construct() {
$registry = new Registry();
echo $registry->config['host'];
}
}
?>
class Registry {
private $store = array(
config => array('host' => 'localhost')
);
//constructor etc.
public function __get($key) {//$key geeft 'config'
return isset($this->store[$key]) ? $this->store[$key] : false;
}
}
class Retrieve {
public function __construct() {
$registry = new Registry();
echo $registry->config['host'];
}
}
?>
Toen ik een getCountry() implementeerde in mijn Countries class, was het script namelijk veel en veel sneller.
Gewijzigd op 01/01/1970 01:00:00 door Mark PHP
Ja, geen wonder. Een return-value is normaal inderdaad een kopie. Je kan echter wel afdwingen dat hij gewoon een reference neemt, maar dan moet je wel oppassen dat je geen wijzigingen aan de variabele toepast. Die worden dan namelijk ook in het register doorgevoerd.
En nu ik dit test merk ik ook een merkwaardigheid in mijn versie van PHP. Ik gebruik hierbij jouw code, heb alleen de inhoud van Retrieve aangepast. Namelijk:
verandert het register niet (zoals je zou verwachten). Echter, de volgende code verandert het register bij mij wel. Merk op dat ik $x verder niet eens gebruik.
Deze code levert trouwens 2 notices op, "PHP Notice: Indirect modification of overloaded property Registry::$config has no effect" voor regel 3 & 4. Maar blijkbaar heeft het wel degelijk effect... De eerste code levert diezelfde waarschuwing ook op, maar daar klopt hij ook.
En nu ik dit test merk ik ook een merkwaardigheid in mijn versie van PHP. Ik gebruik hierbij jouw code, heb alleen de inhoud van Retrieve aangepast. Namelijk:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$registry = new Registry();
$registry->config['host'] = 'Blaat';
var_dump($registry);
?>
$registry = new Registry();
$registry->config['host'] = 'Blaat';
var_dump($registry);
?>
verandert het register niet (zoals je zou verwachten). Echter, de volgende code verandert het register bij mij wel. Merk op dat ik $x verder niet eens gebruik.
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$registry = new Registry();
$x = &$registry->config['host']; // let op deze
$registry->config['host'] = 'Blaat';
var_dump($registry);
?>
$registry = new Registry();
$x = &$registry->config['host']; // let op deze
$registry->config['host'] = 'Blaat';
var_dump($registry);
?>
Deze code levert trouwens 2 notices op, "PHP Notice: Indirect modification of overloaded property Registry::$config has no effect" voor regel 3 & 4. Maar blijkbaar heeft het wel degelijk effect... De eerste code levert diezelfde waarschuwing ook op, maar daar klopt hij ook.
Mja oke ... een referentie wijst nog steeds naar de hele array, maar een referentie is maar 1 'ding'. Beter dan een volledig kopie, weet alleen niet of het makkelijker werkt.
EDIT: hmm geen idee hoe ik dit goed werkend moet krijgen.
EDIT: hmm geen idee hoe ik dit goed werkend moet krijgen.
Gewijzigd op 01/01/1970 01:00:00 door Mark PHP
Zou je een voorbeeld kunnen geven van een referentie waarbij geen kopie wordt gemaakt? Ik kom er namelijk niet uit en de pagina wordt steeds slomer...




