PHP MySQL обзор GET кода

0

Я думаю, что это довольно простой вопрос. Это мой лучший выбор или есть "правильный" способ сделать это?

<?php  
    $correctOrder = array("name", "address", "phone", "starttime", "endtime", 
                    "status", "details");  

    $sql->sql1 = "SELECT * FROM 'pickups' WHERE";  

    if (isset($_GET["name"])){  
        $sql->sql2 = "'name' LIKE '%" . $_GET['name'] . "%'";  
        }  
    if (isset($_GET["address"])){  
        if (!isset($_GET['name'])){
            $q = "'address' LIKE '%" . $_GET['address'] . "%'";  
        } else {  
            $q = "AND 'address' LIKE '%" . $_GET['address'] . "%'";  
            }
        $sql->sql3 = $q;
        }
    ...
    ...

    echo implode(" ", (array) $sql);  
?>  

Итак, прямо сейчас:

?name=Jari%20Martikainen&address=some%20random%20street

а также

?name=Jari%20Martikainen&address=some%20random%20street&blah=har

а также

?address=some%20random%20street&blah=har&name=Jari%20Martikainen

все возвращают тот же результат, который желателен, но он просто не кажется очень эффективным способом делать что-то.

  • 0
    и если нет никаких параметров get - или их нет в массиве correctOrder что происходит? Это не выглядит наиболее эффективным способом выполнения действий - лучше correctOrder
  • 1
    Он широко открыт для внедрения SQL-кода, и он сломается, если не будет выполнено ни одного условия.
Показать ещё 2 комментария
Теги:
performance
oop
get

3 ответа

1
Лучший ответ

Создайте массив ($ands) из предложений AND, но без "AND".

$ands = array();
if (...)
    $ands[] = "name LIKE ...";
if (...)
    $ands[] = "address LIKE ...";
...

Затем постройте запрос:

$query = "SELECT ... WHERE " . implode(' AND ', $ands);

Я считаю, эта модель должна быть простой, чистой, и избегаю кладжи как 1=1 или удаления дополнительного AND.

1

Этот код использует массив для определения того, какие параметры ему интересны, и создает массив предложений where.

Причина, по которой я использую "name" => "name" в этом массиве ($correctOrder), заключается в том, что он позволяет $correctOrder имя параметра и имя столбца. Здесь вы должны добавить любые параметры.

Также этот код использует переменные связывания, не уверен, какой вкус базы данных имеет доступ к вашему использованию, но вы можете передать массив $data для execute чтобы связать их.

$correctOrder = array("name" => "name", "address" => "address");

$_GET = [ 'name' => 'name1', 'address' => 'add'];

$where = [];
$data = [];
foreach ( $_GET as $paramName => $param ) {
    if ( isset($correctOrder[$paramName]) ) {
        $where[] = "'{$correctOrder[$paramName]}' like ? ";
        $data[] = '%'.$param.'%';
    }
}

$sql = "SELECT * FROM 'pickups'";
if ( count($where) > 0 ){
    $sql .= " WHERE ".implode( " and ", $where);
}

echo $sql.PHP_EOL;
print_r($data);

Функция count($where) > 0 добавит только предложение where, если есть что добавить, и implode добавляет соответствующие and бит в качестве клей.

Что с тестовыми данными дает...

SELECT * FROM 'pickups' WHERE 'name' like ?  and 'address' like ? 
Array
(
    [0] => %name1%
    [1] => %add%
)

Это действительно работает только со строками, но вы можете добавить специальный код для других полей данных и добавить предложение в массив $where прежде чем попасть в финальную часть, которая строит инструкцию.

0

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

Сначала начните предложение WHERE с 1 = 1, затем выполните цикл через свой массив поисковых терминов и расширьте предложение where, если какой-либо из них включен в массив $ _GET.

Во-вторых, я бы использовал объект PDO для подключения к вашей базе данных, а затем BIND значения $ _GET. Это поможет защитить вас от SQL-инъекций/взломов.

Ниже я просматриваю поисковые запросы, сохраняя их в массив с именем $ sqlParams, если в массиве $ _GET есть что-то. Затем я просматриваю $ sqlParams и привязываю значения.

// connect to database via PDO
try {
    $db = new PDO($dsn, $username, $password, $options);    
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

$correctOrder = array("name", "address", "phone", "starttime", "endtime", 
                "status", "details");  

$sql = "SELECT * FROM 'pickups' WHERE 1=1 ";  

// check the $_GET array, build SQL, remember values in $sqlParams
$sqlParams = [];
foreach ($correctOrder as $key) {
    if (isset($_GET[$key])) {
        $sql .= "and '$key' LIKE :$key ";
        $sqlParams[":$key"] = "%{$_GET[$key]}%";
    }
}


// bind values from $sqlParams into SQL statement
$stmt = $db->prepare($sql);
foreach ($sqlParams as $key => &$value) {
    $stmt->bindParam($key, $value);
}

// execute SQL statement, catching exception
try {
    $stmt->execute();
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

// cycle through results and do stuff
while ($row = $stmt->fetch()) {
    print_r($row);
}
  • 0
    Теперь я понимаю, что два приведенных ниже ответа лучше, чем этот, потому что они избегают трюка 1 = 1, а NigelRen также готовит данные для более эффективного связывания.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню