Domanda

Sto lavorando su un'applicazione web che farà largo uso di tecniche AJAX per la comunicazione client / server ... JSON-RPC specificamente. Zend Framework è utilizzato sul lato server, e offre una piacevole server JSON-RPC che vorrei utilizzare.

Il mio obiettivo è quello di architetto un sistema gestibile che espone un di grandi dimensioni sottoinsieme delle funzionalità lato server per il client-side (javascript), senza duplicazione codice non necessario. Ho visto numerosi blog e tutorial su come utilizzare il server JSON-RPC di ZF (vedi qui e < a href = "http://sourcecodebean.com/archives/creating-a-json-rpc-service-using-zend-json-server/422" rel = "nofollow"> qui ), ma tutti sembrava orientata verso esponendo una piccola, API di consumo pubblicamente. La duplicazione del codice è comune, per esempio un post sul blog ha il seguente metodo esposto:

public static function setTitle($bookId, $title) {
    $book = new Nickel_Model_Book($bookId);
    $book->setTitle($title);
    $book->update();
    return true;
}

Non mi piace il fatto che ci sono due metodi setTitle. Se la firma del metodo per la si cambia, l'altro deve essere tenuto in sincronia ... sembra un incubo manutenibilità se la vostra API è ampia. Mi sembra che ci dovrebbe essere una classe Book, con un metodo di setTitle.

Il mio pensiero iniziale è aggiungere un docblock un'annotazione @export di metodi / classi che io voglio esposto. Quando decido di esporre il metodo setTitle, mi basta aggiungere l'annotazione piuttosto che un nuovo metodo.

Un potenziale problema che vedo comporta la persistenza degli oggetti. Sul lato server, ha senso per setTitle di impostare la proprietà titolo dell'oggetto ... ma non persistono nel database fino update() viene chiamato. setTitle lato client, chiamando dovrebbe influenzare immediatamente il database. Una possibile soluzione è quella di modificare tutte le funzioni di accesso in modo tale che essi prendono un secondo parametro opzionale a significare la modifica dovrebbe aggiornare immediatamente il database:

function setTitle($title, $persist = false) {
    $this->title = $title;

    if ($persist) $this->update();
}

Una sorta di classe proxy potrebbe assicurare che la bandiera $persist è impostato per tutte le chiamate RPC sul lato client.

Un altro problema è la serializzazione di oggetti PHP. Sul lato server, ha senso fare una chiamata $book->setTitle("foo") OO-stile, ma book.setTitle(1234, "foo") lato client ha un senso (dove 1234 è del libro ID) a causa della mancanza di Stato. La mia soluzione per questo sarebbe di avere la classe proxy di cui sopra sarà responsabile in qualche modo trasformare book.setTitle(1234, "foo") in:

$book = new Book();
$book->load(1234);
return $book->setTitle($title);

Mi sento come questo problema deve essere stato affrontato o discusso prima ... ma non sto trovando molte risorse on-line. Ti sembra una soluzione sana di mente?

È stato utile?

Soluzione

Quello che stai cercando si chiama Servizio strato .

I loro entità dovrebbe essere puramente contenitori di dati (a meno che non si sta utilizzando Active Record), si dovrebbe esporre solo il tuo livello di servizio, e questo a sua volta accede loro entità e le rispettive modalità.

 "La vostra classe Book è un modello di dominio, si dovrebbe ora creare il livello di servizio"

La classe di servizio sarebbe qualcosa di simile:

class BookService extends Service {

    //...

    public function changeBookTitle( $title, Book $book )
    {
        //verify if the $title is correct and valid
        $book->setTitle( $title );
        $this->methodToGetThePersistenceManager()->save( $book );

        //fire events, create a result object, etc...
    }
}

Altri suggerimenti

Sono stato rimuginando la tua domanda per qualche minuto. Se si vuole provare, ed è in PHP, si potrebbe fare alcuni metodi magici della forma

set {Proprietà} di {oggetto}.

È possibile farlo attraverso il metodo magico __call.

In questo modo non avrebbe dovuto definire esplicitamente le modalità, ma le proprietà sarebbe ancora ottenere insieme.

Il metodo di magia sarebbe identificare quale tipo di oggetto che ha da istanziare e che Proprietà per impostare su di esso e quindi persistono.

Si avrebbe dovuto trovare il modo di differenziare le chiamate remote e chiamate urbane anche se così non persistono per errore se stai facendo chiamate di libreria locale e che persistono sulle chiamate remote.

mi sento come se ho frainteso la tua domanda in qualche modo, ma ho provato.

Bene,

Che cosa si vuole fare suona veramente bene su carta, e si desidera il codice sia mantenibile, e in base al sistema attuale, ciò che si chiede può anche essere un po 'al sicuro, ma la cosa si fa vicino ad essere pericoloso e soggetto a errori.

In ogni caso, si sarebbe probabilmente hanno a che fare la maggior parte di voi stessi, o semplicemente inserire qualche sorta di intercettore a tutte le chiamate di metodo, ecco un esempio veloce:

class Book {
  public $title = '';
  public $id = 0;
  public function setTitle($string) {
    $this->title = $string;
    echo "title called with $string\n";
  }
  public function twoArgs($arg1,$arg2) {
    echo "Multi-call: $arg1,$arg2\n";
  }
}
class Api {
  public function parse($json) {
    $jsonobj = json_decode($json,true);
    foreach ($jsonobj as $key=>$value) {
      $class_name = $key;
      $obj = new $class_name();
      foreach ($value as $vkey=>$vvalue) {
        if (method_exists($obj,$vkey)) {
          call_user_func_array(array($obj,$vkey),$vvalue);
        } else if (isset($obj->$vkey)) {
          echo "Setting $vkey\n";
          $obj->$vkey = $vvalue;
        }
      }
    }
  }
}

$json = json_encode(array('Book' => array('id' => 1234, 'setTitle' => array('The new title'))));
$api = new Api();
$api->parse($json);
$json = json_encode(array('Book' => array('id' => 1234, 'twoArgs' => array('arg1 :) ', 'arg2 :]'))));
$api->parse($json);

Ovviamente si vorrebbe aggiungere logica per gestire persistono bandiera, e il caricamento o consentire loro di passare in un costruttore: [args] e maniglia. ecc Quando si tratta di funzioni di esporre, li espongono nella documentazione, sono tutti accessibili fintanto che sono funzioni pubbliche da quel momento in poi, ecc.

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