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

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?

Related

Symfony Bundle references "#Bundle" - FileLocatorFileNotFoundException

I am currently building my own Symfony bundle (I am using version 3.3). It works fine so far, but now I wanted to move the bundle-specific service definition out of my app/config/services.yml to a service definition within the bundle.
I created a src/MyBundle/Resources/config/services.yml and followed the guide How to Load Service Configuration inside a Bundle to load it. That works just fine, but I thought that the paths inside the newly created services.yml look a bit ugly:
MyBundle\:
resource: '../../*'
exclude: '../../{Tests}'
So I thought it would look a little cleaner, if I use the #Bundle-notation instead:
MyBundle\:
resource: '#MyBundle/*'
exclude: '#MyBundle/{Tests}'
However, than I was facing the error:
FileLocatorFileNotFoundException
The file "#MyBundle" does not exist (in: <...>\MyBundle\DependencyInjection/../Resources/config), where <...> corresponds to an absolute path.
I also tested whether it was a naming issue of the bundle name, but when I have a wrongly named bundle reference in the app/config/services.yml, e.g. #SomeBundleThatDoesNotExist then I get a different error:
FileLoaderLoadException
Bundle "SomeBundleThatDoesNotExist" does not exist or it is not enabled.
So my question is: Why does the #Bundle-notation work fine in the app/config/services.yml but not in the src/MyBundle/Resources/config/services.yml?
If you use the service remember make public for external use:
autowire: true
public: true
But, if your symfony dont know where is the bundle please chec this answer:
Symfony generated Bundle doesn't work

Provide Doctrine with custom cache factory for second level cache

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

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.

Entity alias in new symfony 2.7 directory structure

after adapting to new recommended structure in Symfony 2.7 I'm not able to access entity alias through $em->getRepository('Bundle:Entity').
This is my directory structure:
MyBundle
- Component
- Catalog
- Model
Product.php
And my mapping definitition in config.yml:
mappings:
mybundle:
type: annotation
dir: %kernel.root_dir%/../src/mybundle/Component/Product/Model
prefix: MyBundle\Component\Product\Model
alias: ??? # I tried different things
What should I write in $em->getRepository('MyBundle:Product') instead of MyBundle:Product to succesfully accesing the entity?
If possible I would like to use default Symfony alias, so I don't need to specify an alias for every entity in config.yml
Actually I didn't need generate:bundle as it's not a real bundle but a namespace and a logical organization of files.
The solution is to specify the complete namespace in getRespository():
$em->getRepository('MyBundle\\Component\\Product\\Model\\CFGProduct)
Thanks

Nothing to update "Doctrine"

I'm using Symfony2 with Doctrine to try and update a table schema. I was able to create the table. I was also able to populate the table. However after updating the comments in the Entity (I wanted some fields to become nullable), those changes did NOT get picked up.
I did create the entity with the "Annotations" option chosen. But when I added this line "nullable=true" to the Entity on the field imageName nothing happens. ie: when I run "./app/console doctrine:schema:update" I get the following output "Nothing to update - your database is already in sync with the current entity metadata."
Note, I have tried deleted the table via: ./app/console doctrine:database:drop --force and then recreating it via: ./app/console doctrine:database:create and then also ./app/console doctrine:schema:create but it STILL does not add my updated nullable field to imageName.
I was able to figure this out. I first of all created my entity "Foobar" using yml as the Configuration format. I then wanted to use "annotation" as the configuration format so I manually deleted the Entity folder (I only had one table created), however I did NOT delete the configuration yml in the Resources/config/doctrine/Foobar.orm.yml.
Thus when I created the entity again, this time using the annotation as the configuration format, it was still linking to the yml configuration. Removing that solved all the troubles.
I have however decided to stick to yml as I feel it is a little easier to read than the Doctrine Metadata found in the comments.
I had been stuck with this for almost 2 days. Removing all the file in /src/AppBundle/Resources/config/doctrine resolve my issue.
For me, the key was to clear Redis cache.
php app/console redis:flushdb
I has this problem too. Have you right annotation before class declaration?
/**
*
* #ORM\Entity <- this does the trick
*/
class MyEntityName
{
...
Check doctrine.yaml config file for orm mappings:
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
As you see here all entities should have prefix (namespace) App\Entity
You have to check your entities namespace, it should be App\Entity or whatever you want in config

Resources