Frage

Aktualisiert:. 09/02/2009 - Revised Frage, vorausgesetzt, bessere Beispiele, hinzugefügt Prämie


Hallo,
Ich baue eine PHP-Anwendung der Daten Mapper Muster zwischen der Datenbank und den Entitäten (Domain-Objekten). Meine Frage lautet:

Was ist der beste Weg, um eine häufig ausgeführte Aufgabe zu verkapseln?

Zum Beispiel ist eine gemeinsame Aufgabe abruft eine oder mehrere Website Einheiten von der Site Mapper, und ihre zugehörigen (home) Seite Entitäten von der Seite Mapper. Derzeit würde ich das tun, wie folgt:

$siteMapper = new Site_Mapper();
$site = $siteMapper->findByid(1);

$pageMapper = new Page_Mapper();
$site->addPage($pageMapper->findHome($site->getId()));

Nun, das ist ein ziemlich einfaches Beispiel, aber es wird noch komplizierter in der Realität, auch als jede Website hat eine zugehörige locale und die Seite hat tatsächlich mehrere Revisionen (obwohl für die Zwecke dieser Aufgabe würde ich nur in der interessiert sein jüngste).

Ich werde brauchen diese (erhalten Sie die Website und Homepage zugeordnet, locale etc.) zu tun, an mehreren Stellen innerhalb meiner Anwendung, und ich kann nicht der beste Weg / Ort denken, diese Aufgabe zu kapseln, so dass ich nicht wiederholen muß, um es ganz über den Platz. Im Idealfall würde ich mit so etwas wie dies am Ende mögen:

$someObject = new SomeClass();
$site = $someObject->someMethod(1); // or
$sites = $someObject->someOtherMethod();

Wenn die resultierende Website Einheiten bereits ihre zugehörigen haben Einheiten erstellt und einsatzbereit.

Das gleiche Problem tritt auf, wenn diese Objekte wieder zu speichern. Sagen, dass ich eine Website Einheit und der zugehörigen Homepage Unternehmen haben, und sie haben beide modifiziert worden, ich, so etwas zu tun haben:

$siteMapper->save($site);
$pageMapper->save($site->getHomePage());

Auch hier trivial, aber dieses Beispiel vereinfacht. Die Vervielfältigung des Codes noch gilt.

In meinem Kopf ist es sinnvoll, eine Art zentraler Aufgabe zu haben, die dafür sorgen könnte aus:

  • Abrufen einer Website (oder Websites) und alle nessessary assoziierten Unternehmen
  • Erstellen von neuen Standort Einheiten mit neuen assoziierten Unternehmen
  • Eine Website (oder Sites) wird und es und alle damit verbundene Einheiten speichern (wenn sie haben geändert)

auf meine Frage Also zurück, was soll diese Aufgabe sein?

  • Die bestehende Mapperobjekt?
  • Something basierend auf dem Repository-Muster? *
  • Etwas auf der Grundlage der Arbeitseinheit patte? *
  • Etwas anderes?

* ich nicht voll entweder davon verstehen, wie Sie wahrscheinlich erraten kann.

Gibt es eine standardisierte Möglichkeit, dieses Problem zu nähern, und könnte jemand eine kurze Beschreibung liefern, wie sie sie umsetzen würden? Ich bin nicht für alle, die eine voll funktionsfähige Implementierung zur Verfügung zu stellen, nur die Theorie.

Danke,
Jack

War es hilfreich?

Lösung

Mit dem Repository / Service Mustern, Ihre Repository-Klassen eine einfache CRUD-Schnittstelle für jede Ihrer Einheiten bieten würden, dann würden die Serviceklassen eine zusätzliche Schicht sein, wie Befestigungseinheit Abhängigkeiten zusätzliche Logik ausführt. Der Rest Ihrer App nutzt dann nur die Dienste. Ihr Beispiel könnte wie folgt aussehen:

$site = $siteService->getSiteById(1); // or
$sites = $siteService->getAllSites();

Dann in der Site Klasse würden Sie so etwas wie diese:

function getSiteById($id) {
  $site = $siteRepository->getSiteById($id);
  foreach ($pageRepository->getPagesBySiteId($site->id) as $page)
  {
    $site->pages[] = $page;
  }
  return $site;
}

