Hiệu suất pdo so với mysqli
Đã có rất nhiều hướng dẫn về PDO, nhưng thật không may, hầu hết chúng không giải thích được lợi ích thực sự của PDO, hoặc thậm chí khuyến khích các thực hành khá tồi. Hai ngoại lệ duy nhất là phptherightway. com và hashphp. org, nhưng họ bỏ lỡ rất nhiều thông tin quan trọng. Kết quả là, một nửa số tính năng của PDO vẫn chưa được biết đến và hầu như không bao giờ được sử dụng bởi các nhà phát triển PHP, những người luôn cố gắng phát minh lại bánh xe đã tồn tại trong PDO Show
Không giống như những hướng dẫn đó, hướng dẫn này được viết bởi một người đã sử dụng PDO trong nhiều năm, tìm hiểu kỹ về nó và trả lời hàng nghìn câu hỏi trên Stack Overflow (người mang huy hiệu PDO vàng duy nhất). Theo sứ mệnh của trang web này, bài viết này sẽ bác bỏ những ảo tưởng và thực hành xấu khác nhau, đồng thời chỉ ra cách đúng đắn Mặc dù hướng dẫn này dựa trên trình điều khiển mysql, nhưng nói chung, thông tin này có thể áp dụng cho bất kỳ trình điều khiển nào được hỗ trợ Tại sao PDO?điều đầu tiên đầu tiên. Tại sao lại là PDO? PDO là Lớp trừu tượng truy cập cơ sở dữ liệu. Sự trừu tượng, tuy nhiên, là gấp đôi. một cái được biết đến rộng rãi nhưng ít quan trọng hơn, trong khi một cái khác ít người biết đến nhưng quan trọng nhất Mọi người đều biết rằng PDO cung cấp giao diện hợp nhất để truy cập nhiều cơ sở dữ liệu khác nhau. Mặc dù bản thân tính năng này rất tuyệt vời, nhưng nó không tạo ra vấn đề lớn đối với ứng dụng cụ thể, nơi chỉ có một phụ trợ cơ sở dữ liệu được sử dụng. Và, bất chấp một số tin đồn, không thể chuyển đổi phụ trợ cơ sở dữ liệu bằng cách thay đổi một dòng trong cấu hình PDO - do các hương vị SQL khác nhau (để làm như vậy, người ta cần sử dụng ngôn ngữ truy vấn trung bình như DQL). Do đó, đối với nhà phát triển LAMP bình thường, điểm này không đáng kể và đối với anh ta, PDO chỉ là một phiên bản phức tạp hơn của hàm 2 quen thuộc. Tuy nhiên, không phải vậy; PDO tóm tắt không chỉ API cơ sở dữ liệu mà còn cả các hoạt động cơ bản phải lặp lại hàng trăm lần trong mọi ứng dụng, khiến mã của bạn cực kỳ ƯỚT. Không giống như mysql và mysqli, cả hai đều là API trần cấp thấp không nhằm mục đích sử dụng trực tiếp (mà chỉ làm vật liệu xây dựng cho một số lớp trừu tượng cấp cao hơn), 3 đã là một sự trừu tượng như vậy rồi. Mặc dù vẫn chưa hoàn thiện, nhưng ít nhất có thể sử dụng đượcNhững lợi ích PDO thực sự là
Lưu ý rằng mặc dù PDO là trình điều khiển db gốc tốt nhất, nhưng đối với ứng dụng web hiện đại, hãy cân nhắc sử dụng ORM với Trình tạo truy vấn hoặc bất kỳ thư viện trừu tượng cấp cao nào khác, chỉ thỉnh thoảng có dự phòng cho vanilla PDO. Các ORM tốt là Doctrine, Eloquent, RedBean và Yii. thực tế tăng cường. hào quang. SQL là một ví dụ điển hình về trình bao bọc PDO với nhiều tính năng bổ sung Dù bằng cách nào, thật tốt khi biết các công cụ cơ bản trước. Vì vậy, chúng ta hãy bắt đầu Đang kết nối. DSNPDO có một phương thức kết nối ưa thích được gọi là DSN. Mặc dù vậy, không có gì phức tạp - thay vì một danh sách tùy chọn đơn giản và đơn giản, PDO yêu cầu bạn nhập các chỉ thị cấu hình khác nhau ở ba vị trí khác nhau
trong đó DSN là một chuỗi được phân cách bằng dấu chấm phẩy, bao gồm các cặp 2, bắt đầu từ tên trình điều khiển và dấu hai chấm 1Lưu ý rằng điều quan trọng là phải tuân theo định dạng thích hợp - không được sử dụng dấu cách hoặc dấu ngoặc kép hoặc cách trang trí khác trong DSN mà chỉ được sử dụng các tham số, giá trị và dấu phân cách, như được trình bày trong sách hướng dẫn Đây là một ví dụ cho mysql 2Với tất cả các biến đã nói ở trên được đặt đúng cách, chúng ta sẽ có phiên bản PDO thích hợp trong biến 3Lưu ý quan trọng cho người dùng tiện ích mở rộng mysql muộn
Bạn có thể tìm thêm chi tiết về Mysql trong chương tương ứng, Kết nối với MySQL Chạy truy vấn. PDO. truy vấn()Có hai cách để chạy truy vấn trong PDO. Nếu không có biến nào sẽ được sử dụng trong truy vấn, bạn có thể sử dụng PDO. phương thức truy vấn (). Nó sẽ chạy truy vấn của bạn và trả về đối tượng đặc biệt của lớp PDOStatement có thể được so sánh gần đúng với tài nguyên, được trả về bởi 00, đặc biệt là theo cách bạn có thể lấy các hàng thực tế từ nó 1Ngoài ra, phương thức 7 cho phép chúng ta sử dụng một chuỗi phương thức gọn gàng cho các truy vấn CHỌN, sẽ được hiển thị bên dướibáo cáo chuẩn bị. Bảo vệ khỏi việc tiêm SQLĐây là lý do chính và quan trọng duy nhất khiến bạn bị tước chức năng 00 yêu quý của mình và bị ném vào thế giới khắc nghiệt của Đối tượng dữ liệu. PDO đã chuẩn bị sẵn các câu lệnh hỗ trợ sẵn có. Câu lệnh đã chuẩn bị là cách thích hợp duy nhất để chạy truy vấn, nếu bất kỳ biến nào sẽ được sử dụng trong đó. Lý do tại sao nó lại quan trọng như vậy được giải thích chi tiết trong Hướng dẫn phòng chống SQL injection của The Hitchhiker'sVì vậy, đối với mọi truy vấn bạn chạy, nếu ít nhất một biến sẽ được sử dụng, bạn phải thay thế nó bằng một trình giữ chỗ, sau đó chuẩn bị truy vấn của bạn rồi thực hiện nó, chuyển các biến riêng biệt Tóm lại, nó không khó như vẻ ngoài của nó. Trong hầu hết các trường hợp, bạn chỉ cần hai chức năng - chuẩn bị() và thực thi() Trước hết, bạn phải thay đổi truy vấn của mình, thêm các trình giữ chỗ thay cho các biến. Nói, một mã như thế này 4sẽ trở thành 5hoặc
Lưu ý rằng PDO hỗ trợ các trình giữ chỗ vị trí ( 03) và được đặt tên ( 04), cái sau luôn bắt đầu từ dấu hai chấm và chỉ có thể được viết bằng các chữ cái, chữ số và dấu gạch dưới. Cũng lưu ý rằng không có trích dẫn nào được sử dụng xung quanh trình giữ chỗCó một truy vấn với trình giữ chỗ, bạn phải chuẩn bị nó, sử dụng phương thức 05. Hàm này sẽ trả về cùng một đối tượng 06 mà chúng ta đã nói ở trên, nhưng không có bất kỳ dữ liệu nào được đính kèm với nóCuối cùng, để thực thi truy vấn, bạn phải chạy phương thức 07 của đối tượng này, truyền các biến vào đó, ở dạng mảng. Và sau đó, bạn sẽ có thể lấy dữ liệu kết quả ra khỏi câu lệnh (nếu có)________số 8Như bạn có thể thấy, đối với các trình giữ chỗ vị trí, bạn phải cung cấp một mảng thông thường với các giá trị, trong khi đối với các trình giữ chỗ được đặt tên, nó phải là một mảng kết hợp, trong đó các khóa phải khớp với các tên trình giữ chỗ trong truy vấn. Bạn không thể kết hợp các trình giữ chỗ theo vị trí và được đặt tên trong cùng một truy vấn Xin lưu ý rằng các trình giữ chỗ theo vị trí cho phép bạn viết mã ngắn hơn, nhưng nhạy cảm với thứ tự của các đối số (phải giống hệt như thứ tự của các trình giữ chỗ tương ứng trong truy vấn). Mặc dù các trình giữ chỗ được đặt tên làm cho mã của bạn dài dòng hơn, nhưng chúng cho phép thứ tự ràng buộc ngẫu nhiên Cũng lưu ý rằng mặc dù ảo tưởng phổ biến, nhưng không cần " 08" trong các phímSau khi thực hiện, bạn có thể bắt đầu lấy dữ liệu của mình, sử dụng tất cả các phương pháp được hỗ trợ, như được mô tả trong bài viết này Nhiều ví dụ có thể được tìm thấy trong bài viết tương ứng phương pháp ràng buộcTruyền dữ liệu vào 07 (như được hiển thị ở trên) nên được coi là phương pháp mặc định và thuận tiện nhất. Khi phương thức này được sử dụng, tất cả các giá trị sẽ được liên kết dưới dạng chuỗi (lưu giá trị 50, giá trị này sẽ được gửi đến truy vấn như hiện tại, tôi. e. như SQL 50), nhưng hầu hết thời gian đều ổn và sẽ không gây ra vấn đề gìTuy nhiên, đôi khi tốt hơn là đặt loại dữ liệu một cách rõ ràng. Các trường hợp có thể xảy ra là
Trong trường hợp như vậy, ràng buộc rõ ràng phải được sử dụng, mà bạn có thể lựa chọn hai hàm, bindValue() và bindParam(). Cái trước phải được ưu tiên hơn, bởi vì, không giống như 54, nó không có tác dụng phụ để giải quyếtTruy vấn các phần bạn có thể liên kếtĐiều rất quan trọng là phải hiểu phần truy vấn nào bạn có thể liên kết bằng cách sử dụng câu lệnh đã chuẩn bị và phần nào bạn không thể. Trên thực tế, danh sách này quá ngắn. chỉ chuỗi và chữ số có thể được ràng buộc. Vì vậy, bạn có thể nói rằng miễn là dữ liệu của bạn có thể được biểu diễn trong truy vấn dưới dạng số hoặc chuỗi ký tự được trích dẫn - nó có thể bị ràng buộc. Đối với tất cả các trường hợp khác, bạn hoàn toàn không thể sử dụng các câu lệnh đã chuẩn bị PDO. không phải là mã định danh hoặc danh sách được phân tách bằng dấu phẩy hoặc một phần của chuỗi ký tự được trích dẫn hoặc bất kỳ phần truy vấn tùy ý nào khác không thể bị ràng buộc bằng cách sử dụng câu lệnh đã chuẩn bị Cách giải quyết cho các trường hợp sử dụng thường xuyên nhất có thể được tìm thấy trong phần tương ứng của bài viết báo cáo chuẩn bị. Nhiều lần thực hiệnĐôi khi bạn có thể sử dụng các câu lệnh đã chuẩn bị để thực hiện nhiều truy vấn đã chuẩn bị. Nó nhanh hơn một chút so với việc thực hiện lặp đi lặp lại cùng một truy vấn, vì nó chỉ phân tích cú pháp truy vấn một lần. Tính năng này sẽ hữu ích hơn nếu có thể thực thi một câu lệnh được chuẩn bị trong một phiên bản PHP khác. Nhưng than ôi - nó không phải là. Vì vậy, bạn bị giới hạn chỉ lặp lại cùng một truy vấn trong cùng một phiên bản, điều này hiếm khi cần thiết trong các tập lệnh PHP thông thường và điều này hạn chế việc sử dụng tính năng này đối với các lần chèn hoặc cập nhật lặp lại 0Lưu ý rằng tính năng này được đánh giá cao một chút. Nó không chỉ hiếm khi được đề cập đến, mà hiệu suất đạt được cũng không lớn - việc phân tích cú pháp truy vấn hiện nay thực sự nhanh chóng Lưu ý rằng bạn chỉ có thể nhận được lợi thế này khi tắt chế độ mô phỏng Chạy các câu lệnh SELECT INSERT, UPDATE hoặc DELETEcố lên mọi người. Hoàn toàn không có gì đặc biệt trong các truy vấn này. Đối với PDO, tất cả đều giống nhau. Không quan trọng bạn đang chạy truy vấn nào Giống như đã trình bày ở trên, điều bạn cần là chuẩn bị một truy vấn với các trình giữ chỗ, sau đó thực hiện truy vấn đó, gửi các biến một cách riêng biệt. Đối với truy vấn 55 và 56, quy trình về cơ bản là giống nhau. Sự khác biệt duy nhất là (vì các truy vấn DML không trả về bất kỳ dữ liệu nào), bạn có thể sử dụng chuỗi phương thức và do đó gọi ngay 07 cùng với 58 5Tuy nhiên, nếu bạn muốn lấy số lượng hàng bị ảnh hưởng, mã sẽ phải giống nhau ba dòng 6Nhiều ví dụ có thể được tìm thấy trong bài viết tương ứng Lấy dữ liệu ra khỏi câu lệnh. cho mỗi()Cách cơ bản và trực tiếp nhất để lấy nhiều hàng từ một câu lệnh là vòng lặp 59. Nhờ giao diện Traversable, có thể lặp lại 06 bằng cách sử dụng toán tử 59 20Lưu ý rằng phương pháp này thân thiện với bộ nhớ, vì nó không tải tất cả các hàng kết quả trong bộ nhớ mà cung cấp từng hàng một (mặc dù hãy ghi nhớ vấn đề này) Lấy dữ liệu ra khỏi câu lệnh. tìm về()Chúng ta đã thấy chức năng này rồi, nhưng hãy xem xét kỹ hơn. Nó tìm nạp một hàng từ cơ sở dữ liệu và di chuyển con trỏ bên trong trong tập kết quả, do đó, các cuộc gọi tiếp theo đến hàm này sẽ trả về tất cả các hàng kết quả từng cái một. Điều này làm cho phương pháp này tương tự như 62 nhưng nó hoạt động theo một cách hơi khác. thay vì nhiều chức năng riêng biệt ( 63, 64, v.v.), chỉ có một, nhưng hành vi của nó có thể được thay đổi bởi một tham số. Có nhiều chế độ tìm nạp trong PDO và chúng ta sẽ thảo luận về chúng sau, nhưng đây là một số chế độ dành cho người mới bắt đầu
Từ những điều trên, bạn có thể biết rằng chức năng này phải được sử dụng trong hai trường hợp
Một chế độ hữu ích khác là 200, chế độ này có thể tạo đối tượng của một lớp cụ thể 22sẽ tạo ra một mảng chứa đầy các đối tượng của lớp Tin tức, thiết lập các thuộc tính của lớp từ các giá trị được trả về. Lưu ý rằng trong chế độ này
Lưu ý rằng chế độ mặc định là 67, nhưng bạn có thể thay đổi chế độ này bằng cách sử dụng tùy chọn cấu hình 204 như minh họa trong ví dụ kết nối. Do đó, một khi được đặt, nó có thể được bỏ qua hầu hết thời gianloại trả lạiChỉ khi PDO được xây dựng dựa trên mysqlnd và tắt chế độ mô phỏng, thì PDO sẽ trả về các giá trị 205 và 206 với các loại tương ứng. Giả sử, nếu chúng ta tạo một bảng 23Và sau đó truy vấn nó từ PDO dựa trên mysqlnd khi tắt mô phỏng, đầu ra sẽ là 24Nếu không, hành vi quen thuộc của 62 sẽ được tuân theo - tất cả các giá trị được trả về dưới dạng chuỗi chỉ có 50 được trả về là 50Nếu vì lý do nào đó bạn không thích hành vi này và chỉ thích kiểu cũ với chuỗi và NULL, thì bạn có thể sử dụng tùy chọn cấu hình sau để ghi đè lên nó 25Lưu ý rằng đối với loại 210, chuỗi luôn được trả về, do bản chất của loại này nhằm giữ lại giá trị chính xác, không giống như các loại FLOAT và DOUBLE cố ý không chính xácLấy dữ liệu ra khỏi câu lệnh. tìm nạpColumn()Một hàm trợ giúp gọn gàng trả về giá trị của một trường duy nhất của hàng được trả về. Rất tiện dụng khi chúng tôi chỉ chọn một trường 26Lấy dữ liệu ra khỏi câu lệnh ở hàng chục định dạng khác nhau. tìm nạp tất cả ()Đó là chức năng thú vị nhất, với hầu hết các tính năng đáng kinh ngạc. Chủ yếu là nhờ sự tồn tại của nó, người ta có thể gọi PDO là trình bao bọc, vì chức năng này có thể tự động hóa nhiều thao tác được thực hiện thủ công 211 trả về một mảng bao gồm tất cả các hàng được truy vấn trả về. Từ thực tế này, chúng ta có thể đưa ra hai kết luận
Bạn sẽ ngạc nhiên về số lượng định dạng khác nhau mà hàm này có thể trả về dữ liệu (và một người dùng PHP trung bình biết rất ít về chúng), tất cả được kiểm soát bởi các biến 212. một số trong số họ làLấy một mảng đơn giảnTheo mặc định, hàm này sẽ chỉ trả về mảng liệt kê đơn giản bao gồm tất cả các hàng được trả về. Các hằng số định dạng hàng, chẳng hạn như 65, 66, 68, v.v. có thể thay đổi định dạng hàng 27Lấy một cộtThường rất thuận tiện để lấy mảng một chiều đơn giản ra khỏi truy vấn, nếu chỉ một cột trong số nhiều hàng được tìm nạp. của bạn đây 28Nhận các cặp khóa-giá trịĐịnh dạng này cũng cực kỳ hữu ích, khi chúng ta cần lấy cùng một cột, nhưng được lập chỉ mục không phải theo số theo thứ tự mà theo trường khác. Đây là hằng số 216 29Lưu ý rằng bạn chỉ phải chọn hai cột cho chế độ này, cột đầu tiên phải là duy nhất Bắt các hàng được lập chỉ mục theo trường duy nhấtTương tự như trên, nhưng không nhận được một cột mà là hàng đầy đủ, chưa được lập chỉ mục bởi một trường duy nhất, nhờ hằng số 217 10Lưu ý rằng cột đầu tiên được chọn phải là duy nhất (trong truy vấn này, giả định rằng cột đầu tiên là id, nhưng để chắc chắn hơn, hãy liệt kê nó một cách rõ ràng) Nhận các hàng được nhóm theo một số trường 218 sẽ nhóm các hàng thành một mảng lồng nhau, trong đó các chỉ mục sẽ là các giá trị duy nhất từ cột đầu tiên và các giá trị sẽ là các mảng tương tự như các mảng được trả về bởi 219 thông thường. Ví dụ, đoạn mã sau sẽ tách nam khỏi nữ và đặt chúng vào các mảng khác nhau 11Vì vậy, đây là giải pháp lý tưởng cho nhu cầu phổ biến như "nhóm sự kiện theo ngày" hoặc "nhóm hàng hóa theo danh mục". Một số trường hợp sử dụng thực tế Các chế độ khác Tất nhiên, có một 220 dành cho những người hâm mộ lập trình chức năngNhiều chế độ sắp ra mắt xử lý lỗi. ngoại lệMặc dù có một số chế độ xử lý lỗi trong PDO, chế độ thích hợp duy nhất là 221. Vì vậy, người ta phải luôn đặt nó theo cách này, bằng cách thêm dòng này sau khi tạo phiên bản PDO, 12hoặc như một tùy chọn kết nối, như minh họa trong ví dụ trên. Và đây là tất cả những gì bạn cần để báo cáo lỗi cơ bản Báo cáo lỗi PDOTL;DR. 222 để báo cáo lỗi PDO. Chỉ bắt một ngoại lệ nếu bạn có một tình huống xử lý khác ngoài việc chỉ báo cáo nó. Nếu không, hãy để nó nổi lên thành một trình xử lý trên toàn trang web (lưu ý rằng bạn không cần phải viết một trình xử lý nào, có một trình xử lý tích hợp cơ bản trong PHP, khá tốt). Ngoại lệ duy nhất (không nhằm mục đích chơi chữ) là việc tạo phiên bản PDO, trong trường hợp có lỗi, phiên bản này có thể tiết lộ thông tin xác thực kết nối (đó sẽ là một phần của dấu vết ngăn xếp). Để ẩn chúng, chúng ta có thể gói mã kết nối vào một toán tử 222 và sau đó ném một 224 mới chỉ chứa thông báo chứ không chứa thông tin đăng nhậpMột câu nói dài về vấn đề này Mặc dù ảo tưởng phổ biến, bạn không bao giờ nên bắt lỗi để báo cáo chúng. Một mô-đun (như lớp cơ sở dữ liệu) không được báo cáo lỗi của nó. Chức năng này phải được ủy quyền cho một trình xử lý trên toàn ứng dụng. Tất cả những gì chúng ta cần là đưa ra một lỗi (ở dạng ngoại lệ) - điều mà chúng ta đã làm. Đó là tất cả. Bạn cũng không nên "luôn gói các thao tác PDO của mình trong một 225" như hướng dẫn phổ biến nhất từ tutsplus khuyến nghị. Hoàn toàn ngược lại, việc bắt một ngoại lệ nên là một trường hợp ngoại lệ (ý định chơi chữ)Trên thực tế, không có gì đặc biệt trong các ngoại lệ PDO - chúng đều là lỗi giống nhau. Vì vậy, bạn phải xử lý chúng giống hệt như các lỗi khác. Nếu bạn đã có trình xử lý lỗi trước đó, thì bạn không nên tạo một trình xử lý lỗi dành riêng cho PDO. Nếu bạn không quan tâm - cũng không sao cả, vì PHP rất tốt với việc xử lý lỗi cơ bản và sẽ thực hiện các ngoại lệ PDO. Xử lý ngoại lệ là một trong những vấn đề với hướng dẫn PDO. Lần đầu tiên làm quen với các ngoại lệ khi bắt đầu với PDO, các tác giả xem xét các ngoại lệ dành riêng cho thư viện này và bắt đầu xử lý ngoại lệ một cách siêng năng (nhưng không đúng cách) chỉ cho PDO. Điều này là hoàn toàn vô nghĩa. Nếu trước đây một người không chú ý đặc biệt đến bất kỳ trường hợp ngoại lệ nào, thì họ đã không nên thay đổi thói quen đối với PDO. Nếu một người không sử dụng 222 trước đây, họ nên tiếp tục sử dụng điều đó, cuối cùng học cách sử dụng các ngoại lệ và khi nào thích hợp để bắt chúngVì vậy, bây giờ bạn có thể nói rằng hướng dẫn sử dụng PHP là sai, nói rằng
Tuy nhiên, không có cái gọi là "hiển thị dấu vết quay lại". Những gì công cụ zend thực sự làm chỉ là chuyển đổi một ngoại lệ chưa được xử lý thành một lỗi nghiêm trọng. Và sau đó, lỗi nghiêm trọng này được xử lý giống như bất kỳ lỗi nào khác - vì vậy nó sẽ chỉ được hiển thị nếu lệnh 227 thích hợp được đặt. Do đó, mặc dù bạn có thể hoặc không thể bắt gặp một ngoại lệ, nhưng nó hoàn toàn không liên quan gì đến việc hiển thị thông tin nhạy cảm, bởi vì đó là một cài đặt cấu hình hoàn toàn khác để đáp ứng với điều này. Vì vậy, đừng bắt các ngoại lệ PDO để báo cáo chúng. Thay vào đó, hãy định cấu hình máy chủ của bạn đúng cáchTrên máy chủ phát triển, chỉ cần bật hiển thị lỗi 13Trong khi trên máy chủ sản xuất, tắt hiển thị lỗi trong khi bật lỗi đăng nhập 14
Bạn có thể chỉ muốn bắt lỗi PDO trong hai trường hợp
E. g 15Tuy nhiên, nói chung, không cần điều trị riêng cho các trường hợp ngoại lệ PDO. Nói tóm lại, để có lỗi PDO được báo cáo chính xác
Do đó, bạn sẽ luôn được thông báo về tất cả các lỗi cơ sở dữ liệu mà không cần thêm một dòng mã nào. đọc thêm Lấy số lượng hàng với PDOBạn không cần nó Mặc dù PDO cung cấp một hàm để trả về số hàng mà truy vấn tìm thấy, 233, nhưng bạn hầu như không cần đến nó. Có thật khôngNếu bạn nghĩ kỹ, bạn sẽ thấy đây là chức năng bị lạm dụng nhiều nhất trên web. Hầu hết thời gian nó không được sử dụng để đếm bất cứ thứ gì, mà chỉ là một lá cờ - chỉ để xem liệu có bất kỳ dữ liệu nào được trả về hay không. Nhưng đối với trường hợp như vậy, bạn có dữ liệu. Chỉ cần lấy dữ liệu của bạn, sử dụng 234 hoặc 219 - và nó sẽ đóng vai trò như một lá cờ như vậy. Nói, để xem có người dùng nào có tên như vậy không, chỉ cần chọn một hàng 16Chính xác điều tương tự với việc nhận một hàng hoặc một mảng có hàng 17Hãy nhớ rằng ở đây bạn không cần số đếm, số hàng thực tế, mà là cờ boolean. Vì vậy, bạn đã nhận nó Chưa kể trường hợp sử dụng phổ biến thứ hai cho chức năng này không bao giờ được sử dụng. Người ta không bao giờ nên sử dụng 236 để đếm hàng trong cơ sở dữ liệu. Thay vào đó, người ta phải yêu cầu cơ sở dữ liệu đếm chúng và trả về kết quả trong một hàng 18là cách thích hợp duy nhất về bản chất
Do đó, bạn có thể nói rằng câu trả lời hàng đầu cho câu hỏi này trên Stack Overflow về cơ bản là vô nghĩa và có hại - một lệnh gọi tới ____1236 không bao giờ có thể được thay thế bằng truy vấn ____1242 - mục đích của chúng về cơ bản là khác nhau, trong khi chỉ chạy một truy vấn bổ sung để lấy số lượng hàng Các hàng bị ảnh hưởng và id chènPDO đang sử dụng cùng một chức năng để trả về cả số hàng được trả về bởi câu lệnh SELECT và số hàng bị ảnh hưởng bởi các truy vấn DML - 233. Do đó, để có được số lượng hàng bị ảnh hưởng, chỉ cần gọi hàm này sau khi thực hiện truy vấnMột câu hỏi thường gặp khác là do mysql sẽ không cập nhật hàng, nếu giá trị mới giống với giá trị cũ. Do đó, số hàng bị ảnh hưởng có thể khác với số hàng khớp với mệnh đề WHERE. Đôi khi cần phải biết số sau này Mặc dù bạn có thể yêu cầu 236 trả về số hàng khớp thay vì số hàng bị ảnh hưởng bằng cách đặt tùy chọn 245 thành TRUE, nhưng vì đây là tùy chọn chỉ dành cho kết nối và do đó bạn không thể thay đổi hành vi của nó trong thời gian chạy, nên bạn sẽ chỉ phải tuân theo Lưu ý rằng 245 không được đảm bảo để hoạt động, như được mô tả trong nhận xét bên dướiThật không may, không có bản sao PDO nào cho hàm 247 mà đầu ra có thể được phân tích cú pháp dễ dàng và tìm thấy số mong muốn. Đây là một trong những nhược điểm nhỏ của PDOCó thể lấy mã định danh được tạo tự động từ trường trình tự hoặc trường auto_inclement trong mysql từ PDO. chức năng lastInsertId. Câu trả lời cho câu hỏi thường gặp, "liệu chức năng này có an toàn để sử dụng trong môi trường đồng thời không?" . vâng, nó an toàn. Chỉ là một giao diện cho hàm mysql_insert_id() của MySQL C API, nó hoàn toàn an toàn Báo cáo đã chuẩn bị và mệnh đề THÍCHMặc dù nhìn chung PDO dễ sử dụng, nhưng vẫn có một số vấn đề và tôi sẽ giải thích một số Một trong số họ đang sử dụng trình giữ chỗ với mệnh đề SQL 248. Lúc đầu, người ta sẽ nghĩ rằng một truy vấn như vậy sẽ làm 19nhưng họ sẽ sớm biết rằng nó sẽ tạo ra lỗi. Để hiểu bản chất của nó, người ta phải hiểu rằng, như đã nói ở trên, trình giữ chỗ chỉ phải biểu thị một dữ liệu hoàn chỉnh theo nghĩa đen - một chuỗi hoặc một số cụ thể là. Và không có nghĩa là nó có thể đại diện cho một phần của một phần SQL theo nghĩa đen hoặc một phần tùy ý nào đó. Vì vậy, khi làm việc với LIKE, trước tiên chúng ta phải chuẩn bị nghĩa đen hoàn chỉnh của mình, sau đó gửi nó đến truy vấn theo cách thông thường 40Câu lệnh chuẩn bị và mệnh đề INGiống như đã nói ở trên, không thể thay thế một phần truy vấn tùy ý bằng một trình giữ chỗ. Bất kỳ chuỗi nào bạn liên kết thông qua trình giữ chỗ sẽ được đưa vào truy vấn dưới dạng một chuỗi ký tự đơn. Ví dụ: một chuỗi 249 sẽ được ràng buộc dưới dạng một chuỗi, dẫn đến 41tạo SQL để tìm kiếm chỉ một giá trị Để làm cho đúng, người ta cần các giá trị riêng biệt, để làm cho một truy vấn giống như 42Do đó, đối với các giá trị được phân tách bằng dấu phẩy, như đối với toán tử SQL 250, người ta phải tạo một bộ 03 theo cách thủ công và đưa chúng vào truy vấn 43Không thuận tiện lắm, nhưng so với mysqli thì nó ngắn gọn đến kinh ngạc Trong trường hợp có các trình giữ chỗ khác trong truy vấn, bạn có thể sử dụng hàm 252 để nối tất cả các biến thành một mảng, thêm các biến khác của bạn ở dạng mảng, theo thứ tự chúng xuất hiện trong truy vấn của bạn 44Trong trường hợp bạn đang sử dụng các trình giữ chỗ được đặt tên, mã sẽ phức tạp hơn một chút, vì bạn phải tạo một chuỗi các trình giữ chỗ được đặt tên, ví dụ:. g. 253. Vì vậy, mã sẽ là 45May mắn thay, đối với các trình giữ chỗ được đặt tên, chúng tôi không phải tuân theo thứ tự nghiêm ngặt, vì vậy chúng tôi có thể hợp nhất các mảng của mình theo bất kỳ thứ tự nào Bảo vệ tên bảng và trườngTrên Stack Overflow, tôi đã thấy quá nhiều người dùng PHP triển khai mã PDO nguy hiểm nhất, nghĩ rằng chỉ các giá trị dữ liệu phải được bảo vệ. Nhưng tất nhiên là không Thật không may, PDO không có trình giữ chỗ cho số nhận dạng (tên bảng và trường), vì vậy nhà phát triển phải lọc chúng theo cách thủ công. Bộ lọc như vậy thường được gọi là "danh sách trắng" (nơi chúng tôi chỉ liệt kê các giá trị được phép) trái ngược với "danh sách đen" nơi chúng tôi liệt kê các giá trị không được phép. Đây là một ví dụ ngắn gọn 46phương pháp tương tự nên được sử dụng cho hướng, mặc dù mã sẽ đơn giản hơn một chút 47có được hai biến này theo cách này sẽ giúp chúng an toàn 100% 48Cách tiếp cận tương tự phải được sử dụng mỗi khi một bảng tên trường sẽ được sử dụng trong truy vấn Một vấn đề với mệnh đề LIMITMột vấn đề khác liên quan đến mệnh đề SQL 254. Khi ở chế độ mô phỏng (được bật theo mặc định), PDO sẽ thay thế trình giữ chỗ bằng dữ liệu thực, thay vì gửi riêng. Và với liên kết "lười biếng" (sử dụng mảng trong 07), PDO coi mọi tham số là một chuỗi. Do đó, truy vấn 256 đã chuẩn bị trở thành 257, đây là cú pháp không hợp lệ khiến truy vấn không thành côngCó hai giải pháp Một là tắt mô phỏng (vì MySQL có thể sắp xếp tất cả các trình giữ chỗ đúng cách). Để làm như vậy người ta có thể chạy mã này 49Và các thông số có thể được giữ trong 07 50Một cách khác là liên kết các biến này một cách rõ ràng trong khi đặt loại tham số phù hợp 51Một điều đặc biệt về 259. vì một số lý do, nó không thực thi kiểu truyền. Vì vậy, sử dụng nó trên một số có kiểu chuỗi sẽ gây ra lỗi nói trên 52Nhưng thay đổi 260 trong ví dụ thành 261 - và mọi thứ sẽ suôn sẻgiao dịchĐể thực hiện thành công một giao dịch, bạn phải đảm bảo rằng chế độ lỗi được đặt thành ngoại lệ và tìm hiểu ba phương pháp chính tắc
Ngoại lệ là điều cần thiết cho các giao dịch vì chúng có thể bị bắt. Vì vậy, trong trường hợp một trong các truy vấn không thành công, quá trình thực thi sẽ bị dừng và chuyển thẳng đến khối bắt, nơi toàn bộ giao dịch sẽ được khôi phục Vì vậy, một ví dụ điển hình sẽ giống như 53Xin lưu ý những điều quan trọng sau đây
Gọi các thủ tục được lưu trữ trong PDOCó một điều về thủ tục lưu sẵn mà bất kỳ lập trình viên nào cũng vấp phải lúc đầu. mọi thủ tục được lưu trữ luôn trả về một tập hợp kết quả bổ sung. một (hoặc nhiều) kết quả có dữ liệu thực và một kết quả trống. Điều đó có nghĩa là nếu bạn cố gắng gọi một thủ tục và sau đó tiếp tục với một truy vấn khác, thì lỗi "Không thể thực hiện các truy vấn trong khi các truy vấn không có bộ đệm khác đang hoạt động" sẽ xảy ra, bởi vì trước tiên bạn phải xóa kết quả trống thừa đó. Do đó, sau khi gọi một thủ tục lưu trữ nhằm mục đích chỉ trả về một tập kết quả, chỉ cần gọi 268 một lần (tất nhiên là sau khi tìm nạp tất cả dữ liệu trả về từ câu lệnh, nếu không nó sẽ bị loại bỏ) 54Trong khi đối với các thủ tục được lưu trữ trả về nhiều tập kết quả, hành vi sẽ giống như khi thực hiện nhiều truy vấn 55Tuy nhiên, như bạn có thể thấy ở đây có một thủ thuật khác phải được sử dụng. nhớ rằng tập hợp kết quả bổ sung? . Vì vậy, chúng tôi không thể chỉ sử dụng 269. Thay vào đó, chúng ta cũng phải kiểm tra kết quả trống. Vì mục đích gì thì 270 thật xuất sắcTính năng này là một trong những khác biệt cơ bản giữa mysql ext cũ và các thư viện hiện đại. sau khi gọi một thủ tục được lưu trữ với 00, không có cách nào để tiếp tục làm việc với cùng một kết nối, vì không có chức năng 272 cho 273. Người ta phải đóng kết nối và sau đó mở lại một kết nối mới để chạy các truy vấn khác sau khi gọi một thủ tục được lưu trữViệc gọi một thủ tục được lưu trữ là một trường hợp hiếm hoi khi sử dụng 54 là hợp lý, vì đó là cách duy nhất để xử lý các tham số 275 và 276. Ví dụ có thể được tìm thấy trong chương hướng dẫn tương ứng. Tuy nhiên, đối với mysql thì nó không hoạt động. Bạn phải dùng đến một biến SQL và một lệnh gọi bổ sungLưu ý rằng đối với các cơ sở dữ liệu khác nhau, cú pháp cũng có thể khác nhau. Ví dụ: để chạy thủ tục được lưu trữ đối với máy chủ Microsoft SQL, hãy sử dụng định dạng sau 56ở đâu ? . Lưu ý rằng không nên sử dụng dấu ngoặc nhọn trong cuộc gọi Chạy nhiều truy vấn với PDO
Khi ở chế độ mô phỏng, PDO có thể chạy nhiều truy vấn trong cùng một câu lệnh, thông qua query() hoặc ________ 1277. Để truy cập kết quả của các truy vấn hệ quả, người ta phải sử dụng 268 57Trong vòng lặp này, bạn sẽ có thể thu thập tất cả thông tin liên quan từ mọi truy vấn, chẳng hạn như hàng bị ảnh hưởng, id được tạo tự động hoặc lỗi đã xảy ra Điều quan trọng là phải hiểu rằng tại thời điểm 07, PDO sẽ chỉ báo lỗi cho truy vấn đầu tiên. Nhưng nếu xảy ra lỗi ở bất kỳ truy vấn nào sau đó, để nhận được lỗi đó, người ta phải lặp lại các kết quả. Mặc dù có một số ý kiến thiếu hiểu biết, PDO không thể và không nên báo cáo tất cả các lỗi cùng một lúc. Một số người không thể nắm bắt được toàn bộ vấn đề và không hiểu rằng thông báo lỗi không phải là kết quả duy nhất từ truy vấn. Có thể có một tập dữ liệu được trả về hoặc một số siêu dữ liệu như id chèn. Để có được những thứ này, người ta phải lặp lại các tập kết quả, từng cái một. Nhưng để có thể đưa ra lỗi ngay lập tức, PDO sẽ phải tự động lặp lại và do đó loại bỏ một số kết quả. Đó sẽ là một điều vô nghĩa rõ ràngKhông giống như 280 PDO không thực hiện cuộc gọi không đồng bộ, vì vậy bạn không thể "bắn và quên" - gửi hàng loạt truy vấn tới mysql và đóng kết nối, PHP sẽ đợi cho đến khi truy vấn cuối cùng được thực thichế độ thi đua. PDO. ATTR_EMULATE_PREPARESMột trong những tùy chọn cấu hình PDO gây tranh cãi nhất là 281. Nó làm gì?
Cả hai phương pháp đều có nhược điểm và ưu điểm của chúng, và - tôi phải nhấn mạnh vào điều đó - cả hai đều an toàn như nhau, nếu được sử dụng đúng cách. Mặc dù giọng điệu khá hấp dẫn của bài viết phổ biến trên Stack Overflow, nhưng cuối cùng, nó nói rằng nếu bạn đang sử dụng các phiên bản PHP và MySQL được hỗ trợ đúng cách, bạn sẽ an toàn 100%. Tất cả những gì bạn phải làm là đặt mã hóa trong DSN, như được hiển thị trong ví dụ trên và các câu lệnh chuẩn bị được mô phỏng của bạn sẽ an toàn như câu lệnh thực Lưu ý rằng khi chế độ gốc được sử dụng, dữ liệu sẽ không bao giờ xuất hiện trong truy vấn, được công cụ phân tích cú pháp nguyên trạng với tất cả các trình giữ chỗ tại chỗ. Nếu bạn đang xem nhật ký truy vấn Mysql cho truy vấn đã chuẩn bị của mình, bạn phải hiểu rằng đó chỉ là truy vấn nhân tạo được tạo chỉ cho mục đích ghi nhật ký chứ không phải truy vấn thực đã được thực thi Các vấn đề khác với chế độ mô phỏng như sau Khi chế độ mô phỏng được BẬTngười ta có thể sử dụng một tính năng tiện dụng của các câu lệnh đã chuẩn bị được đặt tên - một trình giữ chỗ có cùng tên có thể được sử dụng bất kỳ số lần nào trong cùng một truy vấn, trong khi biến tương ứng chỉ được ràng buộc một lần. Vì một số lý do mơ hồ, chức năng này bị tắt khi tắt chế độ mô phỏng 58Ngoài ra, khi mô phỏng là 283, PDO có thể chạy nhiều truy vấn trong một câu lệnh đã chuẩn bịNgoài ra, vì các câu lệnh chuẩn bị sẵn chỉ hỗ trợ một số loại truy vấn nhất định, nên bạn chỉ có thể chạy một số truy vấn với các câu lệnh chuẩn bị khi mô phỏng là 283. Đoạn mã sau sẽ trả về tên bảng trong chế độ mô phỏng và lỗi khác 59Khi chế độ mô phỏng bị TẮTNgười ta có thể không bận tâm với các loại tham số, vì mysql sẽ sắp xếp tất cả các loại đúng cách. Do đó, chuỗi thậm chí có thể được liên kết với các tham số GIỚI HẠN, như đã được lưu ý trong chương tương ứng Ngoài ra, chế độ này sẽ cho phép sử dụng lợi thế của tính năng thực thi một lần chuẩn bị nhiều lần Thật khó để quyết định chế độ nào được ưu tiên hơn, nhưng vì lợi ích khả dụng, tôi muốn biến nó thành 286, để tránh rắc rối với mệnh đề 254. Các vấn đề khác có thể được coi là không đáng kể khi so sánhMysqlnd và các truy vấn được đệm. Bộ dữ liệu khổng lồGần đây, tất cả các tiện ích mở rộng PHP hoạt động với cơ sở dữ liệu mysql đã được cập nhật dựa trên thư viện cấp thấp có tên là 288, thay thế ứng dụng khách 289 cũ. Do đó, một số thay đổi trong hành vi PDO, chủ yếu được mô tả ở trên và một thay đổi sauCó một thứ gọi là truy vấn đệm. Mặc dù có thể bạn không để ý nhưng bạn đã sử dụng chúng suốt. Thật không may, đây là tin xấu cho bạn. không giống như các phiên bản PHP cũ, nơi bạn đang sử dụng các truy vấn được đệm gần như miễn phí, các phiên bản hiện đại được xây dựng dựa trên trình điều khiển mysqlnd sẽ không cho phép bạn làm điều đó nữa
Toàn bộ vấn đề là về một tập kết quả, viết tắt của tất cả dữ liệu được truy vấn tìm thấy Khi truy vấn CHỌN của bạn được thực thi, có hai cách để cung cấp kết quả trong tập lệnh của bạn. một bộ đệm và không có bộ đệm. Khi sử dụng phương thức đệm, tất cả dữ liệu do truy vấn trả về sẽ được sao chép vào bộ nhớ của tập lệnh cùng một lúc. Trong khi ở chế độ không có bộ đệm, máy chủ cơ sở dữ liệu sẽ cung cấp từng hàng một Vì vậy, bạn có thể biết rằng ở chế độ được lưu vào bộ đệm, tập kết quả luôn chiếm quá nhiều bộ nhớ trên máy chủ ngay cả khi quá trình tìm nạp hoàn toàn không bắt đầu. Đó là lý do tại sao không nên chọn bộ dữ liệu lớn nếu bạn không cần tất cả dữ liệu từ nó Tuy nhiên, khi các ứng dụng khách dựa trên libmysql cũ được sử dụng, vấn đề này không làm phiền người dùng PHP quá nhiều, vì bộ nhớ được sử dụng bởi tập kết quả không được tính trong 290 và 291Nhưng với mysqlnd, mọi thứ đã thay đổi và tập kết quả được trả về bởi truy vấn được lưu trong bộ đệm sẽ được tính vào cả 290 và 291, bất kể bạn chọn cách nào để nhận kết quả 0sẽ cho bạn 1điều đó có nghĩa là với truy vấn được đệm, bộ nhớ sẽ được sử dụng ngay cả khi bạn đang tìm nạp từng hàng một Vì vậy, hãy nhớ rằng nếu bạn đang chọn một lượng dữ liệu thực sự khổng lồ, hãy luôn đặt 294 thành 295Tất nhiên, có những nhược điểm. Một là khét tiếng
thông báo lỗi có nghĩa là cho đến khi bạn không truy xuất tất cả các hàng đã chọn từ truy vấn không có bộ đệm, thì sẽ không thể chạy bất kỳ truy vấn nào khác đối với cùng một kết nối cơ sở dữ liệu |