Проблема со ссылкой на вторую базу данных/источник данных в моем приложении

У меня возникли проблемы с включением второй базы данных в мое приложение.

  1. Я создал обе связи в app.php и app_local.php.
  2. Модель (т. е. BusinessRequests), ссылающаяся на вторую базу данных, реализует defaultConnectionName()

Ошибка:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'app_a.business_requests' doesn't exist

Результирующий SQL – обратите внимание на отсутствие префикса базы данных/соединения при ссылке на BusinessRequests в LEFT JOIN.

SELECT
  Requests.id AS Requests__id,
  Requests.business_request_id AS Requests__business_request_id,
  Requests.notes AS Requests__notes,
  Requests.created AS Requests__created,
  Requests.modified AS Requests__modified,
  BusinessRequests.id AS BusinessRequests__id,
  BusinessRequests.title AS BusinessRequests__title,
  BusinessRequests.status AS BusinessRequests__status,
  BusinessRequests.created AS BusinessRequests__created,
  BusinessRequests.modified AS BusinessRequests__modified
FROM
  requests Requests
  LEFT JOIN business_requests BusinessRequests ON BusinessRequests.id = Requests.business_request_id
WHERE
  Requests.id = 1
LIMIT
  1

База данных app_a (обратите внимание на настройку внешнего ключа)

CREATE TABLE `requests` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `business_request_id` int(11) unsigned DEFAULT NULL,
  `notes` varchar(255) NOT NULL,
  `created` datetime NOT NULL DEFAULT current_timestamp(),
  `modified` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `FK_requests_app_common.business_requests` (`business_request_id`),
  CONSTRAINT `FK_requests_app_common.business_requests` FOREIGN KEY (`business_request_id`) REFERENCES `app_common`.`business_requests` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci

База данных app_common

CREATE TABLE `business_requests` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `status` varchar(255) NOT NULL,
  `created` datetime NOT NULL DEFAULT current_timestamp(),
  `modified` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=70270 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci

Содержание app.php

  'Datasources' => [
    'default' => [
        'className' => Connection::class,
        'driver' => Mysql::class,
        'persistent' => false,
        'timezone' => 'UTC',
        'flags' => [],
        'cacheMetadata' => true,
        'log' => false,
        'quoteIdentifiers' => false,
    ],

    'common' => [
        'className' => Connection::class,
        'driver' => Mysql::class,
        'persistent' => false,
        'timezone' => 'UTC',
        'flags' => [],
        'cacheMetadata' => true,
        'log' => false,
        'quoteIdentifiers' => false,
    ],
],

Содержимое app_local.php (mariadb — это Docker-контейнер)

'Datasources' => [
        'default' => [
            'host' => 'mariadb',
            'username' => 'root',
            'password' => 'root',
            'database' => 'app_a',
            'url' => env('DATABASE_URL', null),
        ],

        'common' => [
            'host' => 'mariadb',
            'username' => 'root',
            'password' => 'root',
            'database' => 'app_common',
            'url' => env('DATABASE_URL', null),
        ],
    ],

Содержание BusinessRequestsTable.php

Здесь я указываю соединение, которое будет использоваться для модели.

public static function defaultConnectionName(): string
{
    return 'common';
}

Содержание RequestsController.php

public function view($id = null)
{
    $request = $this->Requests->get($id, [
           'contain' => ['BusinessRequests'],
    ]);

    $this->set(compact('request'));
}

Вы не можете объединять таблицы из разных соединений, если вы это пытаетесь сделать. Запрос будет отправлен на сервер MariaDB и обработан там, сервер ничего не знает о других соединениях, которые мог установить клиент. Соединения независимы; им даже не обязательно принадлежать одному и тому же серверу.

Álvaro González 25.04.2024 14:33

Тогда мне просто нужно убедиться, что в другой базе данных прочитано текущее соединение по умолчанию?

TechFanDan 25.04.2024 18:15

Странный. Если я оставлю $this->setTable(Configure::read('br_db_name').'.business_req‌​uests');, но удалю соединение common и defaultConnectionName() из модели, это не сработает: Table 'app_a.business_requests' doesn't exist

TechFanDan 25.04.2024 18:44

Если к обеим базам данных можно получить доступ через одно и то же соединение (т. е. один и тот же сервер + одни и те же учетные данные), это правильный путь. Однако я не могу сказать вам, поддерживает ли его CakePHP/4 (в последний раз я использовал фреймворк в более ранней версии, которая не поддерживала).

Álvaro González 26.04.2024 08:38

Старый запрос на добавление функции . Тогда он не был реализован, но содержит хорошие идеи.

Álvaro González 26.04.2024 13:37
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
5
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Укажите в запросе, какая таблица какой базе данных принадлежит. Попробуйте что-то вроде этого:

SELECT
    Requests.id AS Requests__id,
    Requests.business_request_id AS Requests__business_request_id,
    Requests.notes AS Requests__notes,
    Requests.created AS Requests__created,
    Requests.modified AS Requests__modified,
    BusinessRequests.id AS BusinessRequests__id,
    BusinessRequests.title AS BusinessRequests__title,
    BusinessRequests.status AS BusinessRequests__status,
    BusinessRequests.created AS BusinessRequests__created,
    BusinessRequests.modified AS BusinessRequests__modified
FROM
    app_a.requests Requests
    LEFT JOIN app_common.business_requests BusinessRequests ON BusinessRequests.id = Requests.business_request_id
WHERE
    Requests.id = 1
LIMIT
    1

Как мне настроить префикс базы данных для включения в запрос? В находке? Модель может быть?

TechFanDan 25.04.2024 13:46
Ответ принят как подходящий

В этом случае установка префикса базы данных (т. е. app_common) при настройке таблицы в модели, похоже, решила проблему.

public function initialize(array $config): void
{
    parent::initialize($config);

    $this->setTable('app_common.business_requests');
    $this->setDisplayField('title');
    $this->setPrimaryKey('id');

    $this->addBehavior('Timestamp');
}

Другие вопросы по теме