Objektorientierung mit Models

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Ein Model wird beim Model-View-Controller genutzt und enthält die Daten auf die der Controller zugreift um sie in der View darzustellen.
    == Erläuterung ==
    Der Code ist zur Hilfenahme entstanden, als die Frage geklärt werden sollte ob man die Validierung im Controller oder im Model praktizieren sollte: Überprüfung von Werten in $_POST Feldern. Mehr Informationen zum Basismodel sollen noch folgen. Jeder ist aber angehalten den Artikel zu verbessern.

    Das hier erläutere Verfahren nutzt object-relational mapping bzw Objektrelationale Abbildung - kurz ORM.

    == Basismodel ==

    Quellcode

    1. abstract class Model {
    2. protected $primarykey = 'id';
    3. protected $data = array();
    4. abstract public function getColumns();
    5. function __construct($data = array()) {
    6. $this->data = $data;
    7. }
    8. public static function findById($id, $className) {
    9. $sql = "SELECT *
    10. FROM ".$this->getTablename()."
    11. WHERE ".$this->primarykey." = :id ";
    12. $stmt = MyDB::getInstance()->prepare($sql);
    13. $stmt->execute(array(
    14. ':id' => $id
    15. ));
    16. return new $className($stmt->fetch());
    17. }
    18. protected function _findById() {
    19. }
    20. public function __set($name, $value) {
    21. $this->data[$name] = $value;
    22. }
    23. public function __get($name) {
    24. return $this->data[$name];
    25. }
    26. /**
    27. * empty() on a __get function will not work as expected if isset has not been overriden
    28. */
    29. public function __isset($key) {
    30. if (isset($this->data[$key])) {
    31. return (false === empty($this->data[$key]));
    32. } else {
    33. return null;
    34. }
    35. }
    36. public function validate() {
    37. }
    38. public function getTablename() {
    39. return get_class($this);
    40. }
    41. public function delete() {
    42. $primaryval = $this->{$this->primarykey};
    43. $sql = 'DELETE FROM '.$this->getTablename().' WHERE '.$this->primarykey.' = :primaryval';
    44. $stmt = MyDB::getInstance()->prepare($sql);
    45. $stmt->execute(array(
    46. ':primaryval' => $primaryval
    47. ));
    48. }
    49. public function save($override = null) {
    50. if($override !== null) {
    51. $this->data = array_merge($this->data, $override);
    52. }
    53. $this->validate();
    54. $params = array();
    55. $primaryval = $this->{$this->primarykey};
    56. // insert or update
    57. if($primaryval === null) {
    58. $sql = 'INSERT INTO '.$this->getTablename().' ('.implode(',', $this->getColumns()).') VALUES (';
    59. foreach($this->getColumns() as $key) {
    60. $sql .= ':'.$key.',';
    61. $params[':'.$key] = $this->$key;
    62. }
    63. $sql = rtrim($sql,',').')';
    64. if(count($params)) {
    65. $stmt = MyDB::getInstance()->prepare($sql);
    66. $stmt->execute($params);
    67. // remember auto increment key
    68. $this->{$this->primarykey} = MyDB::getInstance()->lastInsertId();
    69. }
    70. } else {
    71. $sql = 'UPDATE '.$this->getTablename().' SET ';
    72. foreach($this->getColumns() as $key) {
    73. $sql .= $key.' = :'.$key.',';
    74. $params[':'.$key] = $this->$key;
    75. }
    76. $sql = rtrim($sql,',').' WHERE '.$this->primarykey.' = :primaryval';
    77. if(count($params)) {
    78. $params[':primaryval'] = $primaryval;
    79. $stmt = MyDB::getInstance()->prepare($sql);
    80. $stmt->execute($params);
    81. }
    82. }
    83. }
    84. }
    Alles anzeigen


    == Beispielimplementierung eines Benutzers ==

    Quellcode

    1. class User extends Model {
    2. public function getTablename() {
    3. return get_class($this); // user
    4. }
    5. public function getColumns() {
    6. return array('email', 'password');
    7. }
    8. public function validate() {
    9. if(...) {
    10. throw new ValidateException('message');
    11. }
    12. }
    13. }
    Alles anzeigen


    == Beispiele ==
    === Neuen Benutzer anlegen ===

    Quellcode

    1. <form method="post">
    2. email: <input type="text" name="email" /><br/>
    3. password: <input type="password" name="password" /><br/>
    4. <input type="submit">
    5. </form>
    6. <?php
    7. if(count($_POST)) {
    8. $user = new User($_POST);
    9. $user->save();
    10. }
    11. ?>
    Alles anzeigen


    === Benutzer bearbeiten ===

    Quellcode

    1. <form method="post" action="edit.php?userid=123">
    2. email: <input type="text" name="email" /><br/>
    3. password: <input type="password" name="password" /><br/>
    4. <input type="submit">
    5. </form>
    6. <?php
    7. if(count($_POST) && isset($_GET['userid'])) {
    8. $user = User::findById($_GET['userid']);
    9. $user->save($_POST);
    10. }
    11. ?>
    Alles anzeigen

    2.861 mal gelesen

Kommentare 0

  • vince -

    Was ich ein bischen unschön finde ist, das der Konstruktor das gesamte Post Array entgegennimmt / entgegennehmen kann.
    [syntax="php"]$user = new User($_POST);[/syntax]

    Das ist natürlich sehr einfach und praktisch, aber wird später sehr unübersichtlich.
    Man selber und vorallem auch andere wissen nicht, welche Felder es denn überhaupt gibt und was required ist oder was selber von dem Model intern ggf. übernommen wird.

    Um das zu wissen müsste man immer in die Datenbank gucken, welche Felder es gibt und wie diese heissen und dann nochmal in die Klasse schauen falls es noch weitere interne Verarbeitungen gibt.


    Ich finde die längere Variante, alles einzeln über den Konstruktor zu setzen und / oder für alle einen Getter & Setter zu implementieren, vorallem hinsichtlich der Lesbarkeit & Wiederverwendbarkeit , schöner.


    Zum Beispiel Doctrine nutzt die magischen Getter & Setter, setzt aber als ausgleich alle Felder als Kommentar, so das die IDE´s das bei, Autocomplete trotzdem alles sauber anzeigen.


    Aber ansonsten wieder ein schöner Artikel :)