2011-09-16 5 views
4

最近、私の仕事の多くは、ajaxのアクションを拡張してバグを修正することに関連しています。しかし、アクションリストはかなりサイズが管理できません。元の著者ではなく、コメントが疎なので、コードパスをたどり、どのjqueryイベントがアクションをトリガしたのか、そして送信したのかを判断するのに多くの時間を費やします要求との適切なデータ。サーバー側のajaxスクリプトを構成する方法

今のところ、ajaxリクエストスクリプトは基本的に、約100個のif-elseブロックが、その機能に基づいて異なるファイルに分割されています。

ajaxリクエストのphp部分を整理するのに役立つ関連デザインパターンやPHPイディオムはありますか?

私は多分ディスパッチインターフェイスのいくつかの並べ替えを考えていた。 (それが良いか実用的なアイデアであるかどうかはわかりません)どこに行動を登録し、何が必要なデータかを何らかの形で示すことができます。ディスパッチャは、適切な場所から関数を呼び出します。それから、私はすべてのAjaxリクエストを単一のスクリプトでルーティングし、自分の機能を整理することができます。また、行ごとにその実装を読まなくても、特定のアクションを呼び出すために必要なデータの概要を知ることができます。私は潜在的にクライアント側から私のサーバー側クラスの階層にアクセスすることができます。

このサウンドは有効ですか?これは安全ですか?他にも効果がある方法はありますか?これのインスピレーションは、基本的にはスモールトークスタイルのメッセージの受け渡しでした。私の大きな心配は、クロスサイトリクエスト偽造脆弱性を導入しようとしているか、コードにすでに存在する脆弱性が存在することです。読みにくいため、私はそれを逃しました。

+0

+1、良い質問 – Rijk

+0

動作可能だが堅く、保証はなく、あなたの仕事は報われる。サービスが明るい観測可能な未来を持っていない限り、おそらくそれを行うべきではありません。 //これらのアイデアを念頭に置いて、次のサービスを作成するとき) – c69

答えて

2

RPCスタイルのメカニズムを使用して、自分が望むものを実現します。 免責事項:私はこのスキームをJS + PHPとJS + Pythonで正常に実装していますので、が有効ですです。しかし、安全ではないかもしれません。あなたはそれが安全な

アイデアは受信方法、RPC要求を処理し、単一のPHPスクリプトを持つことである(コード/ SQLインジェクションやXSS攻撃に対して特にWRT)であることを確認するために、すべての適切な検証手順を実行する必要がありGETとPOSTの両方で名前とその引数を取得し、JSONをJavascript側に出力します。クライアント側で例えば

、:

API.rpc('getItemById', 1532, function(item) { console.log(item); }); 

オブジェクト書きます(ID = 1532、名前= "foo" を、どんな= "バー")

コンソール上の

私が使用する通信プロトコルは以下の通りです:

  1. クライアントがGETまたはPOSTのいずれか を使用して、RPCハンドラスクリプトにHTTPリクエストを送信します。制限は、 'method'はGETに常に を指定する必要があり、すべての引数はURLエンコード である必要があります。それ以外の場合は、すべての引数がkey = valueのペアとして指定され、要求(GET)またはペイロード(POST)の一部になることがあります。
  2. サーバーは常にHTTP 200で応答します(そうでないと非常に厄介なことが起こります)。これはJSONデータだけで応答します。返されるオブジェクトには、少なくとも2つのメンバーがあります。
    • 「成功」のメンバーが常にある、と呼び出しが成功したかどうかを示す - 例外が
    • 成功した場合にスローされなかったこと、つまり、「RET」のメンバーが、例外があれば機能
    • の戻り値が含まれています「メッセージ」メンバは、例外メッセージ(私はここでは全体のバックトレースを送信することを好むが、それは確かに敏感な環境のために良いではありません)のjavascript側で

(1)(、jQueryのを想定しが含まれ、スローされました私が思うようにコーディングしているので、これはバグかもしれないY):あなたは、同期呼び出しを実行するためにこのようなsyncRPC()のようなショートカット機能を追加することができ

API = function() { 
    this.rpc = function(method, args, callback) { 
    return $.ajax({ 
     url: 'rpcscript.php?method='+encodeURIComponent(args.method), 
     data: args, 
     type: 'post', //only the method name is sent as a GET arg 
     dataType: 'json' 
     error: function() { 
     alert('HTTP error !'); // This is e.g. an HTTP 500, or 404 
     }, 
     success: function(data) { 
     if (data.success) { 
      callback(data.ret); 
     } else { 
      alert('Server-side error:\n'+data.message); 
     } 
     }, 
    }); 
    } 
} 

など

(2)PHP側(わずかに変更走行コード)について:

class MyAPI 
{ 
    function getItemById($id) 
    { 
      // Assuming the $db is a database connection returning e.g. an associative array with the result of the SQL query. Note the (int) typecast to secure the query - all defensive measures should be used as usual. 
     return $db->query("SELECT * FROM item WHERE id = ".(int)$id.";"); 
    } 
} 

class RemoteProcedureCall 
{ 
    function __construct() 
    { 
     $this->api = new MyAPI(); 
    } 

    function serve() 
    { 
     header("Content-Type: application/json; charset=utf-8"); 

     try 
     { 
      if (!isset($_GET['method'])) 
       throw new Exception("Invalid parameters"); 

      $methodDesc = array($this->api, $_GET['method']); 

      if (!method_exists($methodDesc[0], $methodDesc[1]) || !is_callable($methodDesc)) 
       throw new Exception("Invalid parameters"); 

      $method = new ReflectionMethod($methodDesc[0], $methodDesc[1]); 
      $params = array(); 
      foreach ($method->getParameters() as $param) 
      { 
       // The arguments of the method must be passed as $_POST, or $_GET 
       if (isset($_POST[$param->getName()])) 
        // OK, arg is in $_POST 
        $paramSrc = $_POST[$param->getName()]; 

       elseif (!in_array($param->getName(),array('action','method')) 
        && isset($_GET[$param->getName()]) 
        && !isset($paramSrc[$param->getName()])) 
        // 'action' and 'method' are reserved $_GET arguments. Arguments for the RPC method 
        // can be any other args in the query string, unless they are already in $_POST. 
        $paramSrc = $_GET[$param->getName()]; 

       if (!isset($paramSrc)) 
       { 
        // If the argument has a default value (as specified per the PHP declaration 
        // of the method), we allow the caller to use it - that is, not sending the 
        // corresponding parameter. 
        if ($param->isDefaultValueAvailable()) 
         $p = $param->getDefaultValue(); 
        else 
         throw new Exception("Invalid parameters"); 
       } 
       else 
       { 
        $p = $paramSrc; 
       } 

       $params[$param->getName()] = $p; 
       unset($paramSrc); 
      } 

      $ret = $method->invokeArgs($db, $params); 

      echo json_encode(array('success' => true, 'ret' => $ret)); 
     } 
     catch (Exception $e) 
     { 
      echo json_encode(array('success' => false, 'message' => $e->getMessage()."\n".$e->getBacktrace())); 
     } 
    } 
}; 

$rpc = RemoteProcedureCall(); 
$rpc->serve(); 

など、予約キーワードをスローされる例外の種類を含め、ここで多くのアプリケーション固有の仮定は、私はこれは良いスタートを提供願っています。とにかく

あります...あなたの問題のポイント。

+0

少なくとも出発点のように見えます。これを自分の状況に適応できるかどうかがわかります。 –

+0

私はこれに非常に似た何かをやりました。私はサブクラス化によってAPIを公開することにしました。それは、私が大量の定型文を書くことなく柔軟性を持たせることができ、既存のスクリプトを簡単に移植できることが重要でした。例外を投げるのではなく、私は既存のメカニズム(間違いなく悪化している)を使ってエラーを投げました。とにかく、アイデアをありがとう。 –

0

あなたはこちらをご覧持つことができます説明からhttp://www.phpapi.org/

を:

「これは、あなたが最も高度利用CRM/ERP /に単純なWeb電卓からウェブシステムを開発することができ、その上にスケルトンで、 CMS/ETC。PHP-APIが提供するものは、コードの一般的な構造、非常に単純な拡張可能なAPIコード構造、APIとのJavaScript接続(新しいモジュール/メソッドハンドラを追加する簡単な方法)

+0

ええと...私は既存のコードベースを持っており、フレームワークに移植することを本当に望んでいません。そのapiを使用すると、html5boilerplateを利用するためにテンプレートと表示コードのすべてを再加工する必要があるようです。私は、現在のプロジェクトがすでに展開され、比較的機能が完結しているので、この現在のプロジェクトでは時間も希望もしていません。私の質問は、既存のコードベースの適切なリファクタリングに行きます。 –

関連する問題