2010-03-09 19 views
9

Angenommen, ich habe eine Klasse, die eine Person darstellt, eine Variable in dieser Klasse wäre $ name.Objektorientierte Best Practices von PHP

Zuvor In meiner Skripte ich eine Instanz des Objekts erstellen würde stellen Sie dann den Namen nur mit:

$object->name = "x"; 

jedoch wurde mir gesagt, diese Praxis nicht am besten ist? Das sollte ich eine Funktion set_name() oder etwas ähnliches wie folgt haben:

function set_name($name) 
{ 
    $this->name=$name; 
} 

Ist das korrekt?

Wenn ich in diesem Beispiel einen neuen "Personen" -Datensatz in die db einfügen möchte, wie gebe ich alle Informationen über die Person, dh $ name, $ age, $ address, $ phone usw. an die Klasse in Reihenfolge weiter um es einzufügen, sollte ich tun:

function set($data) 
{ 
    $this->name= $data['name']; 
    $this->age = $data['age']; 
    etc 
    etc 

} 

Dann senden Sie ihm ein Array? Wäre das eine gute Praxis? oder könnte jemand bitte Best Practice empfehlen?

Antwort

21

Explizite Getter und Setter für Eigenschaften für das Objekt (wie das Beispiel, das Sie für set_name gab), anstatt sie direkt Zugriff gibt Ihnen (unter anderem) folgende Vorteile:

  • Sie können die internen ändern 'Implementierung ohne externe Aufrufe zu ändern. Auf diese Weise muss der "externe" Code nicht so oft geändert werden (weil Sie einen konsistenten Zugriff bereitstellen).
  • Sie geben sehr explizit an, welche Eigenschaften von außerhalb der Klasse verwendet/aufgerufen werden sollen. Dies wird sich als sehr nützlich erweisen, wenn andere Personen Ihre Klasse verwenden.

