Es ist ein Model und es sieht gut aus – Das Grundgerüst

| 1 Kommentar

Nachdem ich beim letzten Mal nun grob die Anforderungen für unsere Model-Klasse beschrieben habe, sollten wir nun auch mal etwas PHP-Code schreiben.

Im ursprünglichen Artikel über die Data Mapper nannte ich die Basis-Klasse einfach nur Container.

Das würde ich nun an dieser Stelle gerne ändern, da ich oft und gerne mit dem Zend Framework arbeite und ich die Klasse, wie weitere folgende auch, gerne in meiner Custom-Library haben will. So benenne ich Container nun einfach in Custom_Model um.

Ein kleiner Schritt für uns, aber ein großer Vorteil für die spätere Verwendung.

Nun geht es erstmal darum, die Schnittstelle der Basisklasse zu definieren. Dazu werde ich sie als Entwurf notieren und die Methoden vorerst leer lassen, da ich im Einzelnen später darauf eingehen werde.

<?php
class Custom_Model implements Custom_Model_Interface
{
  protected $_keys;

  public final function __construct() {}
  public function keyExists($key) {}
  public function keys() {}

  protected function _init() {}
  protected function _initKeys() {}
  protected function _get($key) {}
  protected function _set($key, $value) {}
  protected function _mapKey($key) {}
}

Auch das Interface Custom_Model_Interface bleibt vorerst leer, aber wir werden es im weiteren Verlauf noch brauchen.

<?php
interface Custom_Model_Interface
{
}

Den Konstruktor habe ich final deklariert, weil ich sicherstellen will, dass er nicht überschrieben werden kann. Für spezielle Initialisierungen kann dann die Template-Methode _init() in der konkreten Modelklassen genutzt werden.

public final function __construct()
{
  $this->_initKeys();
  $this->_init();
}

Interessanter als der Konstruktor ist bislang die Methode _initKeys(), die wie der Name schon fast vermuten lässt, eine Liste der verfügbaren Schlüssel generiert. Dazu habe ich Reflections verwendet.

protected function _initKeys()
{
  if(!is_array($this->_keys)) {
    $this->_keys     = array();
    $reflectionClass = new ReflectionClass($this);
    $properties      = $reflectionClass->getProperties();

    $index = 0;

    foreach($properties as $property) {
      if($property->getDeclaringClass()->getName() != __CLASS__ &&
        $property->isProtected()) {
        $intName  = $property->getName();
        $extName = substr($intName, 1);

        $this->_keys[] = $extName;
        $this->_mapping[strtolower($extName)] = $intName;
        $this->_mapping[$index++] = $intName;
      }
    }
  }
}

Über Reflection kann man auf sämtliche Eigenschaften einer Klasse zugreifen. Für unsere Liste lesen wir alle ‘protected’ Variablen aus, die nicht in der selben Klasse definiert wurden. Dadurch können wir die Liste quasi durch eine erbende Klasse konfigurieren. Nebenbei erzeugen wir noch eine Mappingliste mit den Schlüsseln in normalisierter Form.

Als nächstes brauchen wir die Methoden mapKey(), sowie _get() und _set(). Aber warum eigentlich?

Über diese Zugriffsmethoden kann später jede Aktion auf dem Objekt kontrolliert werden und jede weitere Methode muss ihren Aufruf einfach nur noch dahin weiterleiten. Die Methode mapKey() übersetzt dann anhand der Mappingliste die Schlüssel.

protected function _mapKey($key)
{
  $key = strtolower($key);

  if(isset($this->_mapping[$key])) {
    return $this->_mapping[$key];
  }

  trigger_error('Undefined index: ' . $key);
}

Nun, da das Wichtigste soweit vorbereitet ist, können wir nun noch schnell die restlichen Methoden schreiben.

Der Getter…

protected function _get($key)
{
  $key = $this->_mapKey($key);
  return $this->$key;
}

…und dazu der Setter,

protected function _set($key, $value)
{
  $key = $this->_mapKey($key);
  $this->$key = $value;
}

sowie

public function keys()
{
  return $this->_keys;
}

und

public function keyExists($key)
{
  return array_key_exists(strtolower($key), $this->_mapping);
}

Damit hätten wir die Basis auch schon fertig und können in den folgenden Schritten darauf aufbauen.

Ein Kommentar

  1. Pingback: Es ist ein Model und es sieht gut aus « ebene7

Hinterlasse eine Antwort

Pflichtfelder sind mit * markiert.


Schlagwörter: A/B-Test, AbstractType, Adapter, AddOn, Administration, Ajax, Alühn, Alühn2, Amazon, Animation, Annotations, Anonyme Klasse, Ant, Apache, API, Array, ArrayAccess, Attachment, Auftrag, Ausbildung, Auswertung, Authentifizierung, AutoLoader, AWS, Backup, Bedienung, Bedingung, Benchmark, Berechtigung, Berlin, Bildbearbeitung, Bildschirmfoto, Blog, Blogroll, BOM, Bootstrap, Bot, Browser, Bugtracker, Byte Order Mark, Bücher, Cache, CakePHP, Call-Center, Callback, CamelCase, Canvas, Captcha, CDN, Cheatsheet, CLI, Clickout, Closure, Cloud, CodeSniffer, Collection, Community, Comparator, Config, Contest, Controller, Converter, CouchDB, Countable, Cronjob, CRUD, CSS, CSV, CustomLibrary, Custom_Model, Daemon, Data Mapper, Datei, Datenbank, Datensicherung, Datenstruktur, Datentypen, Dating, Datum, Debug, Decorator, Dekorierer, Design, Design Patterns, Doctrine, Dokumentation, Dump, Duplikat, each, EC2, Eclipse, Email, Entwicklung, Entwurfsmuster, Enum, Erweiterung, Event, Eventhandling, Exception-Handling, Extension, Facebook, Factory, Fallback, Fehler, Fehlermeldung, Filter, Firefox, Flash, flexigrid, Foreach, Formatierung, Formular, Framework, FTP, Funktion, Futon, ga:pi(), Getter, Gnome, Google Analytics, Hash, Hash-Bang, Header, htaccess, HTML5, htpasswd, HTTP, HTTPS, IDE, If, Implementierung, InnoDB, Interceptor, Interface, Internet Explorer, isset, Iterator, Java, JavaScript, Job, jQuery, Kommentar, Konfiguration, Konsole, Kontrollstruktur, kopieren, kostenlos, Kundenbetreuung, Late Static Binding, Layout, Links, Linux, Listeners, Lizenz, Logging, Löschen, Magento, Magic Methods, Manual, ManyToMany, Marketing, Methode, Model, Monolog, MVC, MySQL, NetBeans, Network, Nirvanix, Objekt, Observable, Observer, OneToMany, Online Tool, OOP, Open Source, Operator, OR-Mapper, Order, ORM, O’Reilly, Parameter, Partnersuche, Passwort, Performance, PHP, php.ini, PHP hates me, phpMyAdmin, PHPUnit, Plugin, Point and Click, Popup, Praktikum, Proxy, Prüfsumme, Prüfung, QR-Code, Qualitätssicherung, Query, Queue, Redesign, Refactoring, Reflection, Repository, Request, Response, Responsive Design, Rest-API, Rockstar, Rollback, Routing, S3, Samba, Scheifen, Schleife, Schutz, Screenshot, Secure Shell, Selbstreferenz, Server, Setter, setTimeout, Shop, Sicherheit, Sicherung, Sichtbarkeit, Singleton Pattern, Skin, SOAP, Social Network, Software, Sortierung, Sourcecode, Spam, Speicherproblem, Spickzettel, SPL, Splittest, SSH, SSL, Stammtisch, Statement, static, Statistik, Status, Stellvertreter, Strategy Pattern, Stream, String, Stuttgart, Stylesheet, Subversion, Sun VirtualBox, Support, SVN, Switch, Symfony, Symfony2, Symfony Live, Tag, Template, Template Method, Ternär Operator, Testing, Theme, Thumbnail, Tool, Tour, Tracking, Twig, Twitter, Type-Cast, Ubuntu, Umwandlung, Underscore, unset, Update, Upload, Url, User Story, Validierung, Vererbung, Versionskontrolle, Versionsnummer, Verzweigung, Video, Videospiel, Virtualisierung, Visitor Pattern, Vorschaubild, walk, Warteschlange, Webserver, Webservice, Weiterleitung, Werkzeug, Windows, WindowsAzure, WordPress, Wrapper, Writer, XML, Youtube, Zeitschleife, Zeitsteuerung, Zend Framework, Zend_Application, Zend_Cloud, Zend_CodeGenerator, Zend_Http_Client, Zend_Reflection, Zend_Service, ZPress, Zugangskontrolle, Zugriffsmethode