DoctrineOrmServiceProvider
<?php
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
use Doctrine\DBAL\Types\Type;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\Cache\MemcacheCache;
use Doctrine\Common\Cache\ApcCache;
use Doctrine\Common\Cache\RedisCache;
use Doctrine\Common\Cache\XcacheCache;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Doctrine\ORM\Mapping\Driver\YamlDriver;
use Doctrine\ORM\Mapping\Driver\XmlDriver;
use Doctrine\Common\Annotations\SimpleAnnotationReader;
use Doctrine\Common\Annotations\CachedReader;
use \Silex\Application;
use \Silex\ServiceProviderInterface;
class DoctrineOrmServiceProvider implements ServiceProviderInterface
{
public function register(Application $app)
{
if (!$app['db'] instanceof \Doctrine\DBAL\Connection) {
throw new \InvalidArgumentException('$app[\'db\'] must be an instance of \Doctrine\DBAL\Connection');
}
$app['db.orm.em'] = $app->share(function() use($app) {
return EntityManagerUtils::getEntityManager($app['db'], $app['db.orm.options']);
});
}
public function boot(Application $app) { }
}
class EntityManagerUtils {
const CACHE_TYPE_APC = 'apc';
const CACHE_TYPE_XCACHE = 'xcache';
const CACHE_TYPE_MEMCACHE = 'memcache';
const CACHE_TYPE_REDIS = 'redis';
const CACHE_TYPE_ARRAY = 'array';
/**
* @param mixed $dbal
* @param $ormOptions
* @return \Doctrine\ORM\EntityManager
*/
public static function getEntityManager($dbal, $ormOptions)
{
$config = self::getOrmConfiguration($ormOptions);
$em = EntityManager::create($dbal, $config);
$platform = $em->getConnection()->getDatabasePlatform();
if(array_key_exists('additional_mapping_type', $ormOptions)) {
foreach($ormOptions['additional_mapping_type'] as $type => $cast) {
$platform->registerDoctrineTypeMapping($type, $cast);
}
}
return $em;
}
/**
* TODO キャッシュの設定は専用に設定値を持たせる
*
* @param $type
* @return \Doctrine\Common\Cache\Cache
*/
private static function getCache($type)
{
$cache = null;
$type = strtolower($type);
if ($type === self::CACHE_TYPE_APC && extension_loaded('apc')) {
$cache = new \Doctrine\Common\Cache\ApcCache();
} else if ($type === self::CACHE_TYPE_XCACHE && extension_loaded('xcache')) {
$cache = new \Doctrine\Common\Cache\XcacheCache();
} else if ($type === self::CACHE_TYPE_MEMCACHE && extension_loaded('memcache')) {
$memcache = new \Memcache();
$memcache->connect('127.0.0.1');
$cache = new \Doctrine\Common\Cache\MemcacheCache();
$cache->setMemcache($memcache);
} else if ($type === self::CACHE_TYPE_REDIS && extension_loaded('redis')) {
$redis = new \Redis();
$redis->connect('127.0.0.1');
$cache = new \Doctrine\Common\Cache\RedisCache();
$cache->setRedis($redis);
} else {
$cache = new ArrayCache();
}
return $cache;
}
/**
* @param $type
* @param $path
* @return \Doctrine\Common\Persistence\Mapping\Driver\MappingDriver
* @throws \InvalidArgumentException
*/
private static function getDriver($type, array $path)
{
switch ($type) {
case 'default':
case 'annotation':
$reader = new SimpleAnnotationReader();
$reader->addNamespace('Doctrine\ORM\Mapping');
$cachedReader = new CachedReader($reader, new ArrayCache());
$driver = new AnnotationDriver($cachedReader, $path);
break;
case 'yml':
$driver = new YamlDriver($path);
break;
case 'xml':
$driver = new XmlDriver($path);
break;
default:
throw new \InvalidArgumentException(sprintf('"%s" is not a recognized driver', $type));
break;
}
return $driver;
}
/**
* @param $ormOptions
* @return \Doctrine\ORM\Configuration
*/
private static function getOrmConfiguration($ormOptions)
{
$cache = self::getCache($ormOptions['cache']);
$config = new \Doctrine\ORM\Configuration();
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);
$chain = new MappingDriverChain;
foreach ((array)$ormOptions['entities'] as $entity) {
$driver = self::getDriver($entity['type'], (array)$entity['path']);
$chain->addDriver($driver, $entity['namespace']);
}
$config->setMetadataDriverImpl($chain);
if(array_key_exists('custom_types', $ormOptions)) {
foreach($ormOptions['custom_types'] as $type => $class) {
Type::addType($type, $class);
}
}
//Numericオンリーではまずいのでこのあたりは後ほど検討
if(array_key_exists('custom_functions', $ormOptions)) {
foreach($ormOptions['custom_functions'] as $funcName => $class) {
$config->addCustomNumericFunction($funcName, $class);
}
}
$config->setProxyDir($ormOptions['proxies_dir']);
$config->setProxyNamespace($ormOptions['proxies_namespace']);
$config->setAutoGenerateProxyClasses($ormOptions['auto_generate_proxies']);
return $config;
}
}
---
all:
dbal:
wrapperClass: Doctrine\DBAL\Connections\MasterSlaveConnection
driver: pdo_mysql
orm:
proxies_dir: /path/to/project/tmp/doctrine/proxy
proxies_namespace: DoctrineProxies
cache: null
auto_generate_proxies: true
entities:
- type: yml
path: /path/to/project/config/doctrine/meta
namespace: Hoge\ORM\Entity
custom_types:
point: Hoge\Doctrine\Type\PointType
custom_functions:
GEOMFROMTEXT: Hoge\Doctrine\Type\GeomFromText
DISTANCE: Hoge\Doctrine\Type\Distance
YEAR: DoctrineExtensions\Query\Mysql\Year
MONTH: DoctrineExtensions\Query\Mysql\Month
DAY: DoctrineExtensions\Query\Mysql\Day
additional_mapping_type:
point: point
geometry: point
enum: string
prod:
dbal:
master:
user: username
password: password
dbname: dbname
host: 127.0.0.1
slaves:
- user: username
password: password
host: 127.0.0.1
dbname: test
- user: username
password: password
host: 127.0.0.1
dbname: dbname
<?php
$app = new Application();
$app->register(new \Silex\Provider\DoctrineServiceProvider(), array(
'db.options' => Config::get('dbal')
));
$app->register(new \DoctrineOrmServiceProvider(), array(
'db.orm.options' => Config::get('orm')
));