использование глобальной переменной БД внутри классов в PHP

Как я могу использовать глобальную переменную БД внутри класса? Допустим, у меня есть это в моем config.php

$dbh = new PDO("mysql:host=localhost;dbname=mydb", "root", "");

и я хочу использовать этот внутренний класс $dbh следующим образом (MyClass.php)

class MyClass
{
   public function DoSomething($plogin_id)
   {
        $sql = "SELECT * FROM mytable WHERE login_id = :login_id";      
        $stmt = $dbh->prepare($sql);    //line 14
        $stmt->bindParam(':login_id', $plogin_id, PDO::PARAM_STR);
   }
}

И внутри моего файла index.php я использую этот MyClass следующим образом:

include "config.php";
$MyObject = new MyClass();
$login_result = $MyObject->DoSomething("admin");

Это дает мне ошибку:

Неустранимая ошибка: вызов функции-члена prepare() для не-объекта в C:\xampp\htdocs\MyProject\admin\includes\classes\MyClass.php в строке 14


person Ali    schedule 16.12.2010    source источник


Ответы (3)


Вы должны каким-то образом передать объект $dbh объекту MyClass. Поскольку вы не хотите использовать глобальные переменные, я предлагаю передать их конструктору MyClass.

Ваш MyClass и index.php могут выглядеть примерно так:

class MyClass
{
   protected $dbh = null;

   public function __construct ( PDO $Pdh )
   {
      $this->dbh = $Pdh;
   }

   public function DoSomething($plogin_id)
   {
        $sql = "SELECT * FROM mytable WHERE login_id = :login_id";      
        $stmt = $this->dbh->prepare($sql);    //line 14
        $stmt->bindParam(':login_id', $plogin_id, PDO::PARAM_STR);
   }
}

// in your index.php
$MyObject = new MyClass ( $dbh );

Это в основном шаблон, называемый внедрением зависимостей. Подробнее о том, что такое Это.

person Jan Hančič    schedule 16.12.2010

Вы можете ввести его в свою функцию, используя:

global $dbh;

Однако было бы лучше добавить его в класс, например:

class MyClass
{
    private $dbh;

    public function __construct($dbh) {
        $this->dbh = $dbh;
    }

    public function DoSomething($plogin_id)
    {
        $sql = "SELECT * FROM mytable WHERE login_id = :login_id";      
        $stmt = $this->dbh->prepare($sql);    //line 14
        $stmt->bindParam(':login_id', $plogin_id, PDO::PARAM_STR);
    }
}

а потом:

include "config.php";
$MyObject = new MyClass($dbh); // I'm assuming $dbh is created in config.php
$login_result = $MyObject->DoSomething("admin");

Или введите его в свою функцию во время вызова:

class MyClass
{
    public function DoSomething($plogin_id, $dbh)
    {
        $sql = "SELECT * FROM mytable WHERE login_id = :login_id";      
        $stmt = $dbh->prepare($sql);    //line 14
        $stmt->bindParam(':login_id', $plogin_id, PDO::PARAM_STR);
    }
}

А потом:

include "config.php";
$MyObject = new MyClass($dbh); // I'm assuming $dbh is created in config.php
$login_result = $MyObject->DoSomething("admin", $dbh);
person Spiny Norman    schedule 16.12.2010

Это самый распространенный метод:

public function DoSomething($plogin_id){
    global $dbh;
    ...

Альтернативный подход:

Создайте одиночку для подключения к базе данных. И вы используете это вместо глобальной переменной:

$stmt = MyDBConn::getInstance()->prepare($sql);
person Alin Purcaru    schedule 16.12.2010
comment
Вы выступаете за использование глобальных переменных. - person Jan Hančič; 16.12.2010
comment
@Алин; Я не проголосовал против, но проблема, которую вы на самом деле отвечаете на заголовок вопроса, но скажем, ОП неправильно понял проблему, его проблема на самом деле не использует это - person RageZ; 16.12.2010
comment
Вы читали вопрос?! Это способ использования глобальных переменных в функции. Погода это хорошо или плохо это совсем другой вопрос. - person Alin Purcaru; 16.12.2010
comment
Тем не менее, мы должны продвигать лучшие практики здесь. Не лайзины. - person Jan Hančič; 16.12.2010
comment
@Jan Hančič Лучшие практики зависят от ситуации. Если пользователь новичок и не знает об операторе global, не думаете ли вы, что он должен сначала узнать об этом, прежде чем переходить к шаблонам проектирования? Так рождаются плохие программисты... пропуская основы. - person Alin Purcaru; 16.12.2010
comment
@Алин: определенно согласен. @Jan, на мой взгляд, ты слишком далеко зашел - person RageZ; 16.12.2010
comment
Единственное, что он должен знать о ключевом слове global, это не использовать его. И внедрение зависимостей тоже не совсем ракетостроение :) Синглтоны также являются плохой практикой (у них есть несколько применений), потому что они в основном представляют собой причудливый способ использования ключевого слова global. - person Jan Hančič; 16.12.2010
comment
@RageZ, извините меня за попытку научить кого-то делать что-то правильно, а не наполовину. - person Jan Hančič; 16.12.2010
comment
@Jan: вам не нужно плохо воспринимать, просто я думаю, что в программировании вы должны делать часть между наличием решения и передовой практикой. Существует так много лучших практик, в конце концов, вы ничего не кодируете. - person RageZ; 16.12.2010
comment
@Jan: Я имею в виду, что вы можете упомянуть об этом в своем ответе, но после голосования против, даже если ОП попросил global, это слишком много, ИМХО - person RageZ; 16.12.2010
comment
@RageZ Я согласен с вами в том, что вы не используете в своем коде каждую хорошую практику, о которой вы когда-либо слышали. Но это, это самое основное, и я действительно не вижу смысла учить кого-то делать что-то неправильно. Если он будет использовать глобальные переменные, это просто испортит его код, и в будущем у него будет больше проблем. - person Jan Hančič; 16.12.2010
comment
Спасибо за комментарии, ребята, они помогли мне понять проблему. Например, Алин рассказал мне, как их использовать, что помогло мне понять, почему их не следует использовать. Итак, я думаю, что решение Яна и Спайни - лучший способ, верно!? - person Ali; 16.12.2010
comment
@Али Да. Это был бы лучший способ сделать это. - person Alin Purcaru; 16.12.2010