0

Flex クライアントと PHP サーバー間のリモート ゲートウェイとして zendamf を使用しています。サーバー側の型をクライアント側の型にマッピングしても、サービス メソッドのパラメーターとして渡されるオブジェクトには影響がないようです。カスタム型を持つすべてのオブジェクトは stdClass インスタンスとして受け取られます。これを強制する方法はありますか?それとも、ここで何かが欠けていますか?

何かご意見は?

どうも!

4

1 に答える 1

2

この質問は少し古いですが、まだ答えられていません。だから私に試してみましょう。;)

最初の@www.Flextras.com:その通りです。PHPでは、クラスマッピングの処理も行う必要があります。

したがって、Zend Frameworkを使用してクラスマッピングを定義する方法に関心のあるすべての人は、次の短いが(私の意見では)詳細な紹介を見てください。それをすべて知っている場合は、紹介をスキップして、「ZendFrameworkのクライアントからサーバーへのマッピングとstdClassについて」に進んでください。

ZendFrameworkを使用したPHPでのクラスマッピングの方法

Zend FrameworkのZend_Amf_Serverのドキュメントに記載されているように、クラスマッピングを提供するための3つのオプションがあります。完全なドキュメントはここ(ページの中央の「型付きオブジェクト」の下のどこかにあります)にあります。

最初のオプション

// Use the setClassMap() method of Zend_Amf_Server
require_once '<PathToZendFramework>/Zend/Amf/Server.php';
$server = new Zend_Amf_Server();

$server->setClassMap('MyActionScriptClassName', 'MyPHPClassName');

// the typical package notation for ActionScript class names is also allowed here
$server->setClassMap('com.company.MyActionScriptClassName', 'MyPHPClassName');

これは、クライアントからサーバーおよびサーバーからクライアントの両方向に対してクラスマッピングを明示的に指定できるため、最も柔軟なオプションです。柔軟性とは対照的に、ここではより多くの間違いを犯す可能性があります。クラスマッピングを使用する際の考慮事項の下にチェックリストがあります。

2番目のオプション

// Define a special named public property on each class used for
// serialization/deserialization via AMF
public class MyPHPClassName
{
    public $_explicitType = 'MyActionScriptClassName';

    /* your class definition here */
}

このようにすると、Zend_Amf_Serverが$_explicitTypeプロパティを自動的に検索するため、クラスマッピングが少し動的になります。したがって、最初のオプションのようにクラスマッピングを明示的に定義する必要はありません。残念ながら、を使用する$_explicitTypeと、マッピングのPHPクラス名を定義できません(これは「もう少し動的」です)。さらに下に、ここで発生する問題についての詳細な説明があります。

3番目のオプション

// Define a special named public method on each class used for
// serialization/deserialization via AMF
public class MyPHPClassName
{
    public function getASClassName()
    {
        return 'MyActionScriptClassName';
    }

    /* your class definition here */
}

この最後のオプションを使用することにより、クラスマッピングから最もダイナミクスを引き出すことができます。私の例のように文字列リテラルを返すこともできますが、これは$_explicitTypeオプションを使用する場合と同じです。メソッドアプローチの利点は、クラスがActionScriptクラス名を動的に生成できるようにすることです。getASClassName()したがって、すべてのAMFクラスが継承する階層の最上位クラスで定義できます。ここでの欠点は、2番目のオプションの場合と同じです。クラスがマップされるPHPクラス名を定義することはできません。

FlexおよびZendFrameworkのクラスマッピングチェックリスト

クラスマッピングの指定で何か間違ったことをした場合、Flexは厳密に型指定されたオブジェクトに変換できません。代わりに、ジェネリックObjectクラスのインスタンスを取得します。これが発生した場合は、次の1つ以上のことが当てはまるかどうかを確認する必要があります。

フレックス側

  • クラスには[RemoteClass]メタデータタグが必要です。
  • エイリアス()を使用してリモートクラスを指定した場合[RemoteClass(alias="")]は、入力ミスがないかどうかを確認してください。
  • あなたのクラス(それが継承するすべてのクラスを含む)は、サーバー側で定義されたすべてのパブリックプロパティを同等に定義していますか?(public var ...またはゲッター/セッターペアのいずれか)
  • パブリックプロパティを読み取り/書き込みとして定義しましたか?
  • [Transient]メタデータタグを使用して、転送に使用しないプロパティをマークしましたか?(これにより、そのようにマークされたプロパティがシリアル化/逆シリアル化されなくなります)

