С Рождеством всех.
Я пытаюсь использовать доктрину couchdb-ODM с проектом php Silex. Я уже получил это, работая с доктринами, но с диваном, он продолжает ломаться.
Я искал в Интернете несколько дней, но ничего. Я буду конкретен, я получаю эту забавную ошибку
Class Package\documents\User is not a valid document or mapped super class.
При отладке я заметил этот вызов в строке 55 Doctrine / ODM / CouchDB / Mapping / Driver / AnnotationDriver.php
$classAnnotations = $this->reader->getClassAnnotations($reflClass);
Возвращает пустой массив. Думаю, что-то не так с моей конфигурацией, но, похоже, не могу это указать.
Любая помощь будет оценена.
Обновить
Настроить CouchDB ODM. Я создал 2 поставщиков услуг. 1 для CouchDB и другой для CouchDB ODM, смоделированный по умолчанию DoctrineServiceProvider
в Silex
<?php
namespace Package\services\Doctrine\CouchDB;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Doctrine\CouchDB\CouchDBClient;
use Doctrine\DBAL\Configuration;
use Doctrine\Common\EventManager;
use Doctrine\CouchDB\HTTP\SocketClient;
use Symfony\Bridge\Doctrine\Logger\DbalLogger;
class DoctrineCouchDbServiceProvider implements ServiceProviderInterface {
/**
* Registers services on the given app.
*
* This method should only be used to configure services and parameters.
* It should not get services.
*
* @param Application $container An Application instance
*/
public function register(Container $container) {
$container['couchdb.default_options'] = [
'type' => 'socket',
'host' => 'localhost',
'port' => 5984,
'user' => null,
'password' => null,
'ip' => null,
'logging' => true
];
$container['couchdbs.options.initializer'] = $container->protect(function () use ($container) {
static $initialized = false;
if ($initialized) {
return;
}
$initialized = true;
if (!isset($container['couchdbs.options'])) {
$container['couchdbs.options'] = [
'default' => isset($container['couchdb.options']) ? $container['couchdb.options'] : []
];
}
$tmp = $container['couchdbs.options'];
foreach ($tmp as $name => &$options) {
$options = array_replace_recursive($container['couchdb.default_options'], $options);
if (!isset($container['couchdbs.default'])) {
$container['couchdbs.default'] = $name;
}
}
$container['couchdbs.options'] = $tmp;
});
$container['couchdbs'] = function($container) {
$container['couchdbs.options.initializer']();
$couchdbs = new Container();
foreach ($container['couchdbs.options'] as $name => $options) {
if ($container['couchdbs.default'] === $name) {
// we use shortcuts here in case the default has been overridden
$config = $container['couchdb.config'];
$manager = $container['couchdb.event_manager'];
} else {
$config = $container['couchdbs.config'][$name];
$manager = $container['couchdbs.event_manager'][$name];
}
$couchdbs[$name] = function () use ($options, $config, $manager) {
return CouchDBClient::create($options);
};
}
return $couchdbs;
};
$container['couchdbs.config'] = function ($container) {
$container['couchdbs.options.initializer']();
$configs = new Container();
$addLogger = isset($container['logger']) && null !== $container['logger'] && class_exists('Symfony\Bridge\Doctrine\Logger\DbalLogger');
foreach ($container['couchdbs.options'] as $name => $options) {
$configs[$name] = new Configuration();
if ($addLogger) {
$configs[$name]->setSQLLogger(new DbalLogger($container['logger'], isset($container['stopwatch']) ? $container['stopwatch'] : null));
}
}
return $configs;
};
$container['couchdbs.event_manager'] = function ($container) {
$container['couchdbs.options.initializer']();
$managers = new Container();
foreach ($container['couchdbs.options'] as $name => $options) {
$managers[$name] = new EventManager();
}
return $managers;
};
// shortcuts for the "first" DB
$container['couchdb'] = function ($container) {
$couchdbs = $container['couchdbs'];
return $couchdbs[$container['couchdbs.default']];
};
$container['couchdb.config'] = function ($container) {
$couchdbs = $container['couchdbs.config'];
return $couchdbs[$container['couchdbs.default']];
};
$container['couchdb.event_manager'] = function ($container) {
$couchdbs = $container['couchdbs.event_manager'];
return $couchdbs[$container['couchdbs.default']];
};
}
}
<?php
namespace Package\services\Doctrine\CouchDB;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Doctrine\Common\Cache\ApcCache;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\Cache\CacheProvider;
use Doctrine\Common\Cache\CouchbaseCache;
use Doctrine\Common\Cache\FilesystemCache;
use Doctrine\Common\Cache\MemcacheCache;
use Doctrine\Common\Cache\MemcachedCache;
use Doctrine\Common\Cache\RedisCache;
use Doctrine\Common\Cache\XcacheCache;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
use Doctrine\CouchDB\CouchDBClient;
use Doctrine\ODM\CouchDB\Configuration;
use Doctrine\ODM\CouchDB\DocumentManager;
use Doctrine\ODM\CouchDB\Mapping\Driver\DriverChain;
use Doctrine\ODM\CouchDB\Mapping\Driver\AnnotationDriver;
use Doctrine\ODM\CouchDB\Mapping\Driver\PHPDriver;
use Doctrine\ODM\CouchDB\Mapping\Driver\XmlDriver;
use Doctrine\ODM\CouchDB\Mapping\Driver\YamlDriver;
use Doctrine\ODM\CouchDB\Types\Type;
class DoctrineCouchDbOdmServiceProvider implements ServiceProviderInterface {
/**
* Registers services on the given app.
*
* This method should only be used to configure services and parameters.
* It should not get services.
*
* @param Application $container An Application instance
*/
public function register(Container $container) {
foreach ($this->getCouchDbOdmDefaults($container) as $key => $value) {
if (!isset($container[$key])) {
$container[$key] = $value;
}
}
$container['couchdb.dm.default_options'] = [
'connection' => 'default',
'mappings' => [],
'types' => [],
];
$container['couchdb.dms.options.initializer'] = $container->protect(function () use ($container) {
static $initialized = false;
if ($initialized) {
return;
}
$initialized = true;
if (!isset($container['couchdb.dms.options'])) {
$container['couchdb.dms.options'] = [
'default' => isset($container['couchdb.dm.options']) ? $container['couchdb.dm.options'] : []
];
}
$tmp = $container['couchdb.dms.options'];
foreach ($tmp as $name => &$options) {
$options = array_replace($container['couchdb.dm.default_options'], $options);
if (!isset($container['couchdb.dms.default'])) {
$container['couchdb.dms.default'] = $name;
}
}
$container['couchdb.dms.options'] = $tmp;
});
$container['couchdb.dm_name_from_param_key'] = $container->protect(function ($paramKey) use ($container) {
$container['couchdb.dms.options.initializer']();
if (isset($container[$paramKey])) {
return $container[$paramKey];
}
return $container['couchdb.dms.default'];
});
$container['couchdb.dms'] = function($container) {
$container['couchdb.dms.options.initializer']();
$dms = new Container();
foreach ($container['couchdb.dms.options'] as $name => $options) {
if ($container['couchdb.dms.default'] === $name) {
// we use shortcuts here in case the default has been overridden
$config = $container['couchdb.dm.config'];
} else {
$config = $container['couchdb.dms.config'][$name];
}
if (isset($options['dbname'])) {
$config->setDefaultDB($options['dbname']);
}
// print_r($options);
$dms[$name] = function ($dms) use ($container, $options, $config) {
$httpClient = new \Doctrine\CouchDB\HTTP\SocketClient();
$dm = DocumentManager::create(
CouchDBClient::create($container['couchdb.options']),
$config,
$container['couchdbs.event_manager'][$options['connection']]
);
return $dm;
};
}
return $dms;
};
$container['couchdb.dms.config'] = function($container) {
$container['couchdb.dms.options.initializer']();
$configs = new Container();
foreach ($container['couchdb.dms.options'] as $name => $options) {
$config = new Configuration;
$container['couchdb.cache.configurer']($name, $config, $options);
$config->setProxyDir($container['couchdb.proxies_dir']);
$config->setProxyNamespace($container['couchdb.proxies_namespace']);
$config->setAutoGenerateProxyClasses($container['couchdb.auto_generate_proxies']);
$config->setValidateDoctrineMetadata($container['couchdb.validate_doctrine_metadata']);
$config->setAllOrNothingFlush($container['couchdb.all_or_nothing_flush']);
$config->setLuceneHandlerName('_fti');
$chain = $container['couchdb.mapping_driver_chain.locator']($name);
foreach ((array) $options['mappings'] as $document) {
if (!is_array($document)) {
throw new \InvalidArgumentException(
"The 'couchdb.dm.options' option 'mappings' should be an array of arrays.");
}
if (!empty($document['resources_namespace'])) {
$document['path'] = $container['psr0_resource_locator']->findFirstDirectory($document['resources_namespace']);
}
if (isset($document['alias'])) {
$config->addDocumentNamespace($document['alias'], $document['namespace']);
}
switch ($document['type']) {
case 'annotation':
$useSimpleAnnotationReader =
isset($document['use_simple_annotation_reader'])
? $document['use_simple_annotation_reader']
: true;
$driver = $config->newDefaultAnnotationDriver((array) $document['path'], $useSimpleAnnotationReader);
$chain->addDriver($driver, $document['namespace']);
break;
case 'annotation2':
$driver = new AnnotationDriver($document['path']);
$chain->addDriver($driver, $document['namespace']);
break;
case 'yml':
$driver = new YamlDriver($document['path']);
$chain->addDriver($driver, $document['namespace']);
break;
case 'xml':
$driver = new XmlDriver($document['path']);
$chain->addDriver($driver, $document['namespace']);
break;
case 'php':
$driver = new PHPDriver($document['path']);
$chain->addDriver($driver, $document['namespace']);
break;
default:
throw new \InvalidArgumentException(sprintf('"%s" is not a recognized driver', $document['type']));
break;
}
}
$config->setMetadataDriverImpl($chain);
foreach ((array) $options['types'] as $typeName => $typeClass) {
if (Type::hasType($typeName)) {
Type::overrideType($typeName, $typeClass);
} else {
Type::addType($typeName, $typeClass);
}
}
$configs[$name] = $config;
}
return $configs;
};
$container['couchdb.cache.configurer'] = $container->protect(function ($name, Configuration $config, $options) use ($container) {
$config->setMetadataCacheImpl($container['couchdb.cache.locator']($name, 'metadata', $options));
});
$container['couchdb.cache.locator'] = $container->protect(function ($name, $cacheName, $options) use ($container) {
$cacheNameKey = $cacheName . '_cache';
if (!isset($options[$cacheNameKey])) {
$options[$cacheNameKey] = $container['couchdb.default_cache'];
}
if (isset($options[$cacheNameKey]) && !is_array($options[$cacheNameKey])) {
$options[$cacheNameKey] = array(
'driver' => $options[$cacheNameKey],
);
}
if (!isset($options[$cacheNameKey]['driver'])) {
throw new \RuntimeException("No driver specified for '$cacheName'");
}
$driver = $options[$cacheNameKey]['driver'];
$cacheInstanceKey = 'couchdb.cache.instances.'.$name.'.'.$cacheName;
if (isset($container[$cacheInstanceKey])) {
return $container[$cacheInstanceKey];
}
$cache = $container['couchdb.cache.factory']($driver, $options[$cacheNameKey]);
if (isset($options['cache_namespace']) && $cache instanceof CacheProvider) {
$cache->setNamespace($options['cache_namespace']);
}
return $container[$cacheInstanceKey] = $cache;
});
$container['couchdb.cache.factory.backing_memcache'] = $container->protect(function () {
return new \Memcache;
});
$container['couchdb.cache.factory.memcache'] = $container->protect(function ($cacheOptions) use ($container) {
if (empty($cacheOptions['host']) || empty($cacheOptions['port'])) {
throw new \RuntimeException('Host and port options need to be specified for memcache cache');
}
$memcache = $container['couchdb.cache.factory.backing_memcache']();
$memcache->connect($cacheOptions['host'], $cacheOptions['port']);
$cache = new MemcacheCache;
$cache->setMemcache($memcache);
return $cache;
});
$container['couchdb.cache.factory.backing_memcached'] = $container->protect(function () {
return new \Memcached;
});
$container['couchdb.cache.factory.memcached'] = $container->protect(function ($cacheOptions) use ($container) {
if (empty($cacheOptions['host']) || empty($cacheOptions['port'])) {
throw new \RuntimeException('Host and port options need to be specified for memcached cache');
}
$memcached = $container['couchdb.cache.factory.backing_memcached']();
$memcached->addServer($cacheOptions['host'], $cacheOptions['port']);
$cache = new MemcachedCache;
$cache->setMemcached($memcached);
return $cache;
});
$container['couchdb.cache.factory.backing_memcached'] = $container->protect(function () {
return new \Memcached;
});
$container['couchdb.cache.factory.memcached'] = $container->protect(function ($cacheOptions) use ($container) {
if (empty($cacheOptions['host']) || empty($cacheOptions['port'])) {
throw new \RuntimeException('Host and port options need to be specified for memcached cache');
}
/** @var \Memcached $memcached */
$memcached = $container['couchdb.cache.factory.backing_memcached']();
$memcached->addServer($cacheOptions['host'], $cacheOptions['port']);
$cache = new MemcachedCache;
$cache->setMemcached($memcached);
return $cache;
});
$container['couchdb.cache.factory.backing_redis'] = $container->protect(function () {
return new \Redis;
});
$container['couchdb.cache.factory.redis'] = $container->protect(function ($cacheOptions) use ($container) {
if (empty($cacheOptions['host']) || empty($cacheOptions['port'])) {
throw new \RuntimeException('Host and port options need to be specified for redis cache');
}
/** @var \Redis $redis */
$redis = $container['couchdb.cache.factory.backing_redis']();
$redis->connect($cacheOptions['host'], $cacheOptions['port']);
if (isset($cacheOptions['password'])) {
$redis->auth($cacheOptions['password']);
}
$cache = new RedisCache;
$cache->setRedis($redis);
return $cache;
});
$container['couchdb.cache.factory.array'] = $container->protect(function () {
return new ArrayCache;
});
$container['couchdb.cache.factory.apc'] = $container->protect(function () {
return new ApcCache;
});
$container['couchdb.cache.factory.xcache'] = $container->protect(function () {
return new XcacheCache;
});
$container['couchdb.cache.factory.filesystem'] = $container->protect(function ($cacheOptions) {
if (empty($cacheOptions['path'])) {
throw new \RuntimeException('FilesystemCache path not defined');
}
$cacheOptions += array(
'extension' => FilesystemCache::EXTENSION,
'umask' => 0002,
);
return new FilesystemCache($cacheOptions['path'], $cacheOptions['extension'], $cacheOptions['umask']);
});
$container['couchdb.cache.factory.couchbase'] = $container->protect(function ($cacheOptions) {
$host='';
$bucketName='';
$user='';
$password='';
if (empty($cacheOptions['host'])) {
$host='127.0.0.1';
}
if (empty($cacheOptions['bucket'])) {
$bucketName='default';
}
if (!empty($cacheOptions['user'])) {
$user=$cacheOptions['user'];
}
if (!empty($cacheOptions['password'])) {
$password=$cacheOptions['password'];
}
$couchbase = new \Couchbase($host,$user,$password,$bucketName);
$cache = new CouchbaseCache();
$cache->setCouchbase($couchbase);
return $cache;
});
$container['couchdb.cache.factory'] = $container->protect(function ($driver, $cacheOptions) use ($container) {
switch ($driver) {
case 'array':
return $container['couchdb.cache.factory.array']();
case 'apc':
return $container['couchdb.cache.factory.apc']();
case 'xcache':
return $container['couchdb.cache.factory.xcache']();
case 'memcache':
return $container['couchdb.cache.factory.memcache']($cacheOptions);
case 'memcached':
return $container['couchdb.cache.factory.memcached']($cacheOptions);
case 'filesystem':
return $container['couchdb.cache.factory.filesystem']($cacheOptions);
case 'redis':
return $container['couchdb.cache.factory.redis']($cacheOptions);
case 'couchbase':
return $container['couchdb.cache.factory.couchbase']($cacheOptions);
default:
throw new \RuntimeException("Unsupported cache type '$driver' specified");
}
});
$container['couchdb.mapping_driver_chain.locator'] = $container->protect(function ($name = null) use ($container) {
$container['couchdb.dms.options.initializer']();
if (null === $name) {
$name = $container['couchdb.dms.default'];
}
$cacheInstanceKey = 'couchdb.mapping_driver_chain.instances.'.$name;
if (isset($container[$cacheInstanceKey])) {
return $container[$cacheInstanceKey];
}
return $container[$cacheInstanceKey] = $container['couchdb.mapping_driver_chain.factory']($name);
});
$container['couchdb.mapping_driver_chain.factory'] = $container->protect(function ($name) use ($container) {
return new DriverChain;
});
$container['couchdb.add_mapping_driver'] = $container->protect(function (MappingDriver $mappingDriver, $namespace, $name = null) use ($container) {
$container['couchdb.dms.options.initializer']();
if (null === $name) {
$name = $container['couchdb.dms.default'];
}
$driverChain = $container['couchdb.mapping_driver_chain.locator']($name);
$driverChain->addDriver($mappingDriver, $namespace);
});
$container['couchdb.generate_psr0_mapping'] = $container->protect(function ($resourceMapping) use ($container) {
$mapping = [];
foreach ($resourceMapping as $resourceNamespace => $documentNamespace) {
$directory = $container['psr0_resource_locator']->findFirstDirectory($resourceNamespace);
if (!$directory) {
throw new \InvalidArgumentException("Resources for mapping '$documentNamespace' could not be located; Looked for mapping resources at '$resourceNamespace'");
}
$mapping[$directory] = $documentNamespace;
}
return $mapping;
});
$container['couchdb.dm'] = function($container) {
$dms = $container['couchdb.dms'];
return $dms[$container['couchdb.dms.default']];
};
$container['couchdb.dm.config'] = function($container) {
$configs = $container['couchdb.dms.config'];
return $configs[$container['couchdb.dms.default']];
};
}
/**
* @param \Pimple $container
* @return array
*/
protected function getCouchDbOdmDefaults(Container $container) {
return array(
'couchdb.proxies_dir' => __DIR__.'/../../../../../var/cache/doctrine/proxies',
'couchdb.proxies_namespace' => 'CouchDBDoctrineProxy',
'couchdb.proxy_namespace' => 'MyCouchDBProxyNS',
'couchdb.auto_generate_proxies' => true,
'couchdb.auto_generate_proxy_classes' => true,
'couchdb.default_cache' => [
'driver' => 'array',
],
'couchdb.write_doctrine_metadata' => true,
'couchdb.validate_doctrine_metadata' => true,
'couchdb.uuid_generationbuffersize' => 20,
'couchdb.all_or_nothing_flush' => true,
'couchdb.lucene_handler_name' => '_fti',
'couchdb.metadata_resolver' => null,
'couchdb.class_metadata_factory_name' => '\Doctrine\ODM\CouchDB\Mapping\ClassMetadataFactory',
'couchdb.default_repository_class' => '\Doctrine\ODM\CouchDB\DocumentRepository',
);
}
}
Я тогда зарегистрировался как в app.php
$app->register(new DoctrineCouchDbServiceProvider());
$app->register(new DoctrineCouchDbOdmServiceProvider());
и добавил параметры дивана дБ и конфигурации в config/prod.php
$app['couchdb.options'] = [
'dbname' => 'app_db',
'type' => 'socket',
'host' => 'localhost',
'port' => 5984,
'user' => null,
'password' => null,
'ip' => null,
'logging' => true
];
$app['couchdb.dm.options'] = [
'mappings' => [
[
'type' => 'annotation',
'namespace' => 'Package\documents',
'path' => __DIR__.'/../src/package/documents'
],
]
];
<?php
namespace Package\documents;
use Doctrine\ODM\CouchDB\Mapping\Annotations as CouchDB;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\Common\Collections\ArrayCollection;
// Have tried @CouchDB\Document as well
/**
* @Document(repositoryClass="repositories\ZoneRepository")
*/
class Zone {
/**
* @Id(type="string")
*/
protected $id;
/**
* @Field(type="string", indexed=true)
*/
protected $slug;
/**
* @Field(type="string", jsonName="name", indexed=true)
*/
protected $name;
/** @Field(type="boolean", jsonName="enabled") */
protected $enabled;
}
Долго читаю, но надеюсь, это поможет вам разобраться в проблеме.
Спасибо за помощь
Задача ещё не решена.
Других решений пока нет …