PHP: правильный способ использования соединения с базой данных PDO в классе - PullRequest
0 голосов
/ 25 марта 2010

Попытка организовать весь мой код в классы, и я не могу заставить запросы к базе данных работать внутри класса. Я проверил это без обертки класса, и он работал нормально. Внутри класса = не игра в кости. Что с моими уроками все испортило?

РЕДАКТИРОВАТЬ: Проблема в том, что он не будет запрашивать базу данных и возвращать результат. Любой результат.

class ac
  {
  public function dbConnect() 
    {
    global $dbcon;

    $dbInfo['server'] = "localhost";
    $dbInfo['database'] = "sn";
    $dbInfo['username'] = "sn";
    $dbInfo['password'] = "password"; 

    $con = "mysql:host=" . $dbInfo['server'] . "; dbname=" . $dbInfo['database'];
    $dbcon = new PDO($con, $dbInfo['username'], $dbInfo['password']);
    $dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $error = $dbcon->errorInfo();

    if($error[0] != "") 
      {
      print "<p>DATABASE CONNECTION ERROR:</p>";
      print_r($error);
      }
    }


  public function authentication()
    {
    global $dbcon;

    $plain_username = $_POST['username'];
    $md5_password = md5($_POST['password']);

    $ac = new ac();
    if (is_int($ac->check_credentials($plain_username, $md5_password)))
      {
      ?>
      <p>Welcome!</p> <!--go to account manager here-->
      <?php
      }
    else
      {
      ?>
      <p>Not a valid username and/or password. Please try again.</p>
      <?php
      unset($_POST['username']);
      unset($_POST['password']);
      $ui = new ui();
      $ui->start();
      }
    }



  private function check_credentials($plain_username, $md5_password)
    {
    global $dbcon;

    $userid = $dbcon->prepare('SELECT id FROM users WHERE username = :username AND password = :password LIMIT 1');
    $userid->bindParam(':username', $plain_username);
    $userid->bindParam(':password', $md5_password);
    $userid->execute();

    print_r($dbcon->errorInfo());

    $id = $userid->fetch();
    Return $id;
    }
  }

И если это поможет, вот класс, который его вызывает:

require_once("ac/acclass.php");
$ac = new ac();
$ac->dbconnect();
class ui
  {
  public function start()
    {
    if ((!isset($_POST['username'])) && (!isset($_POST['password'])))
      {
      $ui = new ui();
      $ui->loginform();
      }
    else
      {
      $ac = new ac();
      $ac->authentication();
      }
    }

  private function loginform()
    {
    ?>
    <form id="userlogin" action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
     User:<input type="text" name="username"/><br/>
     Password:<input type="password" name="password"/><br/>
     <input type="submit" value="submit"/>
    </form>
    <?php
    }
  }

Ответы [ 2 ]

3 голосов
/ 25 марта 2010

По умолчанию PDOStatement::fetch возвращает строку в виде массива полей, проиндексированных по имени и номеру столбца (режим PDO::FETCH_BOTH). Это означает, что ac::check_credentials возвращает массив, но ac::authentication проверяет целое число. Кроме того, значения полей являются строками, поэтому is_int не будет работать, если вы явно не преобразуете поле результата в целое число. Попробуйте PDOStatement::fetchColumn() и is_numeric.

    public function authentication() {
        ...
        if (is_numeric($this->check_credentials($plain_username, $md5_password))) {
        ...
    }

    private function check_credentials($plain_username, $md5_password) {
        return $userid->fetchColumn();
    }

В качестве альтернативы is_numeric, убедитесь, что результат проверки учетных данных не идентичен False.

    public function authentication() {
        ...
        if (False !== $this->check_credentials($plain_username, $md5_password)) {
        ...
    }

Некоторые Стилистические Очки

Как указывает Ягго, ui::start и ac::dbConnect должны быть статическими методами. ac::authentication не нужно создавать новый ac; поскольку это не статический метод, он может обращаться к текущему объекту через специальную переменную $this (как это было сделано выше). $dbcon следует сделать статическим свойством ac, чтобы вы не не загрязняли глобальное пространство имен . Имена классов должны использовать UpperCamelCase и должны быть более наглядными.

Классы должны иметь единственную, четко определенную цель и не отклоняться от этого. ac имеет много целей: управлять подключением к БД, обрабатывать аутентификацию и отображать результаты аутентификации. Подумайте о разработке набора классов для уровня доступа к данным, скрывая базу данных от всего остального. Также рассмотрите возможность отделения логики домена (аутентификация и с) от отображения. Это часть шаблона, известного как архитектура Model View Controller . Это не должно происходить сразу; Вы можете медленно рефакторинг кода.

1 голос
/ 25 марта 2010

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

class Foo {

    static function bar() {

    }

}

Foo::bar()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...