PHP, нужна помощь с bind_param

251
04 апреля 2018, 08:45

Пытаюсь написать класс для sql query. Вот, попробовала написать такое:

class SQL {
public $connection;
public $query;
public function __construct() {
    $this->connection = mysqli_connect("localhost", "blabla", "arararar");
    mysqli_select_db($this->connection, "blabla");
}
public function select($rowName, $tableName, $rowNameCondition, $whereCondition) {
    if (strlen($rowNameCondition) == 0 && strlen($whereCondition) == 0) {
        $this->query = $this->connection->prepare("select ? from ?");
        $this->query->bind_param('ss', $rowName, $tableName);
        $this->query->execute();
        return $this->query->fetchAll();
    } else {
        $this->query = $this->connection->prepare("select ? from ? where ? = ?");
        $this->query->bind_param('sssi', $rowName, $tableName, $rowNameCondition, $whereCondition);
        $this->query->execute();
        return $this->query->fetchAll();
    }
    //return mysqli_query($this->connection, $this->query);
}

}

Вызываю и использую таким образом:

$result = $SQLobject->select("city", "telegramUsers", "chatID", $chatID);
    while ($row = mysqli_fetch_assoc($result)) {
        if ($row["city"] !== "none") {
            $cityID = $row["city"];
        } elseif ($row["city"] == "none") {
            $telegramAPIobject->sendMessage("Будь ласка, виберіть місто", $chatID);
        }
    }

Пожалуйста-пожалуйста, подскажите что я делаю не так

Answer 1

Вы хотите написать конструктор SQL-запросов. Удобно разделить само конструирование и использование полученного запроса. Для начала соберём запрос с плэйсхолдерами (без значений, но с указателями куда надо подставить значения), который можно будет передать в mysqli_prepare.

Для подстановки имён таблиц и столбцов в строку запроса потребуется функция экранирования. В MySQL эти имена могут содержать самые разные символы и ограничиваются с помощью символа обратного апострофа. Имена могут содержать и обратный апостроф, тогда его нужно экранировать ещё одним апострофом (в документации MySQL можно почитать об этом подробнее), я надеюсь из кода станет понятно о чём речь:

class SQL {
    private static function quote($str) {
        return '`'.strtr($str, array('`' => '``')).'`';
    }
}

Теперь добавим простой метод для создания select-запроса:

public static function select($rowName, $tableName, $rowNameCondition = null) {
    $sql = 'select ' . self::quote($rowName);
    $sql .= ' from ' . self::quote($tableName);
    if ($rowNameCondition) {
        $sql .= ' where ' . self::quote($rowNameCondition) . ' = ?';
    }
    return $sql;
}

Теперь вызывая SQL::select('city', 'telegramUsers', 'chatID');, мы получим строку:

select `city` from `telegramUsers` where `chatID` = ?

Осталось написать код, который передаст запрос в базу данных:

class DB {
    private $connection;
    public function __construct($host, $username, $password, $defaultDb) {
        $this->connection = new mysqli($host, $username, $passwordm $defaultDb);
    }
    public function select($rowName, $tableName, $rowNameCondition = null, $whereCondition = null) {
        $sql = SQL::select($rowName, $tableName, $rowNameCondition);
        $query = $this->connection->prepare($sql);
        if ($rowNameCondition) {
            $query->bind_param('s', $whereCondition);
        }
        $query->execute();
        $result = $query->get_result();
        return $result->fetch_all(); // доступно только с расширением mysqlnd
    }
}

Используйте!

$db = new DB("localhost", "blabla", "arararar", "blabla");
$row = $db->select("city", "telegramUsers", "chatID", $chatID);
foreach ($rows as $row) {
    var_dump($row);
}

Развивая этот код обратите внимание вот на что:

  1. Я использовал параметры конструктора DB, чтобы не зашивать их внутрь. Это позволит использовать класс для разных баз.
  2. Я не использовал $this->query, потому что переменная не нужна за пределами метода.
  3. Я использовал значения по умолчанию, что бывает удобно.
  4. Вы упустили, что метод fetch_all -- метод класса mysqli_result.
  5. Обратите внимание, что существуют готовые решения для вашей задачи, возможно вам следует использовать их. Если вы не знакомы с менеджером зависимостей composer, обязательно познакомьтесь.
READ ALSO
Smarty, как скопировать шаблон?

Smarty, как скопировать шаблон?

Есть шаблон в папке templates/imp/blocks/contacts_datatpl, который подключается на странице контактов

261
PHP MongoDB импорт файл больше чем 16 mb

PHP MongoDB импорт файл больше чем 16 mb

Привет всем! У меня проблема с MongoDB точнее не могу импортировать js файл с размером 55 mbИскал везде но не нашел конкретную решению

263
Собрать массив из уже имеющего

Собрать массив из уже имеющего

Есть такой массив

204
Не срабатывает удаление cookie через AJAX

Не срабатывает удаление cookie через AJAX

Есть файл delphp в этом файле есть такой код:

196