2017-02-09 2 views
1

Я довольно новичок в PDO, и я пытаюсь изменить свой структурно-структурированный PHP-код MySQLi на объектно-ориентированную структуру PDO. Я просто изучаю подготовку, выполнение, bindParam/bindValue и т. П. До степени успеха.PDO-подготовка с подзапросами

Мой вопрос: как подготовить запрос, когда представленное пользователем значение находится в подзапросе этого запроса?

У меня есть переменная, используемая как подзапрос в php (где $ playerOne, $ playerTwo - значения, представленные пользователем).

$sqlPlayerOne = "(SELECT * FROM players WHERE Player_name = $playerOne)"; 
$sqlPlayerTwo = "(SELECT * FROM players WHERE Player_name = $playerTwo)"; 

Это он, чтобы получить все записи для этих игроков. В качестве примера я могу сравнить, какие игры они играли друг против друга, например.

$sqlWith = "SELECT * FROM $sqlPlayerOne s1 
WHERE EXISTS (SELECT * FROM $sqlPlayerTwo s2 WHERE s1.Team_name = s2.Opposing_team) 

Примечание: SELECT * просто используется, чтобы сделать его более удобным для чтения здесь.

Достаточно ли сделать $pdoWith = $db->prepare($sqlWith), или я должен готовить $sqlPlayerOne, так как у этого есть представленная пользователем стоимость?

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

EDIT: Извините за отсутствие ясности. Это был раздел моего кода, прежде чем я его изменил, так как я не был уверен, как мне его изменить. Кажется, я просто должен сделать это подобно тому, как @JC FOREST отметил:

$dsn = "mysql:host=localhost;dbname=database"; 
$username = "user"; 
$password = "pass"; 
$db = new PDO($dsn, $username, $password); 

$stmt = $db->prepare("SELECT * FROM (SELECT * FROM players WHERE Player_name = :playerone) 
s1 WHERE EXISTS (SELECT * FROM (SELECT * FROM players WHERE Player_name = :playertwo) s2 
WHERE s1.Team_name = s2.Opposing_team)"); 

$stmt->bindValue(':playerone', $playerOne); 
$stmt->bindValue(':playertwo, $playerTwo); 
$stmt->execute(); 
+0

Что вы пытаетесь сделать, я ничего не понимаю. То, что вы делаете, недопустимо. Вам нужно быть в курсе того, что вы хотите сделать с этими тремя запросами, и вам просто нужно подготовить 1 запрос, даже если у него есть подзапросы – 131

+1

Вы понимаете, как действительно работает документ, подготовленный PDO? У вас есть идея, что такое ** placeholder **? Ваша переменная $ sqlPlayerOne не показывает никаких признаков использования с «bindParam/bindValue и т. П.» –

+0

Это запуталось. Вы отредактировали вопрос, чтобы задать что-то совсем другое, затем приняли ответ, который не объясняет, что не так с исходным кодом, и не объясняет синтаксис PDO. Надеюсь, вы поняли основы подготовленных заявлений, а не просто слепо вставляли код в свой проект ;-) –

ответ

1

Вам необходимо привязать $ playerOne, $ playerTwo к вашему подготовленному оператору в качестве параметров.http://php.net/manual/en/mysqli.prepare.php

$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'world'); 

/* check connection */ 
if (mysqli_connect_errno()) { 
    printf("Connect failed: %s\n", mysqli_connect_error()); 
    exit(); 
} 

/* create a prepared statement */ 
$stmt = $mysqli->prepare("SELECT * FROM (SELECT * FROM players WHERE Player_name = ?) s1 
WHERE EXISTS (SELECT * FROM (SELECT * FROM players WHERE Player_name = ?) s2 WHERE s1.Team_name = s2.Opposing_team)") 

    /* bind parameters for markers */ 
    $stmt->bind_param("ss", $playerOne, $playerTwo); 

    /* execute query */ 
    $stmt->execute(); 
0

Общий механизм подготовленных заявлений одинаковы во всех расширениях базы данных, которые поддерживают его:

  • Replace номер или строковые литералы (и я имею в виду это, литералы, а не случайные фрагменты кода) внутри SQL с владельцами мест, либо на основе позиции ?, либо по имени :username (не смешивайте, выберите один)
  • Подготовьте запрос, позвонив соответствующая функция, которая получает SQL как параметр
  • Выполнить подготовленный запрос, вызвав соответствующую функцию (ы), которые принимают значения, как paremeter

Так что, если вы делаете это правильно в MySQLi, переход к PDO не потребует изменений в вашей логике. Однако ваши образцы кода предлагают . Вы не используете готовые заявления вообще: нет держателей мест, нет данных в отдельном канале ... Я вижу variable interpolation in double quoted strings, но это функция PHP, а не функция SQL. Таким образом, совершенно бесполезно разделять код и данные и предотвращать инъекцию SQL.

Я подозреваю, что корень недоразумений не совсем уверен в том, как взаимодействуют PHP и SQL. Ответ заключается в том, что они этого не делают: они полностью разные компьютерные языки, и они выполняются совершенно разными программами. Единственное отношение состоит в том, что вы используете первое для генерации последнего. Независимо от того, что вы делаете, в конце вы просто отправляете строку (т. Е. Простой текст) на сервер базы данных. Как вы создаете этот текст, не имеет значения, потому что строки не имеют памяти.

Смежные вопросы