Provide Doctrine with custom cache factory for second level cache - symfony

Background: we're using Symfony 3.1 + Doctrine 2.5.5 + symfony doctrine bundle.
While trying to enable second level caching for our entities, we have encountered the following issue. If we use NONSTRICT_READ_WRITE, everything works fine. However, when we tried to use READ_WRITE, we got the following error
0)
Type error: Argument 2 passed to Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister::__construct() must be an instance of Doctrine\ORM\Cache\ConcurrentRegion, instance of Doctrine\ORM\Cache\Region\DefaultRegion given, called in vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php on line 133
As far as I understood, we need to actually implement our own version of ConcurrentRegion and CacheFactory to make it work (FileLockRegion does not suit us due to its usage of file system to handle cache locks). So I wrote those implementations, but the main issue now lies in following: I cannot find where to put my custom factory class' name in the configuration. We have tried the following locations in config:
1)
doctrine:
orm:
auto_generate_proxy_classes: "%kernel.debug%"
default_entity_manager: master
second_level_cache:
default_cache_factory:
class: AppBundle\Cache\MyCacheFactory
This fails due to
Unrecognized option "second_level_cache" under "doctrine.orm"
even though in our other project using Symfony 2.8 option "second_level_cache" does not throw any errors.
So we went to doctrine bundle code and found the following node description (vendor/doctrine/doctrine-bundle/DependencyInjection/Configuration.php:492)
->arrayNode('second_level_cache')
->children()
->append($this->getOrmCacheDriverNode('region_cache_driver'))
->scalarNode('region_lock_lifetime')->defaultValue(60)->end()
->booleanNode('log_enabled')->defaultValue($this->debug)->end()
->scalarNode('region_lifetime')->defaultValue(0)->end()
->booleanNode('enabled')->defaultValue(true)->end()
->scalarNode('factory')->end()
->end()
So we decided we should try this config in our master entity manager section:
2)
second_level_cache:
region_cache_driver:
type: memcache
enabled: true
log_enabled: true
factory: AppBundle\Cache\MyCacheFactory
regions:
hour_region:
lifetime: 3600
However, even though this config is considered valid, when we actually try to access the entity with configured caching, we get the error 0), which makes us think that this option is being ignored by doctrine/symfony.
Is there any way to do it via .yml config at all? Doctrine docs only propose to implement CacheFactory and provide a PHP code example, but it's still quite unclear where should this PHP code go, even if we decide to abandon the idea of putting our class in .yml config and go the PHP way.

Use type - filelock for configurate FilelockRegion
regions:
default:
cache_driver:
type: service
id: 'Doctrine\Common\Cache\RedisCache'
lifetime: 3600
type: filelock

Related

Issue with Doctrine namespace aliases during upgrade from Symfony 3 to 4

I am trying to upgrade a Symfony 3 application to Symfony 4, but I am having trouble with Doctrine's namespace aliases. My entities are located under AppBundle\Entity (as was the default in older Symfony versions) and there was an alias for that, so my entities are referred to via AppBundle:SomeEntity all over my codebase. I understand that the new way to do this is to use the FQCN instead, but I would like to avoid having to do a massive find&replace operation right now.
I modified config/packages/doctrine.yaml with the following mapping:
mappings:
AppBundle:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/AppBundle/Entity'
prefix: 'AppBundle\Entity'
alias: AppBundle
However, I only get a ReflectionException saying Class AppBundle:SomeEntity does not exist. As far as I can tell from the stack trace, the alias is never resolved, just passed directly down to AbstractManagerRegistry as a class name, which then just passes it to the ReflectionClass constructor. The calling code, e.g., looks like this (inside a controller): $this->getDoctrine()->getRepository("AppBundle:SomeEntity")->...
I have now idea what the problem is. It looks like there is just no logic that would resolve aliases in this code path. It is probably a configuration issue. However, the configuration is mostly the default that comes with Symfony 4. I basically just replaced "App" with "AppBundle". Can anyone help me out here?

Unrecognized config option "url_generator"

I'm currently working on an application involving the dynamic router. To customise the url generator I followed the documentation found here. Unfortunately it doesn't work, the following exception occurs:
InvalidConfigurationException in ArrayNode.php line 312:
Unrecognized option "url_generator" under "cmf_routing.dynamic"
This is the relevant part of my config.yml:
# CMF Routing Configuration
cmf_routing:
cmf_routing:
routers_by_id:
router.default: 200
cmf_routing.dynamic_router: 100
dynamic:
enabled: true
route_provider_service_id: collab.routing.route_provider
url_generator: collab.routing.url_generator
and for reference, this is the part of services.yml:
collab.routing.route_provider:
class: CollaborationBundle\Routing\RouteProvider
arguments:
- "#annotation_reader"
- "#doctrine.orm.entity_manager"
- "#module.provider"
collab.routing.url_generator:
class: CollaborationBundle\Routing\UrlGenerator
What is the right way to use a custom url generator?
This feature is only available in version 1.4 of RoutingBundle, which is not yet released. You can already start to use it with
symfony-cmf/routing-bundle: 1.4.*#dev
The release should happen in the next days, and we don't expect many changes for 1.4 anymore, so this should be pretty safe.

