За последние 24 часа нас посетили 22518 программистов и 1069 роботов. Сейчас ищут 698 программистов ...

Синглтон, ООП

Тема в разделе "PHP для новичков", создана пользователем HeuPoH, 30 апр 2018.

Метки:
  1. HeuPoH

    HeuPoH Новичок

    С нами с:
    2 фев 2017
    Сообщения:
    16
    Симпатии:
    0
    Добрый вечер. Помогите плз исправить ошибку
    Fatal error: Uncaught Error: Call to undefined method DataBase:: prepare() in W:\domains\qqq.ru\application\core\DataBase.php:74 Stack trace: #0 W:\domains\qqq.ru\application\core\Model.php(32): DataBase->select('*', 'fThemes', 'id=:id', Array, NULL, NULL, NULL, NULL) #1 W:\domains\qqq.ru\application\models\Theme_Model.php(12): Model->getData() #2 W:\domains\qqq.ru\application\controllers\Theme_Controller.php(18): Theme_Model->getSingleData() #3 W:\domains\qqq.ru\application\core\Route.php(52): Theme_Controller->show_action() #4 W:\domains\qqq.ru\application\load.php(16): Route::start() #5 W:\domains\qqq.ru\index.php(3): require_once('W:\\domains\\qqq....') #6 {main} thrown in W:\domains\qqq.ru\application\core\DataBase.php on line 68

    Если в методе getConnection() просто возвращать return new self; то все работает, но тогда создается несколько объектов
    var_dump в файле Model.php возвращает object(DataBase)#5 (0) { }

    DataBase.php
    PHP:
    1. <?php
    2. class DataBase
    3. {
    4.     const host = 'localhost';
    5.     const dbname = 'cms';
    6.     const user = 'mysql';
    7.     const password = 'mysql';
    8.     private static $dbPDO;
    9.  
    10.     /**
    11.      * DataBase constructor.
    12.      */
    13.     private function __construct()
    14.     {
    15.         try {
    16.             self::$dbPDO = new PDO('mysql:host='.self::host.';dbname='.self::dbname, self::user, self::password);
    17.             self::$dbPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
    18.         } catch (Exception $e) {
    19.             echo 'Connection failed '.$e->getMessage();
    20.         }
    21.         //return self::$dbPDO;
    22.     }
    23.  
    24.     /** Singleton
    25.      * @return DataBase
    26.      */
    27.     public static function getConnection()
    28.     {
    29.         if(is_null(self::$dbPDO)) {
    30.             self::$dbPDO = new self();
    31.         }
    32.         return self::$dbPDO;
    33.     }
    34.  
    35.     /**
    36.      * @param string $fields
    37.      * @param string $table
    38.      * @param string $where
    39.      * @param array $prepare_params
    40.      * @param string $limit
    41.      * @param string $order
    42.      * @param string $rightTable
    43.      * @param string $condition
    44.      * @return array
    45.      * @throws Exception
    46.      */
    47.     public function select($fields = '*', $table, $where, $prepare_params, $limit, $order, $rightTable, $condition)
    48.     {
    49.         $array = [];
    50.         $sql = 'SELECT ' . $fields . ' FROM ' . $table;
    51.  
    52.         if ($rightTable != null) {
    53.             $sql .= ' LEFT JOIN ' . $rightTable . ' on ' . $condition;
    54.         }
    55.  
    56.         if ($where != null) {
    57.             $sql .= ' WHERE ' . $where;
    58.         }
    59.  
    60.         if ($order != null) {
    61.             $sql .= ' ORDER BY ' . $order;
    62.         }
    63.  
    64.         if ($limit != null) {
    65.             $sql .= ' LIMIT ' . $limit;
    66.         }
    67.  
    68.         $sth = self::$dbPDO->prepare($sql);
    69.         $sth->execute($prepare_params);
    70.  
    71.         if ($sth->rowCount() == 0) {
    72.             throw new Exception('SQL request returned 0 rows');
    73.         } else {
    74.             while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
    75.                 array_push($array, $row);
    76.             }
    77.             return $array;
    78.         }
    79.     }
    Model.php
    PHP:
    1. <?php
    2. class Model
    3. {
    4.     protected $pdo;
    5.     public static $lastInsertId;
    6.     protected static $fields = '*';
    7.     protected static $table;
    8.     protected static $rightTable = null;
    9.     protected static $rows = 'id=:id';
    10.     protected static $prepare_params = null;
    11.     protected static $order = null;
    12.     protected static $where = null;
    13.     protected static $condition = null;
    14.     protected static $limit = null;
    15.  
    16.     /**
    17.      * Connection to database
    18.      */
    19.     protected function connectToDB()
    20.     {
    21.         $this->pdo = DataBase::getConnection();
    22.         var_dump($this->pdo);
    23.     }
    24.  
    25.     /**
    26.      * @return string|array
    27.      */
    28.     protected function getData()
    29.     {
    30.         try {
    31.             $this->connectToDB();
    32.             $data = $this->pdo->select(self::$fields, self::$table, self::$where, self::$prepare_params, self::$limit, self::$order, self::$rightTable, self::$condition);
    33.         } catch (Exception $e) {
    34.             $data = $e->getMessage();
    35.         }
    36.         return $data;
    37.     }
    Спасибо
     
  2. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.751
    Симпатии:
    1.322
    Адрес:
    Лень
    не за что

     
  3. HeuPoH

    HeuPoH Новичок

    С нами с:
    2 фев 2017
    Сообщения:
    16
    Симпатии:
    0
    я понял что не существует метод, а почему если вместо этого
    PHP:
    1.    public static function getConnection()
    2.    {
    3.        if(is_null(self::$dbPDO)) {
    4.            self::$dbPDO = new self();
    5.        }
    6.        return self::$dbPDO;
    7.    }
    просто сделать
    PHP:
    1.    public static function getConnection()
    2.    {
    3.            return new self;
    4.    }

    работает. Т.е. в предыдущем коде объект не создается или что
     
  4. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Конструкт запускается один раз ПЕРЕД создание объекта. Кто тебя учил так делать синглтоны?)
    --- Добавлено ---
    PHP:
    1. class Helper
    2. {
    3.     protected static $_instance;
    4.     public static function _instance() {
    5.         return self::$_instance = self::$_instance ?? new self();
    6.     }
    7. }
     
  5. HeuPoH

    HeuPoH Новичок

    С нами с:
    2 фев 2017
    Сообщения:
    16
    Симпатии:
    0
    да там сям читал, твой код не помог( var_dump DataBase::getConnection возвращает object(DataBase)#5 (0) { }, если в return оставить только new self() работает, а var_dump так же возвращает object(DataBase)#5 (0) { }
     
  6. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    потому что ты в первом случае возвращаешь не то, что во втором.
     
  7. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    @HeuPoH, попробуйте не выпускать экземпляр PDO за пределы класса, тем более что есть select (можно будет и др. методы добавить, если понадобятся).
     
  8. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    Ты возвращаешь экземпляр класса Database, а пытаешься из него дёргать методы класса PDO. Естественно садишься в лужу. Вообще, это стремление делать над PDO свои классы, ничего полезного к нему не добавляющие - это глупость. А ещё глупость - пытаться программировать ООП, прочитав что-то там "там-сям" вместо нормальной книжки. Видно, что ни язык ни ООП ты не знаешь. По языку: https://www.ozon.ru/context/detail/id/139127353/, по ООП на php: https://www.ozon.ru/context/detail/id/33506422/ (поищи, обе книги можно и скачать)
     
  9. HeuPoH

    HeuPoH Новичок

    С нами с:
    2 фев 2017
    Сообщения:
    16
    Симпатии:
    0
    Но почему, когда я возвращаю return new self; все работает? если через var_dump я вижу тот же объект DataBase?
    Спасибо за книги, да я ООП не знаю, но почему ты решил, что я вообще не знаю языка?
    --- Добавлено ---
    Спасибо за ответ
     
  10. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    Потому что код так написан, что хрен в нём что поймёшь. Когда ты возвращаешь new self, срабатывает конструктор, который в поле $dbPDO записывает экземпляр PDO, а когда ты пытаешься изображать синглтон, ты туда рисуешь экземпляр своего дурацкого класса :)

    Знание языка предполагает знание, как в нём работают в том числе и классы. Заметь, не то, как правильно программировать ООП - это отдельная от языка история
     
  11. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Все работает, только через задний проход. Это уже не синглтон. Вы позволяете клонировать экземпляры своего класса на одном экземпляре PDO. У синглтона должен быть максимум один экземпляр. Максимум, потому что его можно сделать полностью статичным.
     
  12. HeuPoH

    HeuPoH Новичок

    С нами с:
    2 фев 2017
    Сообщения:
    16
    Симпатии:
    0
    Теперь понял, спасибо