-1

I would like to use Nette Database 3.1.1 in Symfony 5.2.3. My PHP version is 8.0.

When I try to create a database connection in a command I get the following error.

"The autoloader expected class "Nette\Database\IConventions" to be defined in file "/var/www/html/vendor/composer/../nette/database/src/compatibility-intf.php". The file was found but the class was not in it, the class name or namespace probably has a typo."

However, creating a database connection in a controller works just fine. Also creating a database connection in a file without Symfony works when executing the file on the command line.

Here is my command.

<?php

declare(strict_types=1);

namespace App\Command;

use Nette\Database\Connection;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

class TestCommand extends Command
{
    protected static $defaultName = 'app:test';
    protected static $defaultDescription = 'Add a short description for your command';

    protected function configure()
    {
        $this->setDescription(self::$defaultDescription);
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);

        $database = new Connection(
            'mysql:host=127.0.0.1;dbname=test',
            'test',
            'xxx'
        );

        return Command::SUCCESS;
    }
}

Here is the trace of the exception.

Exception trace:
  at /var/www/html/vendor/symfony/error-handler/DebugClassLoader.php:400
 Symfony\Component\ErrorHandler\DebugClassLoader->checkClass() at /var/www/html/vendor/symfony/error-handler/DebugClassLoader.php:357
 Symfony\Component\ErrorHandler\DebugClassLoader->loadClass() at n/a:n/a
 interface_exists() at /var/www/html/vendor/nette/database/src/Database/Conventions.php:45
 include() at /var/www/html/vendor/symfony/error-handler/DebugClassLoader.php:346
 Symfony\Component\ErrorHandler\DebugClassLoader->loadClass() at n/a:n/a
 class_alias() at /var/www/html/vendor/nette/database/src/compatibility-intf.php:23
 include() at /var/www/html/vendor/symfony/error-handler/DebugClassLoader.php:346
 Symfony\Component\ErrorHandler\DebugClassLoader->loadClass() at n/a:n/a
 interface_exists() at /var/www/html/vendor/nette/database/src/Database/Driver.php:100
 include() at /var/www/html/vendor/symfony/error-handler/DebugClassLoader.php:346
 Symfony\Component\ErrorHandler\DebugClassLoader->loadClass() at /var/www/html/vendor/nette/database/src/Database/Drivers/MySqlDriver.php:18
 include() at /var/www/html/vendor/symfony/error-handler/DebugClassLoader.php:346
 Symfony\Component\ErrorHandler\DebugClassLoader->loadClass() at /var/www/html/vendor/nette/database/src/Database/Connection.php:77
 Nette\Database\Connection->connect() at /var/www/html/vendor/nette/database/src/Database/Connection.php:56
 Nette\Database\Connection->__construct() at /var/www/html/src/Command/TestCommand.php:30
 App\Command\TestCommand->execute() at /var/www/html/vendor/symfony/console/Command/Command.php:256
 Symfony\Component\Console\Command\Command->run() at /var/www/html/vendor/symfony/console/Application.php:989
 Symfony\Component\Console\Application->doRunCommand() at /var/www/html/vendor/symfony/framework-bundle/Console/Application.php:96
 Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /var/www/html/vendor/symfony/console/Application.php:290
 Symfony\Component\Console\Application->doRun() at /var/www/html/vendor/symfony/framework-bundle/Console/Application.php:82
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /var/www/html/vendor/symfony/console/Application.php:166
 Symfony\Component\Console\Application->run() at /var/www/html/bin/console:43
Jayster
  • 61
  • 6

1 Answers1

0

I confirmed the rather puzzling issue. I think it is an interaction with PHP's preloading and Symfony. The problem lies here:

# compatibility-intf.php
} elseif (!interface_exists(ISupplementalDriver::class)) {
    class_alias(Driver::class, ISupplementalDriver::class);
    class_alias(Conventions::class, IConventions::class);
}

It only checks for the driver interface before creating an alias for IConventions. Changing it to:

if (!interface_exists(ISupplementalDriver::class)) {
    class_alias(Driver::class, ISupplementalDriver::class);
}
if (!interface_exists(IConventions::class)) {
    class_alias(Conventions::class, IConventions::class);
}

Will get you past the problem. Obviously editing vendor files is not ideal. I would suggest opening an issue on the github site. There appears to be some recent activity so it might get incorporated fairly quickly. If not then you will have to fork the repo and tweak it yourself.

Cerad
  • 48,157
  • 8
  • 90
  • 92