Как избежать двойного подключения базы данных MySQL?

В своем скрипте я вызываю функцию

<?php if (checkPinCode() == 1): ?>
 текст
<?php endif ?>

Сама функция подключается к базе данных

<?php
session_start();

/**
  * Function 
  */

function check() {

include __DIR__ . '/db_config.php';

Все работает корректно до того, как повторно не вызову ее.

Т.е. дважды прописываю в скрипте

<?php if (checkPinCode() == 1): ?>
 текст
<?php endif ?>

<?php if (checkPinCode() == 1): ?>
 текст два
<?php endif ?>

Обратите внимание: Константа DBSERVER уже определена в ...

require_once __DIR__ . '/db_config.php'; не решило проблему.

Как проверить определены ли уже константы, чтобы не вызывать ошибок?

Посоветовали создать шаблон Singleton, не получается у меня интегрировать его в свой скрипт.

db_config.php

<?php
define('DBSERVER', 'localhost');
define('DBNAME', 'cayddftg_pin_code');
define('DBUSER', 'cayddftg_cayddftg');
define('DBPASS', '2E0m9X0r');

$mysqli = new mysqli(DBSERVER, DBUSER, DBPASS, DBNAME);

if($mysqli->connect_errno > 0){
    die('Error: [' . $mysqli->connect_error . ']');
}

/* Charset */
if (!$mysqli->set_charset('utf8mb4'));

/* MYSQLI  REPORT ERROR | MYSQLI REPORT STRICT */   
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

/* PayPal configuration */ 
define('PAYPAL_SANDBOX', TRUE); // TRUE or FALSE 

/* Change not required */ 
define('PAYPAL_URL', (PAYPAL_SANDBOX == true)?"https://www.sandbox.paypal.com/cgi-bin/webscr":"https://www.paypal.com/cgi-bin/webscr");

Ответы (3 шт):

Автор решения: Alex Khonko

Подозреваю, что ваш singletone не является таковым, раз уже можно создать 2 екземпляра класса.

вот для примера типичный singletone БД, пересмотрите, мб у вас что-то не так

class DB
{
    private static $_instance = null;
    private static $_connection;
    private const DB_HOST = 'localhost';
    private const DB_NAME = 'itvdn';
    private const DB_USER = 'root';
    private const DB_PASS = 'password';

    private function __construct()
    {
        static::$_connection = new PDO(
            'mysql:host=' . self::DB_HOST . ';dbname=' . self::DB_NAME,
            self::DB_USER,
            self::DB_PASS,
            [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"]
        );

    }

    private function __clone()
    {
    }

    private function __wakeup()
    {
    }

    public static function getInstance(): self
    {
        if (!static::$_instance) {
            static::$_instance = new static();
        }

        return static::$_instance;
    }

    public function getConnection(): PDO
    {
        return static::$_connection;
    }
}
→ Ссылка
Автор решения: Алексей Шиманский

Следуя написанному в документации:

Как и superglobals, константы доступны из любой области видимости. Константы можно использовать из любого места скрипта независимо от области видимости.

или

Like superglobals, the scope of a constant is global. Constants can be accessed from anywhere in a script without regard to scope. For more information on scope, read the manual section on variable scope.

Поэтому даже если константа объявлена в функции, то она, если можно так сказать, "всплывает" и получается, что она уже существует.

Так что эти переменные надо подключать единожды в каком-либо файле, который будет подключаться к проекту единожды.


Так же стоит рассмотреть подход, когда работа происходит через единую точку входа в приложении. Это самый распространённый подход. Тогда скрипт с глобальными переменными можно будет подключить где-то в самом начале единожды и всё.

→ Ссылка
Автор решения: Ипатьев

Для того чтобы решить эту ппоблему, надо запомнить несколько важных, но очень простых правил

  1. Подключение к БД должно быть одно. Для этого файл с подключением надо инклюдить не в каждой функции, а в самом начале кода, один раз.
  2. Подключение к БД при этом хранится в переменной, в данном случае $mysqli.
  3. Для того чтобы получить доступ к переменной внутри функции, ее надо передат ьв качестве параметра

То есть при создании функции надо писать так

function checkPinCode($mysqli) {

а при вызове - так:

checkPinCode($mysqli)

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

→ Ссылка