Ich weiß nicht, PHP, das gut so entschuldigen Sie bitte, ob etwas nicht in Ordnung syntaktisch ist.

Andere Tipps

[Edit: Dieser Eintrag versucht, die Tatsache anzusprechen, dass es oft einfacher ist, benutzerdefinierten Code zu schreiben, um direkt mit einer Situation zu umgehen, als es zu versuchen, das Problem zu einem Muster passen.]

Muster sind schön in Konzept, aber sie nicht immer „Karte“. Nach Jahren hohe PHP-Entwicklung Ende haben wir uns auf eine sehr direkte Art und Weise des Umgangs mit solchen Angelegenheiten angesiedelt. Bedenken Sie:

Datei: seite.php

class Site
{
   public static function Select($ID)
   {
      //Ensure current user has access to ID
      //Lookup and return data
   }

   public static function Insert($aData)
   {
      //Validate $aData
      //In the event of errors, raise a ValidationError($ErrorList)

      //Do whatever it is you are doing

      //Return new ID
   }

   public static function Update($ID, $aData)
   {
      //Validate $aData
      //In the event of errors, raise a ValidationError($ErrorList)

      //Update necessary fields
   }

Dann, um es zu nennen (von überall), nur laufen:

$aData = Site::Select(123);

Site::Update(123, array('FirstName' => 'New First Name'));

$ID = Site::Insert(array(...))

Eine Sache im Auge zu behalten über OO-Programmierung und PHP ... PHP nicht halten „Staat“ zwischen den Anforderungen, so eine Objektinstanz zu schaffen gerade zerstörten sie sofort haben oft nicht sinnvoll.

Ich würde wahrscheinlich durch Extrahieren der gemeinsame Aufgabe zu einer Helfer-Methode irgendwo, dann warten, um zu sehen, was das Design beginnen fordert. Es fühlt sich an wie es ist zu früh zu sagen.

Was würden Sie diese Methode nennen? Der Name der Regel Hinweise auf, wo die Methode gehört.

class Page {

  public $id, $title, $url;

  public function __construct($id=false) {
    $this->id = $id;
  }

  public function save() {
    // ...
  }

}

class Site {

  public $id = '';
  public $pages = array();

  function __construct($id) {
     $this->id = $id;
     foreach ($this->getPages() as $page_id) {
       $this->pages[] = new Page($page_id);
     }
  }

  private function getPages() {
    // ...
  }

  public function addPage($url) {
    $page = ($this->pages[] = new Page());
    $page->url = $url;
    return $page;
  }

  public function save() {
    foreach ($this->pages as $page) {
      $page->save();
    } 
    // ..
  }

}

$site = new Site($id);
$page = $site->addPage('/');
$page->title = 'Home';
$site->save();

Machen Sie Ihre Website ein Aggregate Root- die komplexe Assoziation zu kapseln und Konsistenz gewährleisten .

Dann erstellen Sie eine SiteRepository , die die Verantwortung für das Abrufen der Website-Aggregat und bevölkern seine Kinder (einschließlich aller Seiten).

Sie werden keine separaten PageRepository benötigen (unter der Annahme, dass Sie keine Seite eine separate Aggregat Wurzel machen), und Ihre SiteRepository sollten die Verantwortung für das Abrufen der Seite Objekte als auch (in Ihrem Fall von Ihrem bestehenden Mapper verwendet wird) haben.

So:

$siteRepository = new SiteRepository($myDbConfig);
$site = $siteRepository->findById(1); // will have Page children attached

Und dann würde die findById Methode für auch zu finden, all Seite Kinder der Website verantwortlich. Dies wird eine ähnliche Struktur wie die Antwort hat CodeMonkey1 gab, aber ich glaube, Sie mehr profitieren, indem die Aggregate und Repository-Muster verwenden, anstatt einen bestimmten Dienst für diese Aufgabe zu schaffen. Jede andere Retrieval / Abfrage / Aktualisierung des Website-Aggregats, einschließlich eines seiner untergeordneten Objekte, würde durch die gleiche SiteRepository erfolgen.

Edit: Hier ein kurzer DDD-Führer zu helfen mit die Terminologie, obwohl ich wirklich empfehlen würde lesen Evans , wenn Sie das ganze Bild wollen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top