2013-03-18 1 views
5

Ich habe viel über das Arbeiten mit separaten Ebenen in PHP geforscht und gelesen, um wartbaren und lesbaren Code zu erstellen. Allerdings sehe ich viel Code, wo die Entität und der Datenbankzugriff in einer Klasse platziert ist. Zum Beispiel:php DAL - getrennte Einheit und Datenbank?

class User{ 
    public $id; 
    public $username; 
    public $database; 

    function add(){ 
      $database->query .... 
    } 
} 

Ich finde das ziemlich merkwürdig, weil man hier die Benutzerklasse mit Datenbankelementen mischen, die halten es erschwert.

Ich arbeite gerne wie folgt aus:

  • eine separate Datenbank-Klasse
  • eine Benutzerklasse
  • ein Userdata Klasse

Dies funktioniert wie folgt:

$database = new Database(); 
$database->openConnection(); 
$dataUser = new DataUser($db); 
$user = new User(1,"myname"); 
$dataUser->saveUser($user); 

Ich frage mich, arbeite ich Der richtige Weg oder ist der erste Weg ein besserer Weg, um Code zu erstellen? Ich finde möglicherweise sehr einfach zu pflegen, weil Sie eine separate Entität und eine separate Datenbank-Klasse haben, um die Datenbankaktionen zu behandeln.

+0

+1 nette Frage :) –

+1

+1 für schöne Frage ... –

Antwort

1

leicht zu pflegen, weil Sie eine separate Einheit und eine separate Datenbank-Klasse haben

Es scheint, Sie sagen, dass Sie von einem entfernt Active Record Ansatz zu einem Data Mapper/Entity/Repository Ansatz verschieben möchten. Das ist eine gute Richtung, um einzuziehen, weil es eine bessere Trennung von Bedenken anwendet. Sie können dies selbst bauen, aber Sie vielleicht einen Blick auf Lösungen wie Doctrine nehmen wollen, wo es Sie etwas entlang der Linien von dem zu tun erlaubt:

$product = new Product(); 
$product->setName($newProductName); 
$entityManager->persist($product); 

Die $product Einheit ist nur eine POPO (Plain Old PHP-Objekt), enthält die Aufzeichnungsdaten und weiß nicht, wie sie beibehalten werden, und wenn Persistenz benötigt wird, wird sie an den Entitätsmanager übergeben, um für das Speichern zu sorgen.

+0

Danke, ich möchte nur Entitäten trennen, damit ich sie als ein Objekt abrufen kann und nicht als ein Array mit den Daten zum Beispiel. Ich werde in Doctrine schauen. – randomizer

1

Persönlich denke ich abstrahieren UserData von User ist wahrscheinlich zu viel. Da in diesem Fall UserData wahrscheinlich ist sehr ähnlich zum Beispiel ProductData sein - sie werden noch add($data) ein enthalten, find($id) usw.

In Ihrem Fall ist User ein Modell in dem MVC Ansatz und ist völlig akzeptabel, Datenbank-Speicher-/Abruflogik zu enthalten. Sie werden jedoch wahrscheinlich feststellen, dass Sie die gleichen DB-Methoden in der Klasse User, die Sie in anderen Modellen haben, erneut erstellen. Hier können Sie beginnen, eine ORM Implementierung zu betrachten. Wobei die gemeinsamen DB-Zugriffsmethoden in einer abstrakten Klasse definiert sind, die dann alle Ihre Modelle erweitern und bei Bedarf überschreiben.

+0

Ich habe dieses Thema wieder gelesen und ich verstehe nicht wirklich Ihre letzte Zeile. Ist es nicht normal, dass meine Userdata, ProductData, etc. alle enthalten, sagen wir eine "Speichern", "Suchen" und "Löschen" -Funktion, weil sie eine Abfrage an eine andere Tabelle ausführen müssen. Ich bekomme hier nicht den Vorteil einer abstrakten Klasse, ich würde eine abstrakte Klasse verwenden, um meinen Datenbankadapter instanziieren zu lassen, damit er in allen meinen xData-Klassen verwendet werden kann. – randomizer

1

Was ich tue:

Meine Modelle sind nicht mit der Datenbank verknüpft Entities (wenn ich verwende Lehre nicht), so dass keine „aktive Datensatz“ Methoden. Ein Objekt weiß nicht, wie es seine Abhängigkeiten abrufen soll (zum Beispiel kann ein Benutzer n Kommentare haben, mein Modell weiß nicht, wie man Kommentare bekommt).

Ich habe Dienstleistungen, die einige Geschäftslogik halten, die Modelle von Anbietern holen können, ein Service kann viele Anbieter haben.

class UserService{ 
    function __construct(IUserProvider $userProvider){ 
     $this->userProvider = $userProvider 
    } 
    function getUsers(){ 
     // return an array of user objects 
     return $this->userProvider->getUsers(); 

    } 
} 

schließlich habe ich einen Datenprovider, der weiß, wie Daten aus der Datenbank zu beantragen, eine Textdatei, eine JSON-Datei, eine Webservice:

class UserProvider implements IUserProvider{ 
     function __construct(Connection $connection){ 
     $this->connection = $connection; 
     } 
     function getUsers(){ 
     return $this->toUsers($this->connection->fetchAssoc("Select * from users")); 
     } 
     function toUsers(array $datas){ 
      // convert user records to an array of User 
      (...) 
      return $users; 
     } 
} 

dann die Schnittstelle

interface IUserProvider{ 
    /**@return array an array of User */ 
    function getUsers(); 
} 

Wenn ich einen Benutzerkommentar abrufen muss, weiß mein Kommentardienst, wie Kommentare von einer Benutzer-ID abgerufen werden. Um einen Benutzer und seine Kommentare zu erhalten, brauche ich zwei Anfragen an die Datenbank. eine aus dem UserProvider, die andere aus dem CommentProvider.

so habe ich 3 Schichten:

  • meine Anwendungsschicht (Display Benutzer, reagieren auf Anfragen was auch immer ...)
  • meine Service-Layer (die mit einer Kommandozeilen-Schnittstelle zu arbeiten und ist nicht bewusst, meine Web-Anwendung, mit Ausnahme von Passwort-Codierung, die in der Regel auf den Rahmen binded i verwenden und ACL stopft vielleicht ...)
  • meine Datenzugriffsschicht, die nichts über die anderen Schichten kennt,

Die einzige Art und Weise, wie meine Schichten kommunizieren, ist durch Modelle, die ich von Schicht zu Schicht durchlasse.

Und alle meine Klassen sind mit einem Dependency-Injektion Container gebaut, so dass die Verkabelung kein Problem ist.

Hier ein exemple einer App ist i gemacht, es ist Open-Source-: https://github.com/Mparaiso/silex-bookmarkly

Irgendwelche Gedanken willkommen.