die oben genannten Gründe ist, warum diese beste Praxis in Betracht gezogen werden könnte, obwohl es nicht wirklich notwendig ist, dies zu tun (und für einige Anwendungen Overkill in Betracht gezogen werden könnte, zum Beispiel, wenn das Objekt sehr wenig ‚Verarbeitung‘ tut, aber fungiert lediglich als Platzhalter für "Daten".

+0

Ein weiterer wichtiger Punkt bei der Verwendung von Getter/Setter ist es, alle Methoden als 'public' zu vermeiden, damit der Entwickler sie ohne Kontrolle nicht ändern kann. – Strae

2

Als Kontrapunkt zu ChristopheDs Antwort, würde ich, wenn Ihre Instanzvariable ausschließlich für den privaten Gebrauch ist, nicht mit dem Schreiben eines Getters & Setter und nur deklarieren die Instanzvariable privat.

Wenn andere Objekte auf das Objekt zugreifen müssen, können Sie immer einen Getter hinzufügen. (Dies setzt ein weiteres Problem, dass andere Klassen das Objekt durch den Getter zurückgegeben ändern könnte können. Aber Ihr Getter kann immer zurückgeben Kopie der Instanzvariablen.)

Zusätzlich mit einem Getter/Setter auch Schirme andere Teile der gleichen Klasse von Wissen über seine eigene Implementierung, die ich bei Gelegenheit sehr nützlich gefunden habe!

6

Ich stimme CristopheD (abgestimmt) vollkommen zu. Ich würde nur eine gute Übung hinzufügen, wenn Sie eine neue Person erstellen.

Normalerweise verwenden Sie einen Konstruktor, der die Pflichtfelder akzeptiert und die Standardwerte für die optionalen Felder festlegt.Etwas wie:

class Person 
{ 
    private $name; 
    private $surname; 
    private $sex; 

    // Male is the default sex, in this case 
    function Person($name, $surname, $sex='m'){ 
    $this->name = $name; 
    $this->surname = $surname; 
    $this->sex = $sex; 
    } 

    // Getter for name 
    function getName() 
    { 
    return $this->name; 
    } 

    // Might be needed after a trip to Casablanca 
    function setSex($sex) 
    { 
    $this->sex = $sex; 
    } 
} 

Offensichtlich könnten Sie die Setter-Methode im Konstruktor verwenden (man beachte den doppelten Code für das Geschlecht Setter).

+4

"Könnte nach einer Reise nach Casablanca benötigt werden" LOL – Kirzilla

+2

Zwei Dinge zu beachten: 1. Konstruktoren in PHP 5+ haben diese Struktur: __construct() {} 2. In PHP können Sie nicht zwei Konstruktoren erstellen Mit verschiedenen Signaturen, wie Person (String $ name) und Person(), können Sie nur eine haben. (Es gibt jedoch Möglichkeiten, dies ganz einfach zu erreichen.) – Nacho

1

Aus allgemeiner Sicht gelten sowohl der direkte Zugriff ($ person-> name) als auch die Accessor-Methoden ($ person-> getName) als schädlich. In OOP sollten Objekte kein Wissen über ihre interne Struktur teilen und nur an sie gesendete Nachrichten ausführen. Beispiel:

// BAD 

function drawPerson($person) { 
    echo $person->name; // or ->getName(), doesn't matter 
} 

$me = getPersonFromDB(); 
drawPerson($me); 

// BETTER 

class Person .... 
    function draw() { 
     echo $this->name; 
    } 

$me = getPersonFromDB(); 
$me->draw(); 

mehr Lesung: http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html

29

Sie sollten Setter/Getter-Methoden haben. Sie sind ein Schmerz, aber Sie müssen sie nicht unbedingt selbst schreiben. Eine IDE (z. B. Eclipse oder Netbeans) kann diese automatisch für Sie generieren, solange Sie das Klassenmitglied angeben. Wenn aber wollen Sie nicht mit diesem überhaupt beschäftigen und Sie sind auf PHP5 können Sie die magischen Methoden verwenden, um das Problem zu beheben:

protected $_data=array(); 
    public function __call($method, $args) { 
     switch (substr($method, 0, 3)) { 
      case 'get' : 
       $key = strtolower(substr($method,3)); 
       $data = $this->_data[$key]; 
       return $data; 
       break; 
      case 'set' : 
       $key = strtolower(substr($method,3)); 
       $this->_data[$key] = isset($args[0]) ? $args[0] : null; 
       return $this; 
       break; 
      default : 
       die("Fatal error: Call to undefined function " . $method); 
     } 
    } 

Dieser Code wird jedes Mal, wenn Sie eine nicht vorhandene Methode verwenden, läuft beginnend mit Set oder Get. So können Sie jetzt setzen/get (und erklären implizit) Variablen wie folgt:

$object->setName('Bob'); 
$object->setHairColor('green'); 

echo $object->getName(); //Outputs Bob 
echo $object->getHairColor(); //Outputs Green 

Keine Notwendigkeit an Mitglieder oder Setter/Getter Funktionen zu erklären. Wenn Sie in der Zukunft Funktionalität zu einer set/get-Methode hinzufügen müssen, deklarieren Sie sie einfach, indem Sie die magische Methode im Wesentlichen außer Kraft setzen. Da auch die Setter-Methode gibt $ this Sie können sie wie so chain:

$object->setName('Bob') 
     ->setHairColor('green') 
     ->setAddress('someplace'); 

, die für Code macht, die sowohl einfach zu schreiben und zu lesen ist.

Der einzige Nachteil dieses Ansatzes ist, dass es Ihre Klassenstruktur schwieriger zu erkennen macht. Da Sie im Wesentlichen Member und Methoden zur Laufzeit deklarieren, müssen Sie das Objekt während der Ausführung ausgeben, um zu sehen, was es enthält, anstatt die Klasse zu lesen. Wenn Ihre Klasse ein klar definiertes Interface deklarieren muss (weil es eine Bibliothek ist und/oder Sie möchten, dass phpdoc die API-Dokumentation generiert), würde ich Ihnen dringend raten, die public facing set/get-Methoden zusammen mit dem obigen Code zu deklarieren.

+0

+1 Als ich die Frage sah, dachte ich sofort in diese Richtung. Gute Antwort! –

+0

Das ist eine interessante Technik. – dmp

+0

Glaub mir, magische Getter/Setter sind es nicht wert. –

4

volle OOP zu gehen, Sie etwas Ähnliches tun sollten:

class User { 

private $_username; 
private $_email; 

public function getUsername() { 
    return $this->_username; 
} 
public function setUsername($p) { 
    $this->_username = $p; 
} 
... 
public function __construct() { 
    $this->setId(-1); 
    $this->setUsername("guest"); 
    $this->setEmail(""); 
} 
public function saveOrUpdate() { 
    System::getInstance()->saveOrUpdate($this); 
} 
} 

Wenn Sie einen Benutzer speichern möchten, können Sie eine gerade erstellen, weisen ihre Werte Setters mit und do $ user-> saveOrUpdate() , und haben eine andere Klasse, um alle Sparlogik zu behandeln.