knowledge-base/records/plugin-dev/KB-PLUGIN-032-glpi11-second-dbmysql-connection.md
Rodolpho Lopes f1ec0c6405 KB-PLUGIN-032/033: segunda conexão DBmysql + comandos de console de plugin (GLPI 11)
Aprendizados validados no desenvolvimento do plugin sync:
- KB-PLUGIN-032: subclasse DBmysql read-only para banco externo (gotchas de
  senha rawurldecode, query() guard, flag connected).
- KB-PLUGIN-033: comandos de console de plugin exigem src/ + namespace de nome
  plugins:<key>:.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-16 17:16:46 +00:00

3.4 KiB

id title domain tags status severity created_at updated_at applies_to related_records
KB-PLUGIN-032 GLPI 11 — Segunda conexão de banco read-only via subclasse de DBmysql plugin-dev
glpi11
plugin
database
dbmysql
connection
read-only
external-db
sync
active high 2026-06-16 2026-06-16
plugins GLPI 11.x que precisam ler de um banco GLPI externo
plugin Sync (ingestão PROD legado → QA)
KB-PLUGIN-030
KB-PLUGIN-014

GLPI 11 — Segunda conexão de banco via subclasse de DBmysql

Contexto

Um plugin pode precisar ler de um segundo banco (ex.: o PROD legado de um cliente) sem tocar na conexão padrão do GLPI (global $DB). O core já oferece toda a infraestrutura: basta uma subclasse de \DBmysql apontando para o outro host. Reaproveita-se doQuery(), request(), fetchAssoc(), tableExists() etc.

Como fazer

DBmysql::connect()propriedades de instância: $dbhost, $dbuser, $dbpassword, $dbdefault. O construtor nativo (__construct($choice)) chama connect() imediatamente — portanto não chame parent::__construct(): defina as propriedades primeiro e só então chame $this->connect().

namespace GlpiPlugin\Meuplugin;

use DBmysql;

class SourceDB extends DBmysql
{
    public function __construct(string $host, string $dbname, string $user, string $password, int $port = 3306, bool $use_utf8mb4 = true)
    {
        $this->dbhost      = $port > 0 ? $host . ':' . $port : $host;
        $this->dbuser      = $user;
        $this->dbpassword  = rawurlencode($password); // ver gotcha abaixo
        $this->dbdefault   = $dbname;
        $this->use_utf8mb4 = $use_utf8mb4;
        $this->connect();
    }

    public function isConnected(): bool
    {
        return (bool) $this->connected;
    }
}

Gotchas confirmados

  1. Senha é rawurldecoded em connect(). A linha real do core é real_connect($host, $this->dbuser, rawurldecode($this->dbpassword), ...). Portanto guarde a senha rawurlencode()-ada na propriedade (idêntico ao config/config_db.php nativo). Senha com %, +, etc. quebra se passada crua.

  2. Host com porta: connect() faz explode(':', $host). Passe "host:porta" numa string só; não há parâmetro de porta separado.

  3. query() SEMPRE lança exceção (Executing direct queries is not allowed!) — é um guard, não o executor. Para SELECT use doQuery() (retorna mysqli_result) + fetchAssoc()/fetchArray(), ou request() (iterator). Para DDL, ver [KB-PLUGIN-030].

  4. Sucesso da conexão: connect() seta $this->connected = true só em caso de sucesso; em falha permanece false sem lançar exceção. Cheque connected (a falha de credencial NÃO crasha — retorna conexão não-conectada).

  5. Defaults seguros em DBmysql: dbssl=false, use_utf8mb4=false, connected=false. Para ler bancos GLPI 10.0.6+ defina use_utf8mb4=true.

Validação

Comprovado no plugin sync (2026-06-16): subclasse SourceDB conectou a um GLPI 11.0.7 externo via bin/console plugins:sync:test-connection, leu VERSION(), glpi_configs (versão) e COUNT(*) de glpi_tickets. Senha inválida retornou connected=false com exit code 1, sem fatal.

Classificação

  • Tipo: padrão de implementação reutilizável.
  • Reutilização: qualquer plugin com fonte de dados em segundo banco.