Domanda

Aggiornamento:. 09/02/2009 - taglie domanda riveduta, fornito esempi migliori, ha aggiunto


Ciao,
Sto costruendo un'applicazione PHP utilizzando il modello di dati mapper tra il database e le entità (oggetti di dominio). La mia domanda è:

Qual è il modo migliore per incapsulare un compito comunemente eseguita?

Per esempio, un compito comune sta recuperando una o più entità del sito dal sito mapper, ed i loro associati (casa) Pagina entità dalla pagina Mapper. Allo stato attuale, vorrei farlo in questo modo:

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

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

Ora che è un esempio abbastanza banale, ma diventa più complicato, in realtà, come ogni sito ha anche un locale associata, e la pagina in realtà ha revisioni multiple (anche se ai fini di questo compito sarei solo interessato al un recente la maggior parte).

ho intenzione di bisogno di fare questo (ottenere la home page del sito e associati, locale ecc) in più posizioni all'interno della mia applicazione, e non posso pensare al modo migliore / posto per incapsulare questo compito, in modo che io non c'è bisogno di ripetere tutto il luogo. Idealmente mi piacerebbe finire con qualcosa di simile:

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

Quando gli enti del sito derivano già hanno i loro entità associate creato e pronto per l'uso.

Lo stesso problema si verifica quando il salvataggio questi oggetti indietro. Dire che ho un'entità sito e l'entità home page associata, e hanno entrambi stati modificati, devo fare qualcosa di simile:

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

Ancora una volta, banale, ma questo esempio è semplificato. La duplicazione di codice si applica ancora.

Nella mia mente ha senso avere una sorta di oggetto centrale che potrebbe prendersi cura di:

  • Recupero di un sito (o siti) e di tutte le entità associate nessessary
  • La creazione di nuove entità del sito con nuove entità associate
  • Facendo un sito (o siti) e di risparmio e tutte le entità associate (se hanno cambiato)

Ma torniamo alla mia domanda, che cosa dovrebbe essere questo oggetto?

  • L'oggetto mapping esistente?
  • Qualcosa sulla base del modello di repository? *
  • Qualcosa di base l'unità di lavoro Patten? *
  • Qualcos'altro?

* non mi completamente comprendere uno di questi, come si può intuire.

C'è un modo standard per affrontare questo problema, e qualcuno potrebbe fornire una breve descrizione di come si erano implementarlo? Non sto cercando per chiunque di fornire un'implementazione completamente funzionante, solo la teoria.

Grazie,
Jack

È stato utile?

Soluzione

Utilizzando il modello di repository / servizio, le vostre classi repository fornirebbero una semplice interfaccia CRUD per ciascuna delle vostre entità, poi le classi di servizio sarebbe un ulteriore livello che esegue logica addizionale come allegare dipendenze entità. Il resto della vostra applicazione poi utilizza solo i servizi. Il vostro esempio potrebbe essere simile a questo:

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

Poi all'interno della classe SiteService si dovrebbe avere qualcosa di simile:

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

Non so PHP che bene quindi vi prego di scusare se c'è qualcosa che non va sintatticamente.

Altri suggerimenti

[Edit: questa voce tenta di affrontare il fatto che è spesso più facile scrivere codice personalizzato per trattare direttamente con una situazione piuttosto che cercare di inserire il problema in un modello.]

I modelli sono belli nel concetto, ma non sempre "mappa". Dopo anni di fascia alta di sviluppo di PHP, abbiamo optato per un modo molto diretto di gestire tali questioni. Considerate questo:

File: Site.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
   }

Quindi, al fine di chiamare (da qualsiasi luogo), basta eseguire:

$aData = Site::Select(123);

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

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

Una cosa da tenere a mente su programmazione OO e PHP ... PHP non mantiene "stato" tra le richieste, in modo da creare un'istanza oggetto solo per averlo immediatamente distrutte spesso non ha senso.

Probabilmente mi metto estraendo il compito comune per un metodo di supporto da qualche parte, quindi in attesa di vedere ciò che il progetto richiede. Ci si sente come se fosse troppo presto per dirlo.

Che cosa è il nome di questo metodo? Il nome di solito allude a cui il metodo appartiene.

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();

rendere il sito oggetto di un Aggregate Root per incapsulare il complesso associazione e garantire la coerenza .

Quindi creare un SiteRepository che ha la responsabilità di recuperare l'aggregato Sito e popolando i suoi figli (comprese tutte le pagine).

Non avrete bisogno di un PageRepository separata (supponendo che non si fanno Pagina una radice aggregato separato), e il tuo SiteRepository dovrebbe avere la responsabilità di recuperare gli oggetti pagina pure (nel tuo caso utilizzando le Mappers esistenti).

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

E allora il metodo findById sarebbe responsabile per la ricerca di tutti i bambini pagina del Sito. Questo avrà una struttura simile alla risposta CodeMonkey1 ha dato, tuttavia credo che si andrà a beneficio di più utilizzando l'aggregata e modelli Repository, invece di creare un servizio specifico per questo compito. Qualsiasi altro recupero / interrogazione / aggiornamento del totale del sito, tra cui uno qualsiasi dei suoi oggetti figlio, potrebbe essere fatto attraverso la stessa SiteRepository.

Modifica: Ecco una breve guida DDD per aiutarvi con la terminologia, anche se mi piacerebbe molto consiglio di leggere Evans se si desidera che l'intero quadro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top