[PHP] ReflectionClass beperking?

Pagina: 1
Acties:

Onderwerpen


Verwijderd

Topicstarter
Hallo allemaal,

In mijn CMS heb ik een System class welke fungeert als register, vrijwel alle classes waarmee gewerkt wordt worden geextend door de System-class.

Ik gebruik de ReflectionClass om van subclasses de properties op te halen en te valideren of ze bestaan, indien niet dan resulteert dit in een InvalidPropertyException. Nu heb ik een probleem dat wanneer een property een 0-waarde toegewezen krijgt de property niet wordt gevonden door mijn Systemclass en dus resulteert in een InvalidPropertyException terwijl de property wel degelijk bestaat.

Ik vind dit zelf een vreemde fout en ik vermoed dat het door de ReflectionClass komt. Is er iemand die hetzelfde heeft gehad? Via Google zoek ik naar extra functionaliteiten voor de ReflectionClass om het probleem op te lossen maar tot noch toe zonder succes.

[ Voor 5% gewijzigd door Verwijderd op 24-09-2009 23:16 ]


Verwijderd

Topicstarter
Het is al opgelost, na wat extra controle kwam ik uit bij een op het eerste gezicht onschuldige validatie. Maar deze wijze accepteert uiteraard geen 0-values.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// ... System.php
public function __set($property, $value)
        {
            $reflection         = new ReflectionClass($this);
            $classProperties    = $reflection->getProperties();
            $property           = "_".$property;
            
            if($reflection->hasProperty($property))
            {               
                if($this->$property = $value)
                {
                    return true;
                }                           
            }
            
            throw new InvalidPropertyException(new String(get_class($this)), new String($property));
        }
// ... System.php


PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ... System.php
public function __set($property, $value)
        {
            $reflection         = new ReflectionClass($this);
            $property           = "_".$property;
            
            if($reflection->hasProperty($property))
            {               
                $this->$property = $value;
                return true;                                
            }
            
            throw new InvalidPropertyException(new String(get_class($this)), new String($property));
        }
// ... System.php


Het vetgedrukte stuk moest zonder validatie, anders faalt het if-statement in geval van een 0-value.

Misschien dat iemand er in toekomst nog iets aan heeft! Tevens stuitte ik de functie hasProperty(), die heb ik nu toegepast omdat het weer een arrayvergelijking scheelt in het schrijven je eigen code ten aanzien van de getProperties() functie.

  • mithras
  • Registratie: Maart 2003
  • Niet online
Waarom ga je überhaupt met een ReflectionClass aan de gang? Je kan in php zeker ook gemakkelijk een property_exists uitvoeren. En daarnaast een String object (waar haal je die vandaan?): het lijkt me allemaal heel erg veel overhead geven die je niet gebruikt.
Tot slot heb je ook op regel #5 een method waarvan je de waarde uiteindelijk ook niet gebruikt. Is het niet heel veel simpeler om zoiets te doen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
public function __set ($name, $value)
{
  $name = '_' . $name;
  if (property_exists($name)) {
    $this->$name = $value;
  } else {
    throw new InvalidPropertyException(
      'Unknown property ' . $property 
      . ' from ' . get_class($this)
    );
  }
  return true;
}
De magic getters en setters zijn voor je performance al niet al te best, als je dan ook nog allemaal objecten erin gaat stoppen die je eigenlijk niet nodig hebt, waarom laat je het dan niet gewoon simpel?

Acties:
  • 0 Henk 'm!

  • flashin
  • Registratie: Augustus 2002
  • Laatst online: 17-12-2023
In mijn CMS heb ik een System class welke fungeert als register, vrijwel alle classes waarmee gewerkt wordt worden geextend door de System-class.
Iets zegt me dat ook de structuur van je systeem OO-technisch niet helemaal snor zit.

Acties:
  • 0 Henk 'm!

  • --MeAngry--
  • Registratie: September 2002
  • Nu online

--MeAngry--

aka Qonstrukt

Dat hoeft niet persé zo te zijn. Het hebben van een Base class die je voor elk object binnen je framework/CMS gebruikt heeft best zijn voordelen. Maar dan moet je het inderdaad wel goed gebruiken.

En of het aanroepen en/of setten van elke property daarbij gecontroleerd moet worden door __get en/of __set daarbij wel zo'n goed doel is weet ik echter niet...

Tesla Model Y RWD (2024)


Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
--MeAngry-- schreef op vrijdag 25 september 2009 @ 12:21:
Dat hoeft niet persé zo te zijn. Het hebben van een Base class die je voor elk object binnen je framework/CMS gebruikt heeft best zijn voordelen. Maar dan moet je het inderdaad wel goed gebruiken.

En of het aanroepen en/of setten van elke property daarbij gecontroleerd moet worden door __get en/of __set daarbij wel zo'n goed doel is weet ik echter niet...
Daarom zou ik alles ook via functies doen, en wanneer je direct de propery benaderd gebruik je de __get en __set. Ik heb bijvoorbeeld een abstract class de ook de base is van al mijn modellen:
PHP:
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
34
35
36
37
38
39
abstract class Default_Model_Abstract
{
    public function __construct (array $options = null)
    {
        if (is_array($options)) {
            $this->setOptions($options);
        }
    }

    public function __set ($name, $value)
    {
        $method = 'set' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            throw new Exception('Invalid property');
        }
        $this->$method($value);
    }

    public function __get ($name)
    {
        $method = 'get' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            throw new Exception('Invalid property');
        }
        return $this->$method();
    }

    public function setOptions (array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            }
        }
        return $this;
    }
}
Je gebruikt de magic methods dan minimaal (omdat je meestal zegt $blog->getTitle()), maar mocht je het een keer direct willen doen, dan heb je die mogelijkheid.
Pagina: 1