PHPCR-ODM を既存の Symfony プロジェクトに統合しようとしていますが、(おそらく) マップされた Document クラスを検出するのに問題があります。具体的には、クラス MyDocument の Document を永続化しようとすると、次のようなエラーが発生します。
[Doctrine\Common\Persistence\Mapping\MappingException]
The class 'Example\Common\ORM\Document\MyDocument' was not found in the chain configured namespaces Doctrine\ODM\PHPCR\Document
このプロジェクトはDoctrine ORMも使用しているため、私のクラスは奇妙な名前空間にある可能性があります.
ドキュメントに従って、app/autoload.php に追加しました。
AnnotationRegistry::registerFile(__DIR__.'/../vendor/doctrine/phpcr-odm/lib/Doctrine/ODM/PHPCR/Mapping/Annotations/DoctrineAnnotations.php');
私の app/config/config.yml には以下が含まれています (parameters.yml でパラメーターが設定されています):
doctrine_phpcr:
session:
backend:
type: jackrabbit
url: %jackrabbit_url%
workspace: %jackrabbit_workspace%
username: %jackrabbit_user%
password: %jackrabbit_password%
odm:
auto_mapping: true
私のドキュメント クラスは src/Example/Common/ORM/Document/MyDocument.php にあり、次のようになります。
<?php
namespace Example\Common\ORM\Document;
use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCRODM;
/**
* @PHPCRODM\Document
*/
class MyDocument
{
/**
* @PHPCRODM\Id
*/
private $id;
/**
* @PHPCRODM\ParentDocument
*/
private $parent;
/**
* @PHPCRODM\Nodename
*/
private $name;
// .. etc
最後に、統合をテストするために使用しているコードは、単純なコンソール コマンド内にあり、次のようになります。
use Example\Common\ORM\Document\MyDocument;
// ...
$documentManager = $this->container->get('doctrine_phpcr.odm.default_document_manager');
$document = new MyDocument();
$document->setParent($documentManager->find(null, '/'));
$document->setName('ExampleName');
$documentManager->persist($document);
$documentManager->flush();
MyDocument クラスが正しくロードされていることを確認しましたが、マップされた Document クラスであることを DocumentManager に認識させるような方法で注釈が処理されていないようです。
私の推測では、簡単な設定手順を見落としていると思いますが、PHPCR、PHPCR-ODM、さらには Symfony CMF のドキュメントを繰り返し徹底的に調べても、何も見つからないようです。そこにある例のほとんどは、Symfony CMF を介して PHPCR を使用することを含んでおり、PHPCR-ODM が通常の Symfony プロジェクトに統合されている実際の例を多く (すべて?) 見つけることができませんでした。
編集:最終的な解決策
@WouterJ が以下に示したアドバイスに従い、問題を解決しました。さらに、Symfony バンドルにコンパイラ パスを追加して、これを非標準の名前空間 (つまり、 以外のものYourBundle\Document
) で機能させるという彼の提案に従いました。私の場合、これはバンドルではなく別の場所で再利用されるライブラリに入るので、適切でした。
src/Example/Bundle/ExampleBundle/ExampleBundle.php
これを行うには、次のようにファイルにメソッドを追加しました。
<?php
namespace Example\Bundle\ExampleBundle;
use Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class ExampleBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$mappedDirectories = array(
realpath(__DIR__ . '/../../Common/ODM/Document')
);
$mappedNamespaces = array(
'Example\Common\ODM\Document'
);
$phpcrCompilerClass = 'Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass';
if (class_exists($phpcrCompilerClass)) {
$container->addCompilerPass(
DoctrinePhpcrMappingsPass::createAnnotationMappingDriver(
$mappedNamespaces,
$mappedDirectories
));
}
}
}
このコードは、マッピングされたドキュメント クラスを Example\Common\ODM\Document 名前空間に配置できるようにし、それらを取得します。この例では注釈を使用していますが、同じパターンを XML または YAML マッピングに使用できます (Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass
メソッド シグネチャについてはクラスを参照してください)。
doctrine_phpcr.odm.metadata.annotation_reader
これを機能させるには、サービスを定義する必要があることもわかりましたapp/config.yml
。
services:
doctrine_phpcr.odm.metadata.annotation_reader:
class: Doctrine\Common\Annotations\AnnotationReader
それを行うためのより良い方法があるかもしれませんが、それは私にとってそれを機能させるのに十分でした.