Snc_redis exception when loading

I'm getting the following exception:
InvalidConfigurationException: The child node "clients" at path "snc_redis" must be configured.
I use Symfony 2.3 SncRedisBundle 1.1.x-dev
In config.yml I have
clients:
default:
type: predis
alias: default
dsn: redis://localhost
logging: %kernel.debug%
And I've followed the docs here for installation...
Any idea what would cause this ?
The bundle is looking for configuration values under snc_redis root (as you can see here), which you did not provide.
Now, all this wouldn't normally be a problem, but the clients child node is mandatory (as you can see here), which causes the error above.
Simply make the root configuration node in your config.yml to be snc_redis and the problem will go away. You probably simply missed it when doing copy-paste.

Unable to load an entity that is not related to a bundle

I am building a company Symfony2 library that includes several bundles and a library of classes that can be used by any code. The plan is to eventually turn this into an internal package and install it into projects via composer so that it will live in the vendor directory.
One component of the library has a pair of database entity classes and a single repository class associated with it.
Because the only logic associated with these classes is contained in the repository class, it doesn't seem to make sense to to surround it with a bundle.
I have, as yet, been unable to get Doctrine to load this repository. It initially failed with a
The class 'Dplh\Library\DplhEnum\Entity\EnumGroupRepository' was not found in the chain configured namespaces Dplh\DplhSecurityBundle\Entity
exception. (The reference to my security bundle was initially rather confusing. Turns out that this is Doctrine helping out by listing all of the known entity namespaces (see Symfony error The class XXX was not found in the chain configured namespaces XXX)).
As I understand it, this happens because Doctrine is configured to use auto-mapping and expects all entities to be defined in src/WhateverBundle/Entity directories.
This can be changed with additional Doctrine configuration for specific mappings in config.yml (http://zalas.eu/how-to-store-doctrine-entities-outside-of-a-symfony-bundle/).
So far, I have been unable to get this to work either. I expect it's a minor config thing somewhere. I added the following to config.yml:
doctrine:
dbal:
# ...
orm:
auto_generate_proxy_classes: "%kernel.debug%"
auto_mapping: true
mappings:
DplhEnum:
type: annotation
is_bundle: false
dir: %kernel.root_dir%/../src/Dplh/Library/DplhEnum/Entity
prefix: Dplh\Library\DplhEnum\Entity
alias: DplhEnum
I get two different exceptions depending on my call to getRepository().
// Using the fully-qualified class name.
$this->getEntityManager()->getRepository('Dplh\Library\DplhEnum\Entity\EnumGroup' )
This throws
Attempted to load class "EnumGroupRepository" from namespace "Dplh\DplhEnumBundle\Entity".
Did you forget a "use" statement for another namespace?
// Using the alias.
$this->getEntityManager()->getRepository('DplhEnum\EnumGroup' )
this throws
Class 'DplhEnum\EnumGroup' does not exist
I have verified that the EnumGroupRepository.php file is in the src/Dplh/Library/DplhEnum/Entity directory and the EnumGroupRepository class is in the Dplh\Library\DplhEnum\Entity namespace and that they are in the correct directory.

Non-existing setting in Doctrine bridge in Symfony2

I've just installed Sylius Settings bundle.
After composer finished its work, and after setting everything as in docs (link above), enabling Sylius Settings bundle causes the following error:
The service definition "doctrine.orm.default_metadata_driver" does not exist.
I searched for this keywords (whole service name) for the whole vendors folder, but it found it only in some Doctrine test files, nowhere else. Anyone knows what is it about? Perhaps it's just a "legacy bug" in SF2?
Or perhaps not. I found this class for the moment:
Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass
in particular this part (constructor):
public function __construct($driver, array $namespaces, array $managerParameters, $enabledParameter = false, array $aliasMap = array())
{
$managerParameters[] = 'doctrine.default_entity_manager';
parent::__construct(
$driver,
$namespaces,
$managerParameters,
'doctrine.orm.%s_metadata_driver',
$enabledParameter,
'doctrine.orm.%s_configuration',
'addEntityNamespace',
$aliasMap
);
}
(Note: "'doctrine.orm.%s_metadata_driver'," as a partly hard-coded param)
I wonder if it has anything to do with the fact that I'm not using ORM, but PHPCR-ODM as a default connection type (ORM is non-default additional connection layer).
config.yml part referring to the bundle:
sylius_settings:
driver: doctrine/orm
doctrine_cache:
providers:
my_apc_metadata_cache:
type: apc
namespace: metadata_cache_ns
my_apc_query_cache:
namespace: query_cache_ns
apc: ~
sylius_settings:
type: file_system
Nothing extra ordinary.

Resources