bolt / core

🧿 Bolt 5 core
https://boltcms.io
MIT License
550 stars 161 forks source link

Re-enable multiple db table prefixes? - possible fix for old problem with identifying EntityManagers #2205

Open simongroenewolt opened 3 years ago

simongroenewolt commented 3 years ago

Will elaborate later.

When digging in the code for a way to specify different prefixes for different EntityManagers (a question about prefixes was raised on slack...) I found that this used to be possible using https://github.com/bolt/core/blob/master/src/Doctrine/TablePrefix.php and https://github.com/bolt/core/blob/master/src/Doctrine/TablePrefixTrait.php

Apparently after the introduction of symfony/proxy-manager-bridge this functionality stopped working https://github.com/bolt/core/commit/202bd79edb8aea27133b05f05b286ec7148cae37

I think I've found a fix :-)

I did a little experiment, and found that when you do this:

    protected function setTablePrefix(ObjectManager $manager, string $prefix)
    {
        $key = spl_object_hash($manager);
        // force initializing the ObjectManager in case it is a proxy
        $manager->getMetadataFactory();
        $key2 = spl_object_hash($manager);
        $this->tablePrefixes[$key] = Str::ensureEndsWith($prefix, '_');

        return $this;
    }

$key2 will have the 'correct' spl_object_hash() result.

Why? Well, the original call to spl_object_hash() was before the lazy proxy was initialized. Performing an action on the proxy will initialize it. Apparently this initialization is on a level where it actually means the spl_object_hash does change, even when the documentation of spl_object_hash() suggests to me that such a thing would not be possible.

bobdenotter commented 3 years ago

Ooooh, that's a good find!

Back when the issue started showing up, I looked into it, and chalked it up to "Black magic, nothing we can do." ;-)

jordanaubert commented 2 years ago

I'm currently facing the issue with the changes introduced by https://github.com/bolt/core/pull/3142 and the trick in description doesn't seem to work, I have to revert the getTablePrefix to return current($this->tablePrefixes);, is there something I'm missing (just migrated from 5.1.4 to 5.1.14) ?

simongroenewolt commented 2 years ago

@jordanaubert if you copied my example code you might have missed that the $key2 is the correct one, but the line below assigning it still uses $key, so that would have to be changed to $key2 if you want the code to work.

jordanaubert commented 2 years ago

Yes I noticed it but it didn't work either, it seems getMetadataFactory isn't enough to initialize the proxy in my case. I also tried as suggested in https://github.com/bolt/core/pull/2206.

I also tried to do $manager->getWrappedValueHolderValue() to retrieve the manager from the proxy but the hash is still not the same when applying spl_object_hash on it.