web-dev-qa-db-ja.com

JMSSerializerスタンドアロン-注釈が存在しないか、自動ロードできません

JMSSerializerをスタンドアロンライブラリとして使用して、APIからのJSON応答をモデルクラスにマップしようとしていますが、いくつかの問題が発生しています。

次のコードを実行すると、例外が発生します。

<?php
require dirname(__DIR__) . '/vendor/autoload.php';

use JMS\Serializer\Annotation AS JMS;

class Trii {
    /**
     * User ID for this session
     * @JMS\SerializedName("userID")
     * @JMS\Annotation(getter="getUserId")
     * @JMS\Type("string")
     * @var string
     */
    private $userId;

    public function getUserId() {
        return $this->userId;
    }

    public function setUserId($userId) {
        $this->userId = $userId;
    }
}

$serializer = \JMS\Serializer\SerializerBuilder::create()->setDebug(true)->build();
$object = $serializer->deserialize('{"userID":"Trii"}', 'Trii', 'json');
var_dump($object);
?>

ここが例外です

Doctrine\Common\Annotations\AnnotationException: [Semantical Error] The annotation "@JMS\Serializer\Annotation\SerializedName" in property Trii::$userId does not exist, or could not be auto-loaded.

Composerを介してプロジェクト用に次のライブラリがインストールされています

{
    "require": {
        "jms/serializer": "1.0.*@dev"
    }
}

Doctrine 2ソリューション全体を使用していないので、私が見逃している明らかなものはありますか?

編集:私の最終的な解決策は、bootstrapファイルを次の内容で作成することでした:

<?php
// standard composer install vendor autoload magic
require dirname(__DIR__) . '/vendor/autoload.php';

// Bootstrap the JMS custom annotations for Object to Json mapping
\Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace(
    'JMS\Serializer\Annotation',
    dirname(__DIR__).'/vendor/jms/serializer/src'
);
?>
37
Josh J

これにより、名前空間を自分で登録するよりもはるかに便利なサイレント自動ロードが有効になります。

AnnotationRegistry::registerLoader('class_exists');
71
Flip

私は同じ問題に遭遇し、Googleを通じてあなたの質問を見つけました。残念ながら、まだ回答を受け取っていなかったので、私は自分で掘る必要がありました。 :P

問題は、Doctrineアノテーション、JMSSerializerアノテーションが使用する 通常は使用しないPHP autoloading です。

これらの注釈はどのように読み込まれますか?コードを見ると、定義されたPHPオートローダーを使用して、ORMマッピング、検証のアサート、および完全修飾アノテーションを単にロードできることが推測できます。ただし、これは当てはまりません:エラー処理のためAnnotationReader内のクラスの存在をチェックするたびに、class_exists($ name、$ autoload)の2番目のパラメーター$ autoloadがfalseに設定されます。AnnotationReaderを完全に機能させるには、多くのオートローダーにはないサイレントオートローダーが必要です。サイレントオートロードはPSR-0の一部ではありませんオートローディングの仕様。

つまり、アノテーションファイルを自分で登録する必要があります。

AnnotationRegistry::registerFile(
   <PROJECT ROOT> . 
   "/vendor/jms/serializer/src/JMS/Serializer/Annotation/SerializedName.php");

...または名前空間全体(推奨される方法):

AnnotationRegistry::registerAutoloadNamespace(
    'JMS\Serializer\Annotation', 
    <PROJECT ROOT> . "/vendor/jms/serializer/src");

registerAutoloadNamespaceのパスには注意してください。最初に、registerFileを使用して、アノテーションへのパス全体を同じ方法で登録しようとしました:

<PROJECT ROOT> . "/vendor/jms/serializer/src/JMS/Serializer/Annotation 

しかし、それは惨めに失敗しました。 :D

これであなたがさらに一歩前進することを願っています。 :)

40
SirArturio

@SirArturioはこのオートローディングパズルに対する正しい答えを持っています。@ messifiedまたは他の誰かがこれを機能させるために苦労していることに応えて、もう少し明確にしたかっただけです。彼が雄弁に説明したように、composerまたはSPLの自動PSR-0ハンドラーは、Doctrineのオートローディングを使用しているため、これらのアノテーションをロードするためにそれをカットしません。

だからここに小さな完全な例があります。 JMS Serializerオブジェクトを作成してシリアル化を開始するときはいつでも、Doctrineのオートローダーにアノテーション名前空間を追加する良い機会です。明確にするために、IoCはなく、完全修飾された名前空間(ヒントヒント、依存関係注入を使用)を想定しています。

<?php
Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace(
'JMS\Serializer\Annotation', 
$your_app_basepath . "/vendor/jms/serializer/src");


$serializer = JMS\Serializer\SerializerBuilder::create()->build();
$json_output = $serializer->serialize('MyProject\MyClass', 'json');

次に、MyProject\MyClassで:

<?php
use JMS\Serializer\Annotation as JMS;

class MyClass{

    /** @JMS\Exclude */
    private $something_secret;
}

そしてそれはそれをカットし、作曲家の代わりにdoctrineを使用して適切な注釈ファイルをオートロードします。

4
jpschroeder

注釈の大文字の使用を確認してください。私の注釈の場合のタイプミスが原因で、Windows開発環境からUbuntuサーバーにデプロイするときに同様の問題が発生しました。 Windowsファイルは大文字と小文字を区別しないため、そこでは機能しますがLinuxでは失敗します。

3
Tamlyn

Composerを使用する場合は、requireでパスを指定してローダーを取得できます。

$loader = require(__DIR__ . '/../vendor/autoload.php');
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
0
Lebnik