flapflapjack
@flapflapjack
на треть я прав

Как безопасно использовать WHERE?

Привет.

В подготовленных запросах вопроса с экранированием - нет. А вот как правильно поступить, если класс имеет примерно такой вид:

Как контролировать например $where, которое может быть не указано, или может затрагивать другие столбцы?
<?php

Class Test {
protected $where;

public function getAll()
{
$result=$this->db->prepare("SELECT * FROM table WHERE col=:col ".$this->where);
$result->execute(array("col"=>123));
return $result->fetchAll(PDO::FETCH_ASSOC);
}

public function byDate($start,$end=false)
{
$this->where.=" data BETWEEN $start AND ".($end ? $end : "NOW()");
return $this;
}

}


P.S. для DevMan:

Вместо даты можно поставить инъекцию. Как облагородить?
$class=new Test();
var_dump($class->byDate("2021-05-01 00:00:00")->getAll());
  • Вопрос задан
  • 480 просмотров
Решения вопроса 2
FanatPHP
@FanatPHP
Чебуратор тега РНР
Ты хочешь написать квери билдер. Практически всё уже написал.
Всего-то надо вместо значений подставлять плейсхолдеры, а сами значения запоминать в переменной.
Общий принцип такой:

class Test {
    protected $where;
    protected $params;

    public function getAll()
    {
        $result=$this->db->prepare("SELECT * FROM table WHERE 1=1 ".$this->where);
        $result->execute($this->params);
        return $result->fetchAll(PDO::FETCH_ASSOC);
    }

    public function byDate($start,$end=false)
    {
        if ($end) {
            $this->where .= " AND data BETWEEN :start AND :end";
            $this->params['end'] = $end;
        } else {
            $this->where .= " date >= :start";
        }
        $this->params['start'] = $start;
        return $this;
    }

    public function byCol($col)
    {
        $this->where .= " AND col = :col";
        $this->params['col'] = $col;
        return $this;
    }
}

$sql = new Test;
$data = $sql->byCol($col)->byDate($start)->getAll();


по-хорошему тут еще должны быть отдельные переменные для самого запроса, для order by, limit и так далее
Но начать можно с такого
Ответ написан
Fragster
@Fragster
помогло? отметь решением!
Если это не тестовое задание, то проще всего использовать какой-нибудь готовый query builder. А так - использовать prepared statements, динамически создавая плейсхолдеры, а потом вызывая с нужными значениями. Т.е. типа такого
$this->where .= "data BETWEEN :start AND ".($end ? ":end": "NOW()");
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы