Door
Sander Z
op 26-02-2015 18:25
gewijzigd op 26-02-2015 18:56
1.825 views
Ik ben even de weg kwijt. Ik heb een class waarmee ik settings ophaal uit een database.
Het probleem is alleen dat ik de waardes kan overschrijven, dus ze zijn niet private. Maar ik snap even niet waar ik mis ga.
Dit is een uitgekleed voorbeeld van het script:
<?php
class LoadSettings {
public function __construct () {
$this->fillData();
}
private function fillData() {
$data = $this->getData();
foreach ($data as $key => $value) {
$this->$key = $value;
}
}
private function getData() {
# Ophalen waardes etc...
return $values; # Array met alle waardes
}
public function __get($key) {
return $this->$key;
}
}
?>
Je kunt de waarde van een private variabele (property) van buitenaf niet overschrijven. Binnen de class kun je hiermee doen wat je wilt.
Als je een property binnen een class gebruikt is dit doorgaans $this->propertyName, niet simpelweg $propertyName. $propertyName is slechts een lokale variabele binnen een methode...
Euh, je definieert in regel 13 on-the-fly public properties zoals Wouter J al zei, en de __get() methode is er juist voor dat je variabelen van een object "rechtstreeks" aan kunt spreken.
Als er dus een key "test" zit in $data (ik zie overigens niet eens hoe deze code zou moeten werken of waar deze haar waarden vandaan haalt), dan kun je vervolgens rechtstreeks de waarde van "test" ophalen via $objectNaam->test vanwege je __get() methode.
De waardes van $data komen uit de functie getData. Alle rompslomp die daar gebeurt heb ik even weggelaten. Alle data komt uiteindelijk in de array $values te staan welke gereturned wordt naar $data. (vanuit fillData)
En ik snap dat de __get er voor zorgt dat ik de waardes rechtstreeks kan ophalen. Maar ik snap niet dat ik ze dan kan aanpassen buiten de class.
Maar uit de opmerkingen begrijp ik dus ook dat ik het dus beter niet via de __get kan doen. Dus voor iedere variabele een _get aanmaken?
Wat probeer je uiteindelijk te maken? Een lijst van read-only instellingen?
Dan moet je zorgen dat je ook daadwerkelijk alles in $this->values stopt (EDIT: zie code Pipo hierboven, waarvoor dank), en niet naast de pot piest zoals je nu doet :).
Vervolgens zou je zoiets kunnen doen met je __get methode:
<?php
public function __get($key) {
if (array_key_exists($key, $this->values)) {
return $this->values[$key];
} else {
throw new Exception('config key '.$key.' not found');
}
}
?>
EDIT2: en vervolgens kun je dus rechtstreeks entries uit de private variabele "values" uitlezen via $objectNaam->variabeleNaam (de __get methode haalt dan de waarde van $this->values[variabeleNaam] op of genereert een exception).
Wat je daar doet is waarschijnlijk toch een publieke variabele "test" aanmaken, deze heeft dan "voorrang" op $this->values['test'] waarschijnlijk. Dump $this->values maar eens, volgens mij is die nog ongewijzigd. Of niet. Test het uit.
Een extra voorziening is wellicht het schrijven van een __set methode?
<?php
function __set($var, $val) {
throw new Exception('these properties are readonly');
}
?>