Làm cách nào để có thể sử dụng đúng đối tượng PDO cho truy vấn SELECT được tham số hóa


85

Tôi đã thử làm theo hướng dẫn PHP.net để thực hiện SELECTtruy vấn nhưng tôi không chắc cách tốt nhất để thực hiện việc này.

Tôi muốn sử dụng một SELECTtruy vấn được tham số hóa , nếu có thể, để trả về IDmột bảng trong đó nametrường khớp với tham số. Điều này sẽ trả về một IDvì nó sẽ là duy nhất.

Sau đó, tôi muốn sử dụng nó IDcho một INSERTbảng khác, vì vậy tôi sẽ cần xác định xem nó có thành công hay không.

Tôi cũng đọc rằng bạn có thể chuẩn bị các truy vấn để sử dụng lại nhưng tôi không chắc điều này sẽ giúp ích như thế nào.

Câu trả lời:


158

Bạn chọn dữ liệu như sau:

$db = new PDO("...");
$statement = $db->prepare("select id from some_table where name = :name");
$statement->execute(array(':name' => "Jimbo"));
$row = $statement->fetch(); // Use fetchAll() if you want all results, or just iterate over the statement, since it implements Iterator

Bạn chèn theo cách tương tự:

$statement = $db->prepare("insert into some_other_table (some_id) values (:some_id)");
$statement->execute(array(':some_id' => $row['id']));

Tôi khuyên bạn nên cấu hình PDO để ném các ngoại lệ khi có lỗi. Sau đó, bạn sẽ nhận được PDOExceptionnếu bất kỳ truy vấn nào không thành công - Không cần kiểm tra rõ ràng. Để bật ngoại lệ, hãy gọi điều này ngay sau khi bạn đã tạo $dbđối tượng:

$db = new PDO("...");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Tôi cho rằng bạn có nghĩa là PDOStatement nơi bạn có PDO mới (...), phải không?
Joe Phillips

1
Không. PDO là lớp kết nối (Có lẽ nên được đặt tên là PdoConnection). Kết nối có thể tạo PdoStatements. Bạn gọi setAttribute () trên đối tượng kết nối - không phải các câu lệnh riêng lẻ. (Ngoài ra, bạn có thể vượt qua nó để các nhà xây dựng)
troelskn

1
điều này có thể hữu ích:$db = new PDO('mysql:dbname=your_database;host=localhost', 'junior', '444');
Junior Mayhé

2
Đối với dòng $statement->execute(array(':name' => "Jimbo"));, bạn có thể giải thích phần Jimbo?
muttley91 29/12/12

1
@rar Trên dòng trước, truy vấn được bắt đầu bằng trình giữ chỗ :name. Việc gọi executeở đây được thực hiện với một mảng liên kết các cặp giá trị -> trình giữ chỗ. Vì vậy, trong trường hợp này, :nametrình giữ chỗ sẽ được thay thế bằng chuỗi Jimbo. Lưu ý rằng nó không chỉ đơn giản là thực hiện thay thế chuỗi, vì giá trị được thoát hoặc được gửi qua một kênh khác với truy vấn thực tế, do đó ngăn chặn bất kỳ loại tấn công chèn ép nào.
troelskn 29/12/12

16

Tôi đã làm việc với PDO gần đây và câu trả lời ở trên là hoàn toàn đúng, nhưng tôi chỉ muốn ghi lại rằng những điều sau đây cũng hoạt động.

$nametosearch = "Tobias";
$conn = new PDO("server", "username", "password");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sth = $conn->prepare("SELECT `id` from `tablename` WHERE `name` = :name");
$sth->bindParam(':name', $nametosearch);
// Or sth->bindParam(':name', $_POST['namefromform']); depending on application
$sth->execute();

16
Không, không phải vậy, vì bạn chưa chọn cơ sở dữ liệu nào để sử dụng.
Rápli András

3
Điều đó thực sự phải nằm trong chuỗi "máy chủ", thực sự phải là một DSN ở dạng "{driver}: dbname = {db_name}; host = {server}" thay thế các giá trị dấu ngoặc nhọn bằng bất kỳ kết nối nào của bạn cần
thorne51

12

Bạn có thể sử dụng bindParamhoặc bindValuecác phương pháp để giúp chuẩn bị báo cáo của mình. Nó làm cho mọi thứ rõ ràng hơn ngay từ cái nhìn đầu tiên thay vì làm được $check->execute(array(':name' => $name));Đặc biệt nếu bạn đang ràng buộc nhiều giá trị / biến.

Kiểm tra ví dụ rõ ràng, dễ đọc bên dưới:

$q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname LIMIT 1");
$q->bindValue(':forename', 'Joe');
$q->bindValue(':surname',  'Bloggs');
$q->execute();

if ($q->rowCount() > 0){
    $check = $q->fetch(PDO::FETCH_ASSOC);
    $row_id = $check['id'];
    // do something
}

Nếu bạn đang mong đợi nhiều hàng, hãy xóa LIMIT 1và thay đổi phương thức tìm nạp thành fetchAll:

$q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname");// removed limit 1
$q->bindValue(':forename', 'Joe');
$q->bindValue(':surname',  'Bloggs');
$q->execute();

if ($q->rowCount() > 0){
    $check = $q->fetchAll(PDO::FETCH_ASSOC);
    //$check will now hold an array of returned rows. 
    //let's say we need the second result, i.e. index of 1
    $row_id = $check[1]['id']; 
    // do something
}

Không chắc. Có vẻ như một câu trả lời hợp lệ cho tôi. Tôi nghĩ rằng nó sẽ có lợi nếu sử dụng 'myname' thay vì 'name' và cũng có thể sử dụng nhiều tham số thay vì chỉ một.
Joe Phillips

@GillianLoWong Làm được $check = $q->fetch(PDO::FETCH_ASSOC); if (!empty($check)){ $row_id = $check['id']; // do something }gì?
Abdul

1
Xin chào @abdul, tôi đã thay thế kiểm tra đếm / trống trên mảng. Nó được cho là để xem nếu bất kỳ kết quả được trả lại. Nhưng pdo cũng có một hàm gọi là rowCount () cho phép bạn kiểm tra xem có hàng nào bị ảnh hưởng / tìm nạp hay không. Không có ích gì khi tìm nạp dữ liệu nếu bạn thậm chí không biết liệu có hàng nào được chọn hay không, vì vậy tôi đã chuyển câu lệnh tìm nạp vào câu lệnh if rowCount (). :)
Gilly

@Gillian La Wong cảm ơn bạn đã truy vấn rõ ràng về bindValue cho truy vấn nhiều where. lưu dự án của tôi.
php-coder

6

Một câu trả lời hoàn chỉnh nhỏ ở đây với tất cả đã sẵn sàng để sử dụng:

    $sql = "SELECT `username` FROM `users` WHERE `id` = :id";
    $q = $dbh->prepare($sql);
    $q->execute(array(':id' => "4"));
    $done= $q->fetch();

 echo $done[0];

Đây $dbhlà trình kết nối db PDO và dựa trên idbảng từ userschúng tôi đã usernamesử dụngfetch();

Tôi hy vọng điều này sẽ giúp ai đó, Thưởng thức!


Hoặc sử dụng fetchColumn()để tránh những điều [0]cần thiết. Ngoài ra, hãy nhớ sử dụng LIMIT 1trong SQL.
rybo111

3

Phương pháp 1: SỬ DỤNG phương pháp truy vấn PDO

$stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);

Bắt số lượng hàng

$stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

Phương pháp 2: Tuyên bố với tham số

$stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
$stmt->execute(array($name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Phương pháp 3: Tham số ràng buộc

$stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

**bind with named parameters**
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

or
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
$stmt->execute(array(':name' => $name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Muốn biết thêm hãy xem liên kết này


4
Vui lòng loại bỏ Phương pháp 1. Nó cho phép tiêm mysql.
Tomahock

-2

Nếu bạn đang sử dụng mã hóa nội tuyến trong một trang duy nhất và không sử dụng, rất tiếc, hãy đi với ví dụ đầy đủ này, nó chắc chắn sẽ giúp

//connect to the db
$dbh = new PDO('mysql:host=localhost;dbname=mydb', dbuser, dbpw); 

//build the query
$query="SELECT field1, field2
FROM ubertable
WHERE field1 > 6969";

//execute the query
$data = $dbh->query($query);
//convert result resource to array
$result = $data->fetchAll(PDO::FETCH_ASSOC);

//view the entire array (for testing)
print_r($result);

//display array elements
foreach($result as $output) {
echo output[field1] . " " . output[field1] . "<br />";
}

Mặc dù đoạn mã này có thể giải quyết vấn đề, nhưng nó không giải thích tại sao hoặc cách nó trả lời câu hỏi. Vui lòng bao gồm giải thích cho mã của bạn , vì điều đó thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn. Người gắn cờ / người đánh giá: Đối với các câu trả lời chỉ có mã, chẳng hạn như câu trả lời này, hãy phản đối, đừng xóa!
Scott Weldon

Vì vậy, những gì tôi nên xóa nó tự của tôi
Shiv Singh

Không, hoàn toàn ngược lại. Tôi đã xem bài đăng này trong Hàng đợi Bài đăng Chất lượng thấp , và vì vậy phần sau của nhận xét của tôi là khuyên mọi người không bỏ phiếu để xóa. (Đề xuất phản đối thay vào đó nhằm mục đích nhắc nhở phản đối tạm thời, sẽ bị xóa sau khi bài đăng của bạn được chỉnh sửa.) Như đã đề cập trong nhận xét trước của tôi, sẽ tốt hơn nếu bạn thêm giải thích lý do tại sao bạn đề xuất mã mà bạn đã làm . Ngoài ra, câu hỏi này hỏi về các truy vấn được tham số hóa, nhưng có field > 6969vẻ được mã hóa cứng hơn là được tham số hóa.
Scott Weldon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.