Как реализовать массив подстановок для запроса в MySQL?

Собственно есть простейший класс-моделька для работы с БД
class Db
{
    protected $dbh;

    public function __construct()
    {
        $this->dbh = new \PDO('mysql:host=127.0.0.1;dbname=test', 'root', '');
    }

    public function execute($sql)
    {
        $sth = $this->dbh->prepare($sql);
        $res = $sth->execute();
        return $res;
    }

    public function query($sql, $class)
    {
        $sth = $this->dbh->prepare($sql);
        $res = $sth->execute();
        if (false !== $res) {
            return $sth->fetchAll(\PDO::FETCH_CLASS, $class);
        }
        return [];
    }
}


В нем интересна последняя функция. В ней нужно добавить третий аргумент в виде массива значений (насколько я понимаю, в виде ...$arr. Но у меня просто белое полотно в голове, когда я пытаюсь понять, как же это дело осуществить.

То есть, я прекрасно понимаю, что подстановка на значение заменяется таким образом
$stmt->execute([':age' => 20]);
Есть некие мысли о том, что нужно как-то формировать строку с implode, или другими функциями и с помощью цикла подставлять значения, но уже 2-й день при попытке написать хоть строку, реализующую это - все сбивается в кашу.

Заранее благодарен за любую помощь.
  • Вопрос задан
  • 500 просмотров
Решения вопроса 2
@MadridianFox
Web-программист, многостаночник
Используя ...$arr вы не получите ключи в массиве. Поэтому почему бы не сделать третий агрумент обычным агрументом, и не передавать туда массив, который без изменений будет передаваться в execute?
public function query($sql, $class, $params){ // $params = [":age"=>20]
        $sth = $this->dbh->prepare($sql);
        $res = $sth->execute($params); // <----
        if (false !== $res) {
            return $sth->fetchAll(\PDO::FETCH_CLASS, $class);
        }
        return [];
    }
Ответ написан
Комментировать
@Salim_Gareev
function db($query, $arr=false){
global $mysqli;
if(!$mysqli or isset($mysqli)){
	$mysqli = new mysqli('localhost', 'user', '???', 'db');
	$mysqli->set_charset("utf8");
}
$stmt = $mysqli->stmt_init(); 
if($stmt->prepare($query)){
	if(is_array($arr)){
	$refarg = array($stmt, str_pad('', count($arr), 's'));
		foreach ($arr as $key => $value){
			$refarg[] =& $arr[$key];
		}
	call_user_func_array("mysqli_stmt_bind_param", $refarg);
	}
	$stmt->execute();
	$qb = $stmt->get_result();
	if(preg_match("/select (.*)/i", $query)){
		if(preg_match("/(.*) limit 1/i", $query)){
			$result = mysqli_fetch_array($qb);
		}else{
			$result = array();
			while($arr = mysqli_fetch_array($qb)){
			$result[] = $arr;
			}
		}
	}elseif(preg_match("/insert (.*)/i", $query)){
		$result = $mysqli->insert_id;
	}else{
		$result = true;
	}
	$stmt->close();
}else{
	$result = false;
}
return $result;
}

Для mysqli писал когда то функцию. Возможно вам поможет в качестве примера.. В качестве 2 параметра функция принимает массив.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
FanatPHP
@FanatPHP
Чебуратор тега РНР
Внимание, а теперь правильный ответ
public function query($sql, $params = NULL){
        $sth = $this->dbh->prepare($sql);
        $sth->execute($params); // <----
        return $sth;
    }

Это базовая функция, которая должна использоваться при выполнении ВСЕХ запросов.
В том числе запросов на вставку, обновление и удаление, а также запросов, которые при всем желании не могут вернуть объект. Например
$db->query("DELETE FROM t WHERE id=?", [$id]);
$count = $db->query("SELECT count(*) FROM t")->fetchColumn();

В принципе, этого уже достаточно, поскольку для получения списка объектов можно написать
$list = $db->query("SELECT count(*) FROM t")->fetchAll(\PDO::FETCH_CLASS, "class");

Но если прям так очень хочется, то можно засунуть этот код в хелпер-функцию
public function listObjects($sql, $class, $params){
        return $this->query($sql, $params)->fetchAll(\PDO::FETCH_CLASS, $class);
    }
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы