13

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

私の目標は、不要なコードの重複なしに、サーバー側の機能の部分をクライアント側 (javascript) に公開する保守可能なシステムを構築することです。ZF の JSON-RPC サーバーの使用方法に関するブログ記事やチュートリアルを数多く見てきましたが (ここここを参照)、それらはすべて、一般に使用できる小さな API を公開することを目的としているように見えました。コードの重複はよくあることです。たとえば、あるブログ投稿で次のメソッドが公開されています。

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

setTitle2つの方法があるという事実は好きではありません。1 つのメソッド シグネチャが変更された場合、もう 1 つのメソッドの同期を維持する必要があります... API が広範囲に及ぶ場合、保守性の悪夢のように思えます。Book1 つのメソッドを持つ 1 つのクラスが必要であるように私には思えsetTitleます。

@export私の最初の考えは、公開したいメソッド/クラスにdocblock 注釈を追加することです。メソッドを公開することに決めたときsetTitleは、新しいメソッドではなく、注釈を追加するだけです。

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

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

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

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

もう 1 つの問題は、PHP オブジェクトのシリアル化です。サーバー側では OO スタイルの呼び出しを行うのが理にかなっていますが、状態がないため$book->setTitle("foo")クライアント側book.setTitle(1234, "foo")(1234 は本の ID) では理にかなっています。これに対する私の解決策は、前述のプロキシクラスが何らかの形で次のようになることを担当することbook.setTitle(1234, "foo")です。

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

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

4

3 に答える 3

3

あなたが探しているのはService Layerと呼ばれるものです。

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

サービスのクラスは次のようになります。

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...
    }
}
于 2011-09-09T19:28:23.120 に答える
1

良い、

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

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

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

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

于 2011-08-20T15:06:51.857 に答える
1

私はあなたの質問について数分間熟考していました。試してみたい場合、それが PHP である場合は、次の形式の魔法のメソッドをいくつか作成できます。

{Object} の {Property} を設定します。

これは、魔法の __call メソッドを使用して実行できます。

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

魔法のメソッドは、インスタンス化する必要があるオブジェクトのタイプと、それに設定するプロパティを識別し、永続化します。

ただし、リモート呼び出しとローカル呼び出しを区別する何らかの方法を見つける必要があります。そのため、ローカル ライブラリ呼び出しを行っていて、リモート呼び出しを保持している場合に誤って保持しないようにする必要があります。

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

于 2011-06-09T22:37:16.840 に答える