38

我正在尝试使用 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.

我通过作曲家为项目安装了以下库

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

因为我没有使用整个 Doctrine 2 解决方案,所以有什么明显的遗漏吗?

编辑:我的最终解决方案是创建一个包含以下内容的引导文件:

<?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'
);
?>
4

6 回答 6

73

可以肯定的是,这会启用静默自动加载,这比自己注册命名空间要方便得多。

AnnotationRegistry::registerLoader('class_exists');
于 2014-02-04T09:39:09.020 回答
40

我遇到了同样的问题,并通过谷歌找到了你的问题。不幸的是,您还没有收到任何答案,所以我不得不自己挖掘。:P

问题是,JMSSerializer Annotations 使用的 Doctrine Annotations不使用普通的 PHP 自动加载

这些注解是如何加载的?通过查看代码,您可以猜到 ORM 映射、断言验证和完全限定的注释可以使用定义的 PHP 自动加载器加载。然而情况并非如此:出于错误处理的原因,AnnotationReader 中的每次检查类是否存在都会将 class_exists($name, $autoload) 的第二个参数 $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

我希望这能让你更进一步。:)

于 2013-02-01T12:37:23.563 回答
4

@SirArturio 对这个自动加载难题有正确的答案,我只是想更清楚地回应@messified 或其他任何努力让它工作的人。正如他雄辩地解释的那样,composer 或 SPL 中的自动 PSR-0 处理程序不会为了加载这些注释而削减它,因为它们使用 Doctrine 的自动加载。

所以这里是一个完整的小例子。每当您创建 JMS Serializer 对象以开始序列化时,都是将注解命名空间添加到教义自动加载器的好时机。为了清楚起见,我假设没有 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;
}

那应该削减它,使用教义而不是作曲家自动加载正确的注释文件。

于 2013-11-15T15:53:17.173 回答
3

检查注释的大小写。从 Windows 开发环境部署到 Ubuntu 服务器时,我遇到了类似的问题,这是由我的注释中的拼写错误引起的。Windows 文件不区分大小写,因此它可以在那里工作,但在 Linux 上失败。

于 2013-06-26T14:14:56.187 回答
0

如果你使用 Composer,你可以通过在 require 中指定路径来获取 loader:

$loader = require(__DIR__ . '/../vendor/autoload.php');
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
于 2019-02-08T13:22:41.557 回答
-3

这是解决方案

1. 进入 php 目录,然后安装 composer php composer-setup.php 2. 进入项目 sdk 目录,例如

cd /Applications/XAMPP/xamppfiles/htdocs/streetreturn/adn_sdk-php-master

更新作曲家以安装依赖项 php /Users/zakir/composer.phar 更新

*注意:/Users/zakir/composer.phar 将在第 1 步安装 composer 时定位

于 2017-03-02T18:05:30.633 回答