variabele in class niet private

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Sander Z

Sander Z

26/02/2015 18:25:55
Quote Anchor link
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:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?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;
    }
    
}

?>
Gewijzigd op 26/02/2015 18:56:56 door Sander Z
 
PHP hulp

PHP hulp

19/04/2024 19:34:58
 
Wouter J

Wouter J

26/02/2015 18:38:25
Quote Anchor link
Een dynamisch aangemaakte property is altijd public. Het is sowieso idioot dat PHP het toestaat om properties "on the run" aan te maken.

Conclusies: Sla de waardes op in een array die zich in 1 property bevind die je van te voren definieert.
 
Sander Z

Sander Z

26/02/2015 18:55:41
Quote Anchor link
De waardes uit de database werden al opgeslagen in een array. Maar die had ik inderdaad nog niet gedefinieerd.

Nu heb ik:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php

  class LoadSettings {
    private $values = array();

?>


Maar nog steeds kan ik de waardes overschrijven...

BTW: Hoe raad jij het aan om te doen dan?
Gewijzigd op 26/02/2015 18:58:05 door Sander Z
 
Thomas van den Heuvel

Thomas van den Heuvel

26/02/2015 20:07:36
Quote Anchor link
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...
 
Sander Z

Sander Z

26/02/2015 20:16:42
Quote Anchor link
Dat weet ik. Dat is mij bekend.

Maar ondanks dat ik de array values nu private heb gemaakt kan ik nog steeds het volgende buiten de class doen:

De class:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php

  class LoadSettings {
    private $values = array();

    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;
    }
    
}

?>


Buiten de class:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
  echo $settings->test;  # Output bijvoorbeeld xxxxx
  $settings->test = 'Oh oh....';  
  echo $settings->test;  # Output Oh oh.....
?>


En dat zou niet moeten kunnen gebeuren als hij private is.
Gewijzigd op 26/02/2015 20:19:57 door Sander Z
 
Thomas van den Heuvel

Thomas van den Heuvel

26/02/2015 20:25:42
Quote Anchor link
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.
 
Sander Z

Sander Z

26/02/2015 20:50:26
Quote Anchor link
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?
Gewijzigd op 26/02/2015 20:52:58 door Sander Z
 
Pipo Clown

Pipo Clown

26/02/2015 20:56:39
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
    private function fillData() {
            $data = $this->getData();
            foreach ($data as $key => $value) {
                $this->values[$key] = $value;
            }
    }
 
Thomas van den Heuvel

Thomas van den Heuvel

26/02/2015 21:02:13
Quote Anchor link
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:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
<?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).
Gewijzigd op 26/02/2015 21:15:27 door Thomas van den Heuvel
 
Sander Z

Sander Z

26/02/2015 21:15:21
Quote Anchor link
Het is inderdaad de bedoeling om read-only instellingen te hebben.

Ik heb de code aangepast, maar helaas. Het werkt nog steeds niet. Ik kan nog steeds buiten de class aanpassen...

Dit is nu de class met jullie wijzigingen:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php

  class LoadSettings {
    private $values = array();
    
    public function __construct () {
      $this->fillData();
    }

    
    private function fillData() {
      $data = $this->getData();
      foreach ($data as $key => $value) {
        $this->values[$key] = $value;
      }
    }

    
    private function getData() {
     # Data ophalen uit database etc....

      return $values;   # array met alle waardes
      
    }
    
    public function __get($key) {
      if (array_key_exists($key, $this->values)) {
        return $this->values[$key];
      }
else {
        throw new Exception('config key '.$key.' not found');
      }
    }
    
}

?>


Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
  echo $settings->test;  # Output bijvoorbeeld xxxxx
  $settings->test = 'Oh oh....';  
  echo $settings->test;  # Output Oh oh.....
?>


BTW: Bedankt voor alle hulp zover! Ik waardeer het!
Gewijzigd op 26/02/2015 21:19:48 door Sander Z
 
Thomas van den Heuvel

Thomas van den Heuvel

27/02/2015 01:01:47
Quote Anchor link
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?

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
function __set($var, $val) {
    throw new Exception('these properties are readonly');
}

?>
 
Sander Z

Sander Z

27/02/2015 11:08:49
Quote Anchor link
In de dump werd ie ook als private aangegeven.
De __set methode bood ook geen oplossing.

Maar ik heb het wel opgelost. Ik weet van te voren welke waardes uitgelezen worden uit de database.
Dus (simpel) ik declareer eerst alle waardes die aangemaakt gaan worden als private. Verder hoef ik dan niets aan te passen aan mijn script en ze zijn niet meer aan te passen.

Enige nadeel van deze methode is wel dat als er in de toekomst een waarde/variabele in de database bijkomt ik deze niet moet vergeten te declareren in de class.
Ben er dus niet helemaal blij mee.

Wat nu als ik deze class helemaal opnieuw zou maken. Hoe zouden jullie het dan doen?
Gewijzigd op 27/02/2015 11:14:17 door Sander Z
 
Thomas van den Heuvel

Thomas van den Heuvel

27/02/2015 11:44:52
Quote Anchor link
Even vanuit een andere invalshoek de zaak bekijken: je bent er zo op gebrand dat die configuratie-variabelen niet veranderd mogen worden, maar het is (voor jou) al duidelijk dat deze alleen gelezen moeten worden (jij weet hoe je hier om zou moeten gaan).

Als je deze dan toch wijzigt, dan is dat iets dat jij zo programmeert (en waarschijnlijk maak je dan een programmeerfout). Als je geen rechtstreekse toegang hebt tot de programmacode kun je (kan iemand anders) dit ook niet aanpassen.

En als iemand anders toegang heeft tot jouw programmacode, dan is het aanpassen van de waarde van een configuratie-variabele een van je minste zorgen lijkt mij.

Je kunt de class al zo maken dat als je de waarde van een niet-bestaande instelling probeert op te vragen dat het systeem bezwaar maakt (die / exception / whatever). Wat zou er nog meer moeten gebeuren, en vooral waarom? Ik begrijp het niet.

Zoals Wouter al aangaf, PHP staat dit soort dingen nu eenmaal toe. Iets anders wensen is zoiets als "Ik wou dat de aarde niet om de zon draaide". Het ligt buiten jouw macht om daar iets aan te wijzigen.

Quote:
Wat nu als ik deze class helemaal opnieuw zou maken. Hoe zouden jullie het dan doen?

Het is niet zozeer hoe je het opzet, maar hoe je er vervolgens mee omspringt. Een onjuist gebruik van wat dan ook levert zelden het gewenste resultaat op.
 
Sander Z

Sander Z

27/02/2015 12:12:34
Quote Anchor link
Duidelijk verhaal. Je hebt gelijk....
Thanks!
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.