Meine Superclass für Doctrine 2 Models

In einem neuen Projekt möchte ich gern Doctrine 2 verwenden, und habe schonmal etwas vorgearbeitet und mir eine Superclass für die Models erstellt. Doctrine 2 lässt es zu, Models von solch einer Superclass erben zu lassen, in welcher man beispielsweise Felder festlegen kann, die in jedem Model zur Verfügung stehen sollen.

Meine Superclass füllt ein paar Funktionslücken und ist mit folgenden nützlichen Methoden ausgestattet:

  • Definiert die Felder created und updated (jeweils DateTime) und füllt sie entsprechend beim Erstellen und Updaten des Objektes. Wie in Doctrine 1: “act as timestampable”
  • Bietet eine Model::find($id) Methode, welche die gefundene Row oder sonst “null” zurückgibt. Wird Model::find($id, true) aufgerufen, wird ein neues Objekt erstellt und zurückgegeben, wenn $id nicht gefunden wurde. Nützlich, um zum Beispiel die Funktionen zum Erstellen und Bearbeiten von Zeilen nicht doppelt implementieren zu müssen
  • $obj->from($array) erwartet ein array(‘feldname’=>’neuer wert’,…) und füllt die Felder des Objektes entsprechend. Nützlich um viele Werte gleichzeitig zu setzen.
  • $obj->getFieldName() und $obj->setFieldName($value) geben den Wert von field_name zurück, bzw. setzen ihn. Die setter Methode gibt das Objekt zurück, sodass Methodchaining à la $obj->setField1($val1)->setField2($val)… möglich ist. Die setter und getter unterstützen CamelCase. getCamelCaseString würde das Feld camel_case_string zurückgeben.

Anwendung ist ganz einfach; class My_Model extends Model_Base {}. Außerdem muss in der Zend_Registry der EntityManager von Doctrine abgelegt werden, sodass

$registry = Zend_Registry::getInstance();
$em = $registry->entitymanager;

diesen holen kann! Das ginge auch über eine globale Variable oder sowas.

Hier endlich die Klasse zum Kopieren und Spielen:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<?php
 
/** @MappedSuperclass */
class Model_Base {
    /**
     * @Column(type="datetime")
     */
    private $created;
 
    /**
     * @Column(type="datetime")
     */
    private $updated;
 
    /**
     * set the updated and created fields to "now"
     */
    public function __construct() {
        $this->created = $this->updated = new DateTime("now");
    }
 
    /**
     * @PreUpdate
     */
    public function updated() {
        $this->updated = new DateTime("now");
    }
 
    /**
     * just in case...
     * @return string
     */
    public function __toString() {
        return 'this is not a string!!!';
    }
 
    /**
     * magic method which processes getFieldName() and setFieldName($value)
     * setFieldName() returns the object
     *
     * @param string $method
     * @param array $args
     * @return mixed
     */
    public function __call($method, $args) {
        if(substr($method,0,3)=='get') {
            if(isset($this->{$this->_getFieldName($method)}))
                return $this->{$this->_getFieldName($method)};
        }
 
        if(substr($method,0,3)=='set') {
            if(property_exists(get_class($this), $this->_getFieldName($method))) {
                $this->{$this->_getFieldName($method)} = $args[0];
                return $this;
            }
        }
    }
 
    /**
     * transforms getCamelCaseFieldName to camel_case_field_name
     *
     * @param string $methodname
     * @return string
     */
    private function _getFieldName($methodname) {
        $return = preg_replace('/([A-Z])/','_$1',$methodname);
        return strtolower(substr($return, 4));
    }
 
    /**
     * fetches all rows of the database table
     * @return collection
     */
    public static function getAll() {
        $registry = Zend_Registry::getInstance();
        $em = $registry->entitymanager;
        return $em->getRepository(get_called_class())->findAll();
    }
 
    /**
     * finds the row with id $id. If it doesn't exist and $create is true,
     * it creates the object and returns it
     *
     * @param int $id
     * @param boolean $create
     * @return entityname
     */
    public static function find($id, $create = false) {
        $entityname = get_called_class();
        $registry = Zend_Registry::getInstance();
        $em = $registry->entitymanager;
        $match = $em->getRepository($entityname)->find($id);
        if(!is_null($match))
            return $match;
 
        if($create)
            return new $entityname;
 
        return null;
    }
 
    /**
     * populates the object with values from $array, if it's keys are
     * valid table fields.
     *
     * @param array $array
     * @return $this
     */
    public function from($array) {
        foreach($array as $field=>$value)
            if(property_exists(get_class($this), $field))
                $this->{$field} = $value;
        return $this;
    }
}

0 Responses to “Meine Superclass für Doctrine 2 Models”


  • No Comments

Leave a Reply