質問

私は、クライアント/サーバー通信のためにAJAXテクニックを広範囲に使用するWebアプリケーションに取り組んでいます... JSON-RPC特に。 Zend Frameworkはサーバー側に使用されており、使用したい素敵なJSON-RPCサーバーを提供しています。

私の目標は、 大きい クライアント側(JavaScript)へのサーバー側の機能のサブセット、不要なコードの複製なし。 ZFのJSON-RPCサーバーの使用方法に関する多くのブログ投稿やチュートリアルを見てきました(参照 ここここ)、しかし、それらはすべて、小さく、公的に消費可能なAPIを公開することに向けられているように見えました。コードの複製は一般的です。たとえば、1つのブログ投稿には次の方法が公開されています。

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

私は2つあるという事実が好きではありません setTitle 方法。 1つの変更のメソッド署名が変更された場合、もう1つは同期しておく必要があります... APIが広範囲である場合、保守性の悪夢のように見えます。私には1つがあるべきだと思われます Book クラス、1つ setTitle 方法。

私の最初の考えは、docblockアノテーションを追加することです @export 私が露出したい方法/クラスに。私が公開することにしたとき setTitle 方法、新しいメソッドではなく、注釈を追加するだけです。

私が見ている潜在的な問題の1つは、オブジェクトの持続性に関係しています。サーバー側、それは理にかなっています setTitle オブジェクトのタイトルプロパティを設定するには... update() 呼ばれています。クライアント側、呼び出し setTitle すぐにデータベースに影響を与えるはずです。潜在的な解決策の1つは、すべてのアクセサを変更して、変更を意味するオプションの2番目のパラメーターを取得することです。データベースをすぐに更新する必要があります。

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

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

ある種のプロキシクラスは、次のことを保証できます $persist フラグは、すべてのクライアント側RPCの呼び出しに設定されています。

別の問題は、PHPオブジェクトのシリアル化です。サーバー側では、OOスタイルを行うのは理にかなっています $book->setTitle("foo") 電話ですが、クライアント側 book.setTitle(1234, "foo") 国家が不足しているため、理にかなっています(1234は本の身分証明書です)。これに対する私の解決策は、前述のプロキシクラスに何らかの形でターンする責任を負わせることです book.setTitle(1234, "foo") の中へ:

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

この問題は以前に取り組んだか議論されたに違いないと思います...しかし、私はオンラインで多くのリソースを見つけていません。これは正気な解決策のように思えますか?

役に立ちましたか?

解決

あなたが探しているものは呼ばれています サービスレイヤー.

それらのエンティティは純粋にデータコンテナである必要があります(アクティブレコードを使用している場合を除く)、サービスレイヤーのみを公開する必要があります。これは、エンティティとそれぞれの方法にアクセスする必要があります。

"Your Book class is a Domain Model, you should now create your Service Layer"

あなたのサービスのクラスは次のようなものです:

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...
    }
}

他のヒント

私はあなたの質問を数分間熟考していました。あなたが試してみたい、そしてそれがPHPにあるなら、あなたはフォームのいくつかの魔法の方法を作ることができます

{object}の{プロパティ}をset {property}。

これをMagic __Callメソッドを介して行うことができます。

そうすれば、メソッドを明示的に定義する必要はありませんが、プロパティはまだ設定されます。

魔法の方法は、どのタイプのオブジェクトをインスタンス化する必要があるか、どのタイプのプロパティを設定してから持続するかを識別します。

ただし、リモートコールとローカルコールを区別する方法を見つける必要があります。そのため、ローカルライブラリコールを行っていて、リモートコールで持続している場合は、誤って持続しません。

どういうわけかあなたの質問を誤解したように感じますが、試しました。

上手、

あなたがやりたいことは紙の上で本当に良いように聞こえます、そしてあなたはコードを維持可能にしたい、そしてあなたの実際のシステムに応じて、あなたが尋ねるものはやや安全であるかもしれませんが、それは危険でエラーが発生しやすくなっています。

とにかく、あなたはおそらくこれのほとんどを自分で行う必要があるか、すべてのメソッド呼び出しに何らかのインターセプターを挿入する必要があります。ここに簡単な例があります。

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

明らかに、ロジックを追加して永続的なフラグを処理し、コンストラクターをロードするか、[Arg]を渡して処理します。など。関数の公開に関しては、ドキュメントでそれらを公開する場合、それらはすべてその時点からのパブリック機能である限り、すべてアクセスできます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top