Camping_RIDER: Getter / Setter vs. Eigenschaften im Konstruktor

Beitrag lesen

Aloha ;)

P.P.S.: In PHP musst du dir deine getter und setter ja nichtmal selber schreiben. __get und __set sind wirklich tolle Sachen!

Whoa - bis dahin konnte ich alles unterschreiben - aber __get und __set sind magic methods, die nicht an spezielle Properties gebunden sind. Statt dessen muss man darin eine Weiche vorsehen, um für jedes Property das jeweils richtige zu tun.

Eben - für mich verbessert das die Lesbarkeit ungemein. Statt 22 Methoden für 11 Variablen zu haben habe ich nur 2 Methoden und kann da gezielt drin nachschauen. Und noch besser: ich kann eine default-Aktion vorsehen und muss mich daher im besten Fall um gar nichts mehr kümmern, komme aber gleichzeitig in den Genuss, später ganz einfach Aktionen anflanschen zu können.

__get und __set ermöglichen mir, ziemlich ähnlich zu programmieren wie wenn ich keine getter und setter verwenden würde, dabei aber gleichzeitig die Vorteile abzugreifen.

Beispiel:

Im aktuellen Projekt von @Felix Riesterer und mir hantieren wir viel mit Controller-Objekten, die ihre Daten (mithilfe der zugrunde liegenden Datenbank) selbst verwalten. Die Daten, die aus der Datenbank kommen und wieder in die Datenbank müssen, werden in einem $this->data-Array abgelegt. Via __get und __set wird dann einfach geprüft, ob in $this->data ein passender Schlüssel vorkommt, und dann wird der Wert entweder direkt abgelegt/geliefert (default-Aktion) oder eben vorher noch was gemacht (switch/case).

Das ist in der Praxis für uns sehr komfortabel. Zum Beispiel haben wir immer mal wieder eine ganze Reihe gleichartiger Variablen. Datumswerte beispielsweise, die vom Setter immer auf die selbe Weise (also ein Datumsformat) geprüft werden müssen.

Statt jetzt für drei Datumswerte drei gleiche Setter zu schreiben, notiere ich einfach weitere cases an meinem switch in __set:

public function __set ($name, $value) {

    if (array_key_exists($name, $this->data)) {
		
		// check value
		switch ($name) {

            case 'date_of_deregistration':
            case 'date_of_registration':
			case 'date_of_birth':
				// ensure valid date value or null
				if (!is_null($value) && !preg_match(
					'~^\d{4}-\d{2}-\d{2}$~',
					$value
				)) {
					// shorten possible datetime values
					if (preg_match(
						'~^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$~',
						$value
					)) {
						$value = substr($value, 0, 10);
					} else {
						throw new \Exception(
							$this
							. ' needs a valid date'
							. ' or datetime value for '
							. $name
							. ' property!'
						);
					}
				}
			break;
		}

		$this->data[$name] = $value;
	} else {
        throw new \Exception('No such property found!');
    }
}

Aber ein solcher Router muss in jedes Lesen und Schreiben einer Objekteigenschaft hineingrätschen, und das kostet Zeit.

Abgesehen davon, dass ich tatsächlich eben nicht mit einem Router arbeiten würde (was hätte ich davon? da kann ich ja gleich klassisch auf getter und setter setzen?) riecht das für mich nach Mikrooptimierung.

Wenn dieser Router tatsächlich nichts tut außer das Vorhandensein einer Methode zu prüfen, dann ist dein performancetechnisches Zahlenbeispiel (wenn du mich fragst) um Größenordnungen zu groß (oder dein Server VIIIIEL zu alt 😉).

Was aber tatsächlich einen Unterschied macht ist für mich der viel geringere Schreibaufwand, die bessere Übersichtlichkeit und der deutlich geringere Overhead (für mich, nicht für die Maschine) durch weniger eigenständige Methoden bei der Verwendung von __get und __set.

Aber natürlich: YMMV - wenn du anderes gewohnt bist kann ein anderes Vorgehen für dich übersichtlicher sein. Vieles ist Geschmacks- und Gewöhnungssache.

Grüße,

RIDER

--
Camping_RIDER a.k.a. Riders Flame a.k.a. Janosch Albers-Zoller
# Twitter # Steam # YouTube # Self-Wiki # Selfcode: sh:) fo:) ch:| rl:) br:^ n4:? ie:% mo:| va:) js:) de:> zu:} fl:( ss:) ls:[