За последние 24 часа нас посетили 20693 программиста и 1114 роботов. Сейчас ищут 398 программистов ...

Использование PDO внутри класса

Тема в разделе "PHP для новичков", создана пользователем 118_64, 19 фев 2020.

Метки:
  1. 118_64

    118_64 Активный пользователь

    С нами с:
    8 янв 2015
    Сообщения:
    84
    Симпатии:
    2
    В приложении используется файл config.php, в который вынесено подключение к БД. Файл выглядит так: http://phpfaq.ru/pdo#connect

    Переписываю код с использованием ООП с установкой подключения к БД в конструкторе по примеру, описанному здесь: http://code.mu/ru/php/book/oop/class/DatabaseShell

    PHP:
    1.     class DatabaseShell
    2.     {
    3.         private static $link;
    4.  
    5.         public function __construct()
    6.         {
    7.             if (!self::$link) {
    8.                 self::$link = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
    9.                 mysqli_query(self::$link, "SET NAMES 'utf8'");
    10.  
    11.                 $dbcnx = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
    12.                 $dsn = "mysql:host=DB_HOST;dbname=DB_NAME;charset=UTF8";
    13.                 $opt = array(
    14.                     PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    15.                     PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    16.                 );
    17.  
    18.                 $pdo = new PDO($dsn, DB_USER, DB_PASS, $opt);
    19.                 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
    20.             }
    21.         }
    22.     }
    В коде реализована автозагрузка:
    PHP:
    1. spl_autoload_register(function($class) {
    2.   // ...
    3. });
    которая автоматически пытается подгрузить класс PDO, не находит, потому что он нигде не прописан, и предсказуемо выдает "Fatal error".

    Прошу подсказать, что именно я делаю неправильно и как это исправить. Прописать отдельно класс PDO? Где-то можно посмотреть на пример? То, что код неправильный и дублирующий, я вижу и понимаю.
     
    #1 118_64, 19 фев 2020
    Последнее редактирование: 19 фев 2020
  2. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    Переписывать с использованием ООП применяя процедурный стиль так себе занятие. Класс PDO это уже давно неотъемлемая часть РНР, если кто-то его не находит, это уже не трудности - это проблема.
    Какая версия РНР ?
     
  3. 118_64

    118_64 Активный пользователь

    С нами с:
    8 янв 2015
    Сообщения:
    84
    Симпатии:
    2
    php - 7.4.1
     
  4. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    В конфигурационном файле РНР интерпретатора модуль pdo подключен?
    Кстати откуда ты взял этот класс? Скачал с инета и сунул туда строчки про pdo в надежде, что всё заработает? :)
     
  5. 118_64

    118_64 Активный пользователь

    С нами с:
    8 янв 2015
    Сообщения:
    84
    Симпатии:
    2
    Да, подключен. В виде подгружаемого файла в процедурном стиле всё работает. Тут проблема в другом даже: автозагрузка ищет класс PDO, которого нет. Я на этом остановился.
     
  6. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    Просто найди синглтон с пдо и посмотри как он написан и как им пользоваться :)
     
  7. 118_64

    118_64 Активный пользователь

    С нами с:
    8 янв 2015
    Сообщения:
    84
    Симпатии:
    2
    Нашел. Как это решит озвученную проблему автоматического старта загрузки класса, которого не существует?
     
  8. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    @118_64, нет такой проблемы, класс PDO встроен в РНР он есть всегда. Автолоад срабатывает только тогда когда РНР не видит объявленный клас в своих "списках".
    Другое дело ты не в курсе, что такое области видимости. Твой пдо не видно за пределами конструктора класса, не говоря уж о приложении в целом.
    В чём проблема скопипастить найденный класс и посмотреть как правильно его использовать?
     
  9. 118_64

    118_64 Активный пользователь

    С нами с:
    8 янв 2015
    Сообщения:
    84
    Симпатии:
    2
    я хочу не скопировать, а понять. Вопрос области видимости был ответом, который я искал.
     
  10. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.548
    Симпатии:
    1.754
    На будущее, копируй ошибки полностью, как они выдаются.
     
  11. 118_64

    118_64 Активный пользователь

    С нами с:
    8 янв 2015
    Сообщения:
    84
    Симпатии:
    2
    Взял реализацию синглтон отсюда. Вот мой код:

    PHP:
    1. <?php
    2. namespace Models;
    3.  
    4. class DB
    5. {
    6.     private static $_instance = null;
    7.  
    8.     // для безопасности настройки лучше хранить в файле с конфигом
    9.     private static $mysqlhost = "localhost";
    10.     private static $dbname = "shop";
    11.     private static $dbuser = "root";
    12.     private static $dbpasswd = "1234";
    13.  
    14.     public function __construct () {
    15.     //private function __construct () {
    16.  
    17.         $this->_instance = new PDO(
    18.             'mysql:host=' . self::$mysqlhost . ';dbname=' . self::$dbname,
    19.             self::$dbuser,
    20.             self::$dbpasswd,
    21.             [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"]
    22.         );
    23.  
    24.     }
    25.  
    26.     private function __clone () {}
    27.     private function __wakeup () {}
    28.  
    29.     public static function getInstance()
    30.     {
    31.         if (self::$_instance != null) {
    32.             return self::$_instance;
    33.         }
    34.  
    35.         return new self;
    36.     }
    37. }
    Использование:
    $db = DB::getInstance();

    Получаю ту же ошибку:

    Fatal error: Uncaught Exception: Для класса Models\PDO не найден файл E:/data\models\PDO.php. Проверьте наличие файла по указанному пути. Убедитесь, что пространство имен вашего класса совпадает с тем, которое пытается найти фреймворк для данного класса. Например, вы создаете класса модели, но забыли заюзать ее через use. В этом случае вы пытаетесь вызвать класс модели в пространстве имен контроллера, а такого файла нет. in E:\data\index.php:31 Stack trace: #0 [internal function]: {closure}() #1 E:\data\models\DB.php(18): spl_autoload_call() #2 E:\data\models\DB.php(36): Models\DB->__construct() #3 E:\data\config\router.php(18): Models\DB::getInstance() #4 E:\data\index.php(35): require('E:\\data\\config\\...') #5 {main} thrown in E:\data\index.php on line 31

    "Невидимость" $pdo обсуждается, например, здесь. В качестве решения предлагается передавать $pdo в качестве параметра в конструктор. ОК. Но почему не работает синглтон, в котором предполагается создание объекта PDO внутри конструктора? В чём проблема и как её исправить?
     
    #11 118_64, 20 фев 2020
    Последнее редактирование: 20 фев 2020
  12. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.548
    Симпатии:
    1.754
    PDO в глобальном namespace, нужно либо use PDO поставить вверх, либо писать \PDO
    --- Добавлено ---
    Читаем про namespace внимательно.
     
    118_64 нравится это.
  13. 118_64

    118_64 Активный пользователь

    С нами с:
    8 янв 2015
    Сообщения:
    84
    Симпатии:
    2
    спасибо!