1
votes

Symfony Cache tries to instantiate a Doctrine\ODM\MongoDB\Repository\DocumentRepository by passing argument 1 as a string. That is the full class name. But DocumentReposity expects an instance of DocumentManager as first argument.

Below the code. UserRepository is extending Doctrine\ODM\MongoDB\Repository\DocumentRepository. And that expects an instance, not an string in the constructor.

Is this a Doctrine ODM issue or a Symfony issiue and how can I solve it?

Thanks!

Error:

Fatal error: Uncaught Symfony\Component\Debug\Exception\FatalThrowableError: Argument 1 passed to Doctrine\ODM\MongoDB\Repository\DocumentRepository::__construct() must be an instance of Doctrine\ODM\MongoDB\DocumentManager, string given, called in /var/www/html/var/cache/dev/ContainerPtWsxJ7/getPlatform_User_ProviderService.php on line 9 in /var/www/html/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Repository/DocumentRepository.php:52 Stack trace: #0 /var/www/html/var/cache/dev/ContainerPtWsxJ7/getPlatform_User_ProviderService.php(9): Doctrine\ODM\MongoDB\Repository\DocumentRepository->__construct('Foo\ApiB...') 1 /var/www/html/var/cache/dev/ContainerPtWsxJ7/appAppKernelDevContainer.php(157): require('/var/www/html/v...') #2 /var/www/html/var/cache/dev/ContainerPtWsxJ7/getFosOauthServer_ServerService.php(9): ContainerPtWsxJ7\appAppKernelDevContainer->load('getPlatform_Use...') 3 /var/www/html/var/cache/dev/ContainerPtWsxJ7/appAppKernelDevContainer.php(157): require('/var/www/html/v...') #4 /var/www/html in /var/www/html/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Repository/DocumentRepository.php on line 52

Cached class getPlatform_User_ProviderService.php:

use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
// Returns the private 'platform.user.provider' shared service.

return $this->privates['platform.user.provider'] = 
    new \Foo\ApiBundle\Provider\UserProvider(
        ($this->privates['platform.user.repository'] ?? $this->privates['platform.user.repository'] 
        = new \Foo\ApiBundle\Document\Repository\UserRepository('Foo\\ApiBundle\\Document\\User'))
    );

UserRepository:

namespace Foo\ApiBundle\Document\Repository;

use Doctrine\ODM\MongoDB\DocumentRepository;
use Foo\ApiBundle\Document\Company;

class UserRepository extends DocumentRepository {

    public function findByCompany(Company $company, $limit = 5, $skip = 0) {
        $qb = $this->createQueryBuilder();

        return $qb->field('company.$id')->equals(new \MongoId($company->getId()))
                        ->field('disabled')->equals(false)
                        ->limit($limit)
                         ->skip($skip)
                        ->getQuery()->execute();
    }

    public function findOneByActivationHash($hash) {
        return $this->findOneBy(array('activationHash' => $hash));
    }  
...removed the rest of the methods...   
}

User document and annotation:

/**
 * @MongoDB\Document(collection="users",repositoryClass="Foo\ApiBundle\Document\Repository\UserRepository")
 * @MongoDB\InheritanceType("SINGLE_COLLECTION")
 * @MongoDB\Indexes({
 *  @MongoDB\Index(keys={"username"="asc"},unique=true)
 * })
 * @MongoDB\HasLifecycleCallbacks
 * @JMS\ExclusionPolicy("all")
 * ...removed the rest of the annotations...
 */

 abstract class User extends LegacyUser implements 
 \Symfony\Component\Security\Core\User\UserInterface {

services.xml, it's going wrong here!!:

<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services 
http://symfony.com/schema/dic/services/services-1.0.xsd">

    <parameters>
        <parameter key="repository.factory.class">Foo\ApiBundle\Document\Repository\RepositoryFactory</parameter>
    </parameters>
    <services>
        <!-- repository factory -->
        <service id="repository.factory" class="%repository.factory.class%">
            <argument type="service" id="doctrine.mongodb.manager" />
        </service>
        <service id="platform.user.repository" class="%user.repository.class%">
            <!-- This is the first argument which is the string -->
            <!-- It should be an instance of Doctrine\ODM\MongoDB\DocumentManager -->
            <argument>%platform.entity.user.class%</argument>
        </service>
        ...removed the rest of the nodes...

Client code using UserRepository:

class TokenController extends AbstractClientController 
{
    public function fooAction(Request $request) 
    {
        ...
        $repository = $this->getRepositoryFactory()->getUserRepository()
        ...


abstract class AbstractClientController extends AbstractApiController {

abstract class AbstractApiController extends FOSRestController {

Composer:

"require": {
        "symfony/symfony": "v4.2.0",
        "doctrine/orm": "~2.2,>=2.2.3",
        "doctrine/doctrine-bundle": "~1.9",
        "doctrine/mongodb-odm": "2.0.0-alpha1",
        "doctrine/mongodb-odm-bundle": "4.0.0-alpha1",
        "jms/serializer-bundle": "^2.0",
        "friendsofsymfony/rest-bundle": "2.4.0",
        "friendsofsymfony/oauth-server-bundle": "^1.6",
        "twig/extensions": "1.0.*",
        "nelmio/api-doc-bundle": "~2.4",
        "sensio/framework-extra-bundle": "^v5.2.2"
    },
1
Please add the code of the repository and its declaration in your question.A.L
Added the UserRepositoryRichard Jansen
Did you declare the repository as a service? Is it required?A.L
Added more snippets. My goal is to upgrade an old Symfony project PHP5 project to the newest PHP7 and therefore I need to upgrade all old packages too.Richard Jansen

1 Answers

0
votes

It seems to be that the services act differently than in the old Symfony. I don't know exactly how and why.

In my UserProvider I used an instance of UserRepository as argument. But that is not working. Now I use a DocumentManager as argument amd then getting the UserRepository from it. Manually instantiating a repository is not possible as far as I know.

I made some changes in services.xml too. I added autowire="true" so he container will handle the resolving of the DocumentManager.

UserProvider:

// public function __construct(ObjectRepository $userRepository) {
//     $this->userRepository = $userRepository;
// }

public function __construct(\Doctrine\ODM\MongoDB\DocumentManager $documentManager) {
    $this->userRepository = $documentManager->getRepository(\Foo\ApiBundle\Document\User::class);
}

services.xml:

<!--<service id="platform.user.repository" class="%user.repository.class%">
        <argument>%platform.entity.user.class%</argument>
    </service>-->
    <service id="platform.user.provider" class="%platform.user.provider.class%" autowire="true">
        <!--<argument type="service" id="doctrine.mongodb.manager" />-->
    </service>