ZendFramework側

  • クラスマッピングに3つのオプションのいずれかを使用しましたか?
  • 最初のオプションを使用した場合、ActionScriptまたはPHPクラス名のいずれかを誤って入力しましたか?[RemoteClass](ActionScriptクラス名は、Flexアプリケーションのタグで定義されているものとまったく同じである必要があります)

ZendFrameworkのクライアントからサーバーへのマッピングとstdClassについて

また、サーバー側のサービスクラスメソッドに渡される強く型付けされた引数が結果として生じるという問題に遭遇しましたstdClass。私はよくこれが起こる理由を見つけようとしましたが、本当に理由を見つけるのに時間をかけたことはありませんでした。昨日、私のプロジェクトの1つでクラスマッピングを可能な限り動的/一般的にするための追加の試みの後、数時間の調査の後、AMF要求を受け取ったときにZend_Amf_Serverが何をするかを見つけました。(ところで、PHPコードに厳密なクラス命名規則を実装していなかった場合、その理由を見つけることはできませんでした)。

AMF要求が着信し、Zend_Amf_Serverがそれの解析を開始すると、要求からリモートクラスエイリアスを読み取り、そのクラスを自動的にロードしようとします。それがZend_Amf_Serverに実行してほしいことですよね!?ただし、AMFサーバーは、のようなクラス名を処理するための自動化のみをサポートするMyClassNameか、フレームワークの命名規則に準拠しMy_Class_Nameます。のようなリモートクラスエイリアスを持つクラスを自動的にマップすることはできませんcom.company.SomeAmfClass。Zendは、パッケージ(通常のディレクトリパスを表すもの)を指定し、クラスをロードする前にすべてのピリオドをアンダースコアに変換することを想定しています。このようなことを行うクラスはですZend_Amf_Parse_TypeLoader。AMFサーバーは静的メソッドを呼び出しますloadType()

そのメソッドの実装は次のとおりです(Zend Framework 1.11.7から直接コピーされます)。

/**
  * Load the mapped class type into a callback.
  *
  * @param  string $className
  * @return object|false
  */
 public static function loadType($className)
 {
     $class    = self::getMappedClassName($className);
     if(!$class) {
         $class = str_replace('.', '_', $className);
     }
     if (!class_exists($class)) {
         return "stdClass";
     }
     return $class;
 }

最初に、それを実装してシングルトンのオートローダースタックZend_Loader_Autoloader_Interfaceにプッシュするクラスを定義しようとしました。Zend_Loader_Autoloaderただし、ここでの問題は、自動ロードが実行される前にクラス名を変更することでした。が呼び出されるとZend_Amf_Parse_TypeLoader::loadType()どうなりますか。class_exists()

com.company.SomeAmfClassしたがって、フレームワークでそのメソッドを直接変更して、追加の方法のようにActionScriptクラス名を処理することができます。しかし、フレームワークコードを変更するのは悪い習慣なので、これが最後のオプションになるはずです。

もう1つの解決策(そしてほぼ最もクリーンな方法)は、Zend Frameworkの命名規則に合うようにすべてのクラスを再編成して名前を変更することですが、残念ながら、これには数時間のリファクタリング(PHPでの処理は実際には簡単ではありません)と数日にわたるテストとコードベース全体をデバッグします。

バランスをとるために、必要なフレームワーククラスにモンキーパッチを適用できます。したがって、フレームワーク自体を変更することはありませんが、コードベースをリファクタリングすることはありません。トリックを行ういくつかのフレームワークがあります。私はこの質問の答えにいくつかの例を見つけました

さらに、この質問をここで見つけました: フレックスからPHPに戻るAMF型付きオブジェクト それがニーズに合っているかどうかを確認する必要があります。

これが誰かに役立つことを願っています。何かを忘れた場合は教えてください(たとえば、チェックリストで!)

于 2012-08-29T12:21:04.130 に答える