Hướng dẫn php delusions - ảo tưởng php
Có rất nhiều hướng dẫn về PDO, nhưng thật không may, hầu hết trong số họ không giải thích được lợi ích thực sự của PDO, hoặc thậm chí thúc đẩy các thực hành khá xấu. Hai trường hợp 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. Do đó, một nửa các tính năng của PDO vẫn bị che khuất và hầu như không bao giờ được sử dụng bởi các nhà phát triển PHP, do đó, liên tục 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 điều đó, hướng dẫn này được viết bởi một người đã sử dụng PDO trong nhiều năm, đào qua nó và trả lời hàng ngàn câu hỏi về Stack Overflow (người mang huy hiệu PDO vàng duy nhất). Theo nhiệm vụ của trang web này, bài viết này sẽ bác bỏ các ảo tưởng và thực hành xấu khác nhau, trong khi thay vào đó hiển thị đúng cách. Mặc dù hướng dẫn này dựa trên trình điều khiển MySQL, thông tin nói chung, có thể áp dụng cho bất kỳ trình điều khiển nào được hỗ trợ.mysql driver, the information, in general, is applicable for any driver supported. Tại sao PDO?Điều đầu tiên trước tiên. Tại sao PDO ở tất cả? PDO là một lớp trừu tượng truy cập cơ sở dữ liệu. Tuy nhiên, sự trừu tượng là hai lần: một được biết đến rộng rãi nhưng ít quan trọng hơn, trong khi một lần khác là mơ hồ nhưng quan trọng nhất. Mọi người đều biết rằng PDO cung cấp giao diện thống nhất để truy cập nhiều cơ sở dữ liệu khác nhau. Mặc dù tính năng này là tuyệt vời, nhưng nó không tạo ra vấn đề lớn cho ứng dụng cụ thể, trong đó chỉ có một phụ trợ cơ sở dữ liệu được sử dụng. Và, mặc dù có một số tin đồn, không thể chuyển đổi các phụ trợ cơ sở dữ liệu bằng cách thay đổi một dòng duy nhất 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 đèn trung bình, điểm này khá 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 chức năng 2 quen thuộc. Tuy nhiên, nó không phải là; Nó là nhiều, nhiều hơn nữa.Tóm tắt PDO không chỉ là API cơ sở dữ liệu, mà còn các hoạt động cơ bản mà phải được lặp lại hàng trăm lần trong mỗi ứng dụng, làm cho 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 có ý định được sử dụng trực tiếp (nhưng chỉ là vật liệu xây dựng cho một số lớp trừu tượng cao hơn), 3 là một sự trừu tượng. Tuy nhiên, vẫn chưa đầy đủ, nhưng ít nhất là có thể sử dụng.Các lợi ích PDO thực sự là:
Lưu ý rằng mặc dù PDO là trình điều khiển DB bản địa tốt nhất, đối với ứng dụng web hiện đại, hãy xem xét sử dụng ORM với trình xây dựng truy vấn hoặc bất kỳ thư viện trừu tượng cao hơn nào khác, chỉ thỉnh thoảng dự phòng với Vanilla PDO. Orms tốt là học thuyết, hùng hồn, redbean và yii :: ar. Aura.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 tiên. Vì vậy, 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 gọi là DSN. Mặc dù không có gì phức tạp - thay vì một danh sách đơ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 nơi khác nhau:
Trong đó DSN là một chuỗi phân phối 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à một dấu hai chấm:
Lưu ý rằng điều quan trọng là phải tuân theo định dạng thích hợp - không có khoảng trống hoặc trích dẫn hoặc đồ trang trí khác phải được sử dụng trong DSN, nhưng chỉ các tham số, giá trị và phân định, như trong hướng dẫn.no spaces or quotes or other decorations have to be used in DSN, but only parameters, values and delimiters, as shown in the manual. Đây là một ví dụ cho MySQL:
Với tất cả các biến đã nói ở trên, chúng tôi sẽ có phiên bản PDO thích hợp trong biến 3.Ghi chú quan trọng cho người dùng mở rộng MySQL muộn:
Thông tin chi tiết về MySQL có thể được tìm thấy 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 một 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 phương thức PDO :: Query (). 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 với tài nguyên, được trả về bởi 0, đặc biệt là trong cách bạn có thể lấy các hàng thực tế từ nó:
Ngoài ra, phương pháp 7 cho phép chúng tôi sử dụng chuỗi phương thức gọn gàng cho các truy vấn được chọn, sẽ được hiển thị bên dưới.Tuyên bố chuẩn bị. Bảo vệ khỏi tiêm SQLĐây là lý do chính và quan trọng duy nhất tại sao bạn bị tước mất chức năng 0 yêu dấu của bạn và bị ném vào thế giới khắc nghiệt của các đối tượng dữ liệu: PDO đã chuẩn bị các tuyên bố hỗ trợ ra khỏi hộp. 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ó rất quan trọng được giải thích chi tiết trong hướng dẫn của Hitchhiker về phòng chống tiêm SQL.the only proper way to run a query, if any variable is going to be used in it. The reason why it is so important is explained in detail in
The Hitchhiker's Guide to SQL Injection prevention.Vì 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 trình giữ chỗ, sau đó chuẩn bị truy vấn của bạn, sau đó thực hiện nó, chuyển các biến riêng biệt.placeholder, then prepare your query, and then execute it, passing variables separately. Câu chuyện dài, nó không khó như nó có vẻ. Trong hầu hết các trường hợp, bạn chỉ cần hai hàm - PREPARE () và EXECUTE (). Trước hết, bạn phải thay đổi truy vấn của mình, thêm trình giữ chỗ thay cho các biến. Nói, một mã như thế này
sẽ trở thành
hoặc
Lưu ý rằng PDO hỗ trợ người giữ chỗ vị trí ( 3) và được đặt tên ( 4), sau này luôn bắt đầu từ một dấu hai chấm và chỉ có thể được viết bằng các chữ cái, chữ số và chỉ nhấn mạnh. Cũng lưu ý rằng không có báo giá nào phải được sử dụng xung quanh các khoản giữ chỗ.no quotes have to be ever used around placeholders.Có một truy vấn với người giữ chỗ, bạn phải chuẩn bị nó, sử dụng phương pháp 5. Hàm này sẽ trả về cùng một đối tượng 6 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 hiện truy vấn, bạn phải chạy phương thức 7 của đối tượng này, chuyển các biến trong đó, dưới dạng mảng. Và sau đó, bạn sẽ có thể đưa dữ liệu kết quả ra khỏi tuyên bố (nếu có):
Như bạn có thể thấy, đối với các vị trí 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 phím phải khớp với tên trình giữ chỗ trong truy vấn. Bạn không thể trộn các vị trí và đặt chỗ được đặt tên trong cùng một truy vấn. Xin lưu ý rằng các chủ trình vị trí cho phép bạn viết mã ngắn hơn, nhưng nhạy cảm với thứ tự đố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). Trong khi các chủ sở hữu đặt chỗ làm cho mã của bạn rõ ràng hơn, chúng cho phép thứ tự ràng buộc ngẫu nhiên. Cũng lưu ý rằng mặc dù có một ảo tưởng rộng rãi, nhưng không cần " 8" trong các phím.Sau khi thực hiện, bạn có thể bắt đầu nhận dữ liệu của mình, sử dụng tất cả các phương thức đượ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ộcChuyển dữ liệu vào 7 (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ẽ bị ràng buộc dưới dạng chuỗi (lưu cho các giá trị 0, sẽ được gửi đến truy vấn như là, tức là SQL 0), nhưng hầu hết thời gian đều ổn và sẽ không gây ra vấn đề gì.strings (save for 0 values, that will be sent to the query as is, i.e. as SQL 0), but most of time it's all right and won't cause any problem. Tuy nhiên, đôi khi tốt hơn là đặt kiểu dữ liệu một cách rõ ràng. Các trường hợp có thể là:
Trong trường hợp liên kết rõ ràng như vậy 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, bởi vì, không giống như 4, nó không có tác dụng phụ để đối phó.Truy vấn các bộ phận bạn có thể liên kếtĐiều rất quan trọng là phải hiểu những phần truy vấn nào bạn có thể liên kết bằng cách sử dụng các câu lệnh đã chuẩn bị và bạn không thể. Trên thực tế, danh sách này ngắn một cách quá mức: chỉ có thể bị ràng buộc theo chuỗi và số có thể bị 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 một chuỗi được trích dẫn theo nghĩa đen - nó có thể bị ràng buộc. Đối với tất cả các trường hợp khác, bạn không thể sử dụng các câu lệnh được 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 được trích dẫn theo nghĩa đen 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ị. Giải pháp 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 Tuyên bố chuẩn bị. Nhiều thực thiĐôi khi bạn có thể sử dụng các câu lệnh đã chuẩn bị cho việc 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 cùng một truy vấn nhiều lần, vì nó chỉ truy vấn phân tích cú pháp một lần. Tính năng này sẽ hữu ích hơn nếu có thể thực hiện 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. Vì vậy, bạn chỉ giới hạn trong việc lặp lại cùng một truy vấn trong cùng một trường hợp, điều này hiếm khi cần thiết trong các tập lệnh PHP thông thường và giới hạn việc sử dụng tính năng này để chèn hoặc cập nhật lặp lại:
Lưu ý rằng tính năng này là một chút được đánh giá cao. Không chỉ cần thiết quá hiếm khi nói đến, mà việc tăng hiệu suất không phải là lớn - phân tích cú pháp truy vấn là thực sự nhanh chóng. Lưu ý rằng bạn chỉ có thể nhận được lợi thế này khi chế độ mô phỏng bị tắt.off. Chạy Chọn Chèn, Cập nhật hoặc Xóa các câu lệnhCố 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. Để 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ư nó đã được hiển thị ở trên, những gì bạn cần là chuẩn bị một truy vấn với người giữ chỗ, và sau đó thực hiện nó, gửi các biến riêng biệt. Hoặc đối với truy vấn 5 và 6, quá trình này 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 7 ngay cùng với 8:
Tuy nhiên, nếu bạn muốn có được số lượng hàng bị ảnh hưởng, mã sẽ phải giống nhau ba dòng:
Nhiề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 tuyên bố. cho mỗi()Cách cơ bản và trực tiếp nhất để có được nhiều hàng từ một câu lệnh sẽ là vòng lặp 9. Nhờ giao diện có thể đi qua, 6 có thể được lặp lại bằng cách sử dụng toán tử 9: 0Lư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 thu được trong bộ nhớ nhưng cung cấp cho chúng từng cái một (mặc dù hãy nhớ rằng vấn đề này). Lấy dữ liệu ra khỏi tuyên bố. tìm về()Chúng tôi đã thấy chức năng này rồi, nhưng chúng ta 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 cho chức năng 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 trở thành một tương tự sơ bộ với 2 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 ( 3, 4, v.v.), chỉ có một chức năng, nhưng hành vi của nó có thể được thay đổi bằng một tham số. Có rất nhiều chế độ tìm nạp trong PDO và chúng tôi sẽ thảo luận sau, nhưng đây là một số ít để bắt đầu:
Từ những điều trên, bạn có thể nói 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à 00, có thể tạo một đối tượng của lớp cụ thể 2sẽ tạo ra một mảng chứa đầy các đối tượng của lớp tin tức, đặt thuộc tính 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à 7, nhưng bạn có thể thay đổi nó bằng tùy chọn cấu hình 04 như được hiển thị trong ví dụ kết nối. Vì vậy, một khi được đặt, nó có thể được bỏ qua hầu hết thời gian.Các loại trở lại.Chỉ khi PDO được xây dựng trên MYSQLND và chế độ mô phỏng bị tắt, thì PDO sẽ trả về các giá trị 05 và 06 với các loại tương ứng. Nói, nếu chúng ta tạo một bảngoff, then PDO will return 05 and 06 values with respective types. Say, if we create a table 3Và sau đó truy vấn nó từ PDO dựa trên mysqlnd với việc mô phỏng đã tắt, đầu ra sẽ 4Mặt khác, hành vi 2 quen thuộc sẽ được tuân thủ - tất cả các giá trị được trả về dưới dạng các chuỗi chỉ với 0 được trả về là 0.Nếu vì một lý do nào đó, bạn không thích hành vi này và chỉ thích kiểu cũ với các chuỗi và null, thì bạn có thể sử dụng tùy chọn cấu hình sau để ghi đè nó: 5Lưu ý rằng đối với loại 10, 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 nổi và kép không chính xác.Lấy dữ liệu ra khỏi tuyên bố. FetchColumn ()Một hàm trợ giúp gọn gàng trả về giá trị của trường đơn 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: 6Lấy dữ liệu ra khỏi tuyên bố trong hàng chục định dạng khác nhau. Fetchall ()Đó 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à một trình bao bọc, vì chức năng này có thể tự động hóa nhiều hoạt động được thực hiện bằng tay. 11 trả về một mảng bao gồm tất cả các hàng được trả về bởi truy vấn. Từ thực tế này, chúng tôi có thể đưa ra hai kết luận:all the rows
returned by the query. From this fact we can make two conclusions:
Bạn sẽ ngạc nhiên, trong bao nhiêu định dạng khác nhau, chức năng này có thể trả về dữ liệu (và mức độ ít người dùng PHP trung bình biết về chúng), tất cả được kiểm soát bởi các biến 12. Một số trong số họ là:Nhận một mảng đơn giản.Theo mặc định, chức năng này sẽ trả về mảng được 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ư 5, 6, 8, vv có thể thay đổi định dạng hàng. 7Nhận một cột.Nó thường rất tiện dụng để có được mảng một chiều đơn giản ra khỏi truy vấn, nếu chỉ có một cột trong số nhiều hàng được lấy. Bạn đi đây: 8Nhận các cặp giá trị khóa.Cũng định dạng cực kỳ hữu ích, khi chúng ta cần có cùng một cột, nhưng được lập chỉ mục không theo số theo thứ tự mà bởi một trường khác. Đây là 16 hằng số: 9Lưu ý rằng bạn chỉ phải chọn hai cột cho chế độ này, trước tiên phải là duy nhất. Nhận các hàng được lập chỉ mục bởi 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 đủ, nhưng được lập chỉ mục bởi một trường duy nhất, nhờ hằng số 17: 0Lưu ý rằng cột đầu tiên được chọn phải là duy nhất (trong truy vấn này, người ta cho rằng cột đầu tiên là ID, nhưng để chắc chắn liệt kê rõ ràng hơn nó một cách rõ ràng). Nhận các hàng được nhóm theo một số lĩnh vực 18 sẽ nhóm các hàng vào 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 chỉ mục được trả về bởi 19 thông thường. Ví dụ, mã sau đây sẽ tách các chàng trai khỏi các cô gái và đưa chúng vào các mảng khác nhau: 1Vì vậy, đây là giải pháp lý tưởng cho một nhu cầu phổ biến như "các sự kiện nhóm theo ngày" hoặc "hàng hóa nhóm 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 20 cho người hâm mộ lập trình chức năng.Nhiều chế độ sẽ sớm ra mắt. Xử lý lỗi. Ngoại lệMặc dù có một số chế độ xử lý lỗi trong PDO, nhưng phương thức duy nhất thích hợp là 21. Vì vậy, người ta phải luôn 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, 2hoặc như một tùy chọn kết nối, như đã được trình bày trong ví dụ trên. Và đây là tất cả những gì bạn cần cho báo cáo lỗi cơ bản. Báo cáo lỗi PDOTL; DR: Mặc dù tất cả những gì các hướng dẫn khác nói, bạn không cần một nhà điều hành Ngoại lệ duy nhất (không có ý định chơi chữ) là việc tạo phiên bản PDO, trong trường hợp lỗi 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 toán tử 22 và sau đó ném một 24 mới chỉ chứa thông báo nhưng không phải là thông tin đăng nhập.Một lời ca ngợi dài về vấn đề: Mặc dù ảo tưởng rộng rãi, 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 nên báo cáo các lỗi của nó. Chức năng này phải được giao cho một trình xử lý toàn ứng dụng. Tất cả những gì chúng ta cần là nêu ra một lỗi (dướ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 luôn kết thúc các hoạt động PDO của mình trong một 25" 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 đặc biệt (ý đị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 là những lỗi giống nhau. Vì vậy, bạn phải đối xử với chúng giống hệt như các lỗi khác. Nếu bạn đã có một trình xử lý lỗi trước đây, bạn không nên tạo một trình chuyên dụng cho PDO. Nếu bạn không quan tâm - điều đó cũng ổn, vì PHP tốt với việc xử lý lỗi cơ bản và sẽ tiến hành ngoại lệ PDO. Xử lý ngoại lệ là một trong những vấn đề với hướng dẫn PDO. Được làm quen với các ngoại lệ lần đầu tiên 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ý các ngoại lệ một cách siêng năng (nhưng không đúng) cho PDO. Đây là hoàn toàn vô nghĩa. Nếu một người không chú ý đặc biệt đến bất kỳ trường hợp ngoại lệ nào trước đây, họ không nên thay đổi thói quen của họ cho PDO. Nếu một người không sử dụng 22 trước đây, họ nên giữ điều đó, cuối cùng học cách sử dụng các ngoại lệ và khi nào nó phù hợp để bắt chúng.Vì 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ó thứ gọi là "hiển thị dấu vết trở lại"! Những gì Zend Engine thực sự làm chỉ là chuyển đổi một ngoại lệ chưa được thực hiện thành một lỗi nghiêm trọng. Và sau đó, lỗi nghiêm trọng này được xử lý như bất kỳ lỗi nào khác - vì vậy nó sẽ chỉ được hiển thị nếu chỉ thị 27 thích hợp được đặt. Do đó, mặc dù bạn có thể hoặc bạn có thể không bắt được 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 đ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ách:there is no such thing as "the displaying of a back trace"!
What zend engine really does is just convert an uncaught exception into a fatal error. And then this fatal error is treated like any other error - so it will be displayed only if appropriate 27 directive is set. Thus, although you may or you may not catch an exception, it has absolutely nothing to do with displaying sensitive information, because it's a totally different configuration setting in response to this. So, do not catch PDO exceptions to
report them. Instead, configure your server properly:Trên máy chủ phát triển chỉ cần bật lỗi hiển thị lỗi: 3Trong khi trên máy chủ sản xuất, hãy tắt hiển thị lỗi trong khi lỗi đăng nhập: 4
Bắt các ngoại lệ PDOBạn có thể chỉ muốn bắt lỗi PDO trong hai trường hợp:
E.g.: 5Tuy nhiên, nói chung, không có điều trị dành riêng cho ngoại lệ PDO là cần thiết. Nói tóm lại, để có lỗi PDO được báo cáo đúng:
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 một dòng mã bổ sung nào! Đọc thêm. Nhận được số lượng hàng với PDOBạn không cần nó. Mặc dù PDO cung cấp một chức năng để trả về số lượng hàng được tìm thấy bởi truy vấn, 33, bạn hiếm khi cần nó. Có thật không.Nếu bạn nghĩ rằng nó kết thúc, bạn sẽ thấy rằng đây là một chức năng bị sử dụng sai nhiều nhất trong web. Hầu hết thời gian nó được sử dụng không phải để đếm bất cứ thứ gì, mà là một lá cờ đơn thuần - chỉ để xem liệu có bất kỳ dữ liệu nào được trả về. Nhưng đối với trường hợp như vậy, bạn có chính dữ liệu! Chỉ cần nhận dữ liệu của bạn, sử dụng 34 hoặc 19 - và nó sẽ phục vụ như một lá cờ như vậy! Nói, để xem liệu có bất kỳ người dùng nào có tên như vậy không, chỉ cần chọn một hàng: 6Chính xác là điều tương tự với việc nhận được một hàng hoặc một mảng có hàng: 7Hãy nhớ rằng ở đây bạn không cần số lượng, số lượng hàng thực tế, mà là một lá cờ boolean. Vì vậy, bạn đã nhận được nó. Chưa kể rằng 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 36 để đếm các hàng trong cơ sở dữ liệu! Thay vào đó, người ta phải yêu cầu một cơ sở dữ liệu để đếm chúng và trả về kết quả trong một hàng duy nhất:single row: 8là cách duy nhất thích hợp. 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 cuộc gọi đến 36 có thể không bao giờ được thay thế bằng truy vấn 42 - mục đích của chúng về cơ bản là khác nhau, trong khi chạy thêm một truy vấn để có được số lượng hàng trở lại bởi các truy vấn khác hoàn toàn không có ý nghĩa.Hàng bị ảnh hưởng và chèn IDPDO đang sử dụng cùng một chức năng để trả về cả số lượng hàng được trả về bởi câu lệnh chọn và số lượng hàng bị ảnh hưởng bởi các truy vấn DML - 33. Do đó, để có được số lượng hàng bị ảnh hưởng, chỉ cần gọi chức năng này sau khi thực hiện truy vấn.Một câu hỏi thường gặp khác là do thực tế là MySQL sẽ không cập nhật hàng, nếu giá trị mới giống như cũ. Do đó, số lượng hàng bị ảnh hưởng có thể khác với số lượng hàng phù hợ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ể nói 36 trả lại số lượng hàng được khớp thay vì các hàng bị ảnh hưởng bằng cách đặt tùy chọn 45 thành True, nhưng, vì đây là một tùy chọn chỉ có 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 Một chế độ cho ứng dụng, có thể không thuận tiện lắm.Lưu ý rằng 45 không được đảm bảo hoạt động, như được mô tả trong nhận xét dưới đây.Thật không may, không có đối tác PDO cho hàm 47 mà đầu ra có thể dễ dàng phân tích cú pháp và số mong muốn được tìm thấy. Đây là một trong những nhược điểm PDO nhỏ.Một mã định danh được tạo tự động từ một trường hoặc trường tự động_inclement trong MySQL có thể được lấy từ chức năng PDO :: LastInsertid. Một câu trả lời cho một 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?" là tích cực: Có, nó là an toàn. Chỉ là một giao diện của mysql c api mysql_insert_id (), nó hoàn toàn an toàn. Các tuyên bố chuẩn bị và điều khoản thíchMặc dù PDO dễ sử dụng chung, dù sao cũng có một số gotchas, và tôi sẽ giải thích một số. Một trong số đó là sử dụng các khoản giữ chỗ với mệnh đề 48 SQL. Lúc đầu, người ta sẽ nghĩ rằng một truy vấn như vậy sẽ làm: 9Nhưng ngay sau đó họ sẽ học được rằng nó sẽ tạo ra một lỗi. Để hiểu bản chất của nó, người ta phải hiểu rằng, giống như người ta đã nói ở trên, một người giữ chỗ chỉ phải đại diện cho một dữ liệu hoàn chỉnh theo nghĩa đen - một chuỗi hoặc một số 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 số SQL tùy ý. Vì vậy, khi làm việc với như thế, chúng tôi phải chuẩn bị hoàn toàn theo nghĩa đen của mình, và sau đó gửi nó đến truy vấn theo cách thông thường:complete literal first, and then send it to the query the usual way: 0Các tuyên bố chuẩn bị và trong mệnh đềGiống như người ta đã 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 một trình giữ chỗ sẽ được đưa vào truy vấn như một chuỗi đơn nghĩa đen. Ví dụ: chuỗi 49 sẽ bị ràng buộc dưới dạng chuỗi, dẫn đến 1Tạo SQL để tìm kiếm chỉ một giá trị. Để làm cho nó đúng, người ta cần các giá trị tách biệt, để làm cho một truy vấn trông giống như 2Do đó, đố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 50, người ta phải tạo một bộ 3S theo cách thủ công và đưa chúng vào truy vấn: 3Không thuận tiện lắm, nhưng so với MySQLI, nó ngắn gọn một cách tuyệt vời. Trong trường hợp có những người giữ chỗ khác trong truy vấn, bạn có thể sử dụng hàm 52 để tham gia tất cả các biến vào một mảng, thêm các biến khác của bạn dưới dạng mảng, theo thứ tự chúng xuất hiện trong truy vấn của bạn: 4Trong trường hợp bạn đang sử dụng các khoản 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 ra một chuỗi các giữ chỗ được đặt tên, ví dụ: 53. Vì vậy, mã sẽ là: 5May mắn thay, đối với những người 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 chúng tôi theo bất kỳ thứ tự nào. Bảo vệ bảng và tên trườngTrên Stack Overflow, tôi đã thấy số lượng người dùng PHP áp đảo triển khai mã PDO gây tử vong nhất, nghĩ rằng chỉ có 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 một nhà phát triển phải lọc chúng theo cách thủ công. Một bộ lọc như vậy thường được gọi là "danh sách trắng" (trong đó chúng tôi chỉ liệt kê các giá trị cho phép) trái ngược với "danh sách đen" trong đó 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 6Cách tiếp cận 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 7Có hai biến số này theo cách này sẽ giúp chúng an toàn 100% 8Cách tiếp cận tương tự phải được sử dụng mỗi khi bảng tên trường sẽ được sử dụng trong truy vấn. Một vấn đề với mệnh đề giới hạnMột vấn đề khác có liên quan đến mệnh đề SQL 54. Khi ở chế độ mô phỏng (theo mặc định), PDO thay thế trình giữ chỗ bằng dữ liệu thực tế, thay vì gửi riêng. Và với ràng buộc "lười biếng" (sử dụng mảng trong 7), PDO coi mọi tham số dưới dạng chuỗi. Do đó, truy vấn 56 đã chuẩn bị trở thành 57, đó là cú pháp không hợp lệ khiến truy vấn bị lỗi.Có hai giải pháp: Một là tắt thi đua (vì MySQL có thể sắp xếp tất cả các giữ chỗ đúng cách). Để làm như vậy, người ta có thể chạy mã này: 9Và các tham số có thể được giữ trong 7: 0Mộ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ố thích hợp: 1Một điều kỳ dị về 59: Vì một số lý do, nó không thực thi loại đúc. Do đó, sử dụng nó trên một số có loại chuỗi sẽ gây ra lỗi đã nói ở trên: 2Nhưng thay đổi 60 trong ví dụ thành 61 - và mọi thứ sẽ diễn ra suôn sẻ.Giao dịchĐể chạy 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 thức chính tắc:
Ngoại lệ là rất 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 những truy vấn không thành công, việc thực hiện sẽ bị dừng và di chuyển thẳng đến khối bắt, nơi toàn bộ giao dịch sẽ được quay lại. Vì vậy, một ví dụ điển hình sẽ giống như 3Xin lưu ý những điều quan trọng sau:
Gọi các thủ tục được lưu trữ trong PDOCó một điều về các thủ tục được lưu trữ mà bất kỳ lập trình viên nào vấp ngã lúc đầu: mọi quy trình được lưu trữ luôn trả về một tập kết quả bổ sung: một (hoặc nhiều) kết quả với dữ liệu thực tế và một kết quả chỉ 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ến hành truy vấn khác, thì "không thể thực hiện các truy vấn trong khi các truy vấn không bị truy vấn khác đang hoạt động" sẽ xảy ra lỗi, vì bạn phải xóa kết quả trống thêm đó trước. Do đó, sau khi gọi một quy trình được lưu trữ nhằm trả về chỉ một bộ kết quả, chỉ cần gọi 68 một lần (tất nhiên sau khi tìm nạp tất cả dữ liệu được trả về từ câu lệnh, hoặc nó sẽ bị loại bỏ):one extra result set: one (or many) results with actual data and one just empty. Which means if you try to call a
procedure and then proceed to another query, then "Cannot execute queries while other unbuffered queries are active" error will occur, because you have to clear that extra empty result first. Thus, after calling a stored procedure that is intended to return only one result set, just call 68 once (of course after fetching all the returned data from statement, or it will be discarded): 4Trong khi đối với các quy trình được lưu trữ trả về nhiều kết quả, nhưng hành vi sẽ giống như với nhiều truy vấn thực thi: 5Tuy nhiên, như bạn có thể thấy ở đây là một thủ thuật khác phải được sử dụng: hãy nhớ rằng bộ kết quả bổ sung đó? Về cơ bản, nó trống rỗng đến mức ngay cả một nỗ lực để tìm nạp từ nó sẽ tạo ra một lỗi. Vì vậy, chúng tôi không thể sử dụng chỉ 69. Thay vào đó, chúng tôi cũng phải kiểm tra kết quả trống. Với mục đích đó 70 chỉ là tuyệt vời.Tính năng này là một trong những khác biệt thiết yếu giữa các thư viện MySQL cũ và hiện đại: sau khi gọi một quy trình được lưu trữ với 0, 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, bởi vì không có chức năng 72 cho 73. Người ta phải đóng kết nối và sau đó mở một cái mới một lần nữa để chạy các truy vấn khác sau khi gọi một thủ tục được lưu trữ.Gọi một thủ tục được lưu trữ là một trường hợp hiếm hoi trong đó việc sử dụng 4 là hợp lý, vì đó là cách duy nhất để xử lý các tham số 75 và 76. Ví dụ có thể được tìm thấy trong chương thủ công tương ứng. Tuy nhiên, đối với MySQL, nó không hoạt động. Bạn phải dùng đến một biến SQL và một cuộc gọi thêm.for mysql it doesn't work. You have to resort to an SQL variable and an extra call.Lư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 quy trình được bảo vệ đối với Microsoft SQL Server, hãy sử dụng định dạng sau 6ở đâu ? Dấu hiệu là người giữ chỗ. Lưu ý rằng không nên sử dụng niềng răng 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 các truy vấn đột biến trong cùng một câu lệnh, thông qua truy vấn () hoặc 77. Để truy cập kết quả của các truy vấn hậu quả, người ta phải sử dụng 68: 7Trong vòng lặp này, bạn sẽ có thể thu thập tất cả các thông tin liên quan từ mọi truy vấn, như các hàng bị ảnh hưởng, ID hoặc lỗi do tự động tạo ra. Điều quan trọng là phải hiểu rằng tại điểm 7 PDO sẽ báo cáo lỗi cho truy vấn đầu tiên. Nhưng nếu xảy ra lỗi tại bất kỳ truy vấn hậu quả nào, để có được lỗi đó, người ta phải lặp lại kết quả. Mặc dù có một số ý kiến không biết gì, 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 chỉ không thể nắm bắt toàn bộ vấn đề và không hiểu 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 bộ 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 kết quả, từng cái một. Nhưng để có thể ném lỗi ngay lập tức, PDO sẽ phải lặp lại tự động và do đó loại bỏ một số kết quả. Đó sẽ là một điều vô nghĩa rõ ràng.for the first query only. But if error occurred at any of consequent queries, to get that error one has to iterate over results. Despite some ignorant opinions, PDO can not and should
not report all the errors at once. Some people just cannot grasp the problem at whole, and don't understand that error message is not the only outcome from the query. There could be a dataset returned, or some metadata like insert id. To get these, one has to iterate over resultsets, one by one. But to be able to throw an error immediately, PDO would have to iterate automatically, and thus discard some results. Which would be a clear nonsense.Không giống như 80 PDO không thực hiện cuộc gọi không đồng bộ, vì vậy bạn không thể "Fire và quên" - gửi phần lớn các truy vấn đến MySQL và kết nối gần, PHP sẽ đợi cho đến khi truy vấn cuối cùng được thực thi.Chế độ thi đua. PDO :: attr_emulation_preparesMột trong những tùy chọn cấu hình PDO gây tranh cãi nhất là 81. Nó làm gì? PDO có thể chạy các truy vấn của bạn theo hai cách:
Cả hai phương pháp đều có nhược điểm và lợi thế của chúng, và - tôi phải nhấn mạnh vào nó - cả hai đều an toàn như nhau, nếu được sử dụng đúng cách. Mặc dù giai điệu khá hấp dẫn của bài viết phổ biến trên Stack Overflow, cuối cùng, nếu bạn đang sử dụng các phiên bản được hỗ trợ của PHP và MySQL đú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ư nó hiển thị trong ví dụ trên và các câu lệnh được chuẩn bị được mô phỏng của bạn sẽ an toàn như những câu thực tế.equally secure, if used properly. Despite rather appealing tone of the popular article on Stack Overflow, in the end it says that if you are using supported versions of PHP and MySQL properly, you are 100% safe. All you have to do is to set encoding in the DSN, as it shown in the example above, and your emulated prepared statements will be as secure as real ones. Lưu ý rằng khi chế độ gốc được sử dụng, dữ liệu không bao giờ xuất hiện trong truy vấn, được phân tích cú pháp bởi động cơ, với tất cả các giữ chỗ tại chỗ. Nếu bạn đang xem xét nhật ký truy vấn MySQL cho truy vấn đã chuẩn bị của bạn, bạn phải hiểu rằng đó chỉ là một truy vấn nhân tạo chỉ được tạo ra cho mục đích ghi nhật ký, nhưng không phải là một truy cập thực sự đã được thực hiện.the data is never appears in the query, which is parsed by the engine as is, with all the placeholders in place. If you're looking into Mysql query log for your prepared query, you have to understand that it's just an artificial query that has been created solely for logging purpose, but not a real one that has been executed. 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 được 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ỉ phải được ràng buộc một lần. Vì một số lý do tối nghĩa, chức năng này bị vô hiệu hóa khi chế độ mô phỏng bị tắt: 8Ngoài ra, khi mô phỏng là 83, 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 được chuẩn bị gốc chỉ hỗ trợ một số loại truy vấn nhất định, 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à 83. Mã sau sẽ trả về tên bảng trong chế độ mô phỏng và lỗi nếu không: 9Khi chế độ mô phỏng bị tắtNgười ta có thể bận tâm không 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 đó, ngay cả chuỗi có thể được ràng buộc để giới hạn các tham số, như nó đã được ghi nhận 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-đa dạng đơn. Thật khó để quyết định chế độ nào phải được ưu tiên, nhưng vì khả năng sử dụng, tôi thà biến nó 86, để tránh một rắc rối với mệnh đề 54. Các vấn đề khác có thể được coi là không đáng kể khi so sánh.Mysqlnd và truy vấn đệ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 88, thay thế máy khách 89 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 theo sau:Có một thứ gọi là truy vấn đệm. Mặc dù bạn có thể không nhận thấy nó, nhưng bạn đã sử dụng chúng tất cả các cách. 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 hầu như miễn phí, các phiên bản hiện đại được xây dựng 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ộ là về một kết quả, là viết tắt của tất cả các dữ liệu được tìm thấy bởi truy vấn. 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: được đệm và không bị ảnh hưởng. Khi phương thức được đệm được sử dụng, tất cả dữ liệu được trả về bởi truy vấn sẽ được sao chép trong bộ nhớ của tập lệnh. Trong khi ở chế độ không có máy chủ, máy chủ cơ sở dữ liệu sẽ cung cấp từng hàng được tìm thấy từng hàng.gets copied in the script's memory at once. While in unbuffered mode a database server feeds the found rows one by one. Vì vậy, bạn có thể nói rằng ở chế độ đệm, một kết quả luôn luôn gây gánh nặng bộ nhớ trên máy chủ ngay cả khi tìm nạp 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 máy khách dựa trên LibMysQL cũ được sử dụng, vấn đề này không làm phiền quá nhiều PHP, vì bộ nhớ được tiêu thụ bởi kết quả không được tính trong 90 và 91.Nhưng với MySQLND, mọi thứ đã thay đổi và kết quả được trả về bởi truy vấn được đệm sẽ được tính vào cả 90 và 91, bất kể bạn chọn cách nào để có được kết quả: 0sẽ cho bạn 1Điều đó có nghĩa là với truy vấn đệm, bộ nhớ được tiêu thụ ngay cả khi bạn đang tìm nạp từng hàng một!even if you're fetching rows one by one! 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ự lớn, luôn luôn đặt 94 thành 95.Tấ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 sẽ không truy xuất tất cả các hàng đã chọn từ truy vấn không bị ảnh hưởng, sẽ không thể chạy bất kỳ truy vấn nào khác so với kết nối cơ sở dữ liệu HTE. Và một vài cái nhỏ,
Những bài viết liên quan:
|