Cách mã trình tạo số tăng tự động trong php

Ghi chú. Bài đăng này đã hơn một năm tuổi và vì vậy thông tin ở đây có thể đã lỗi thời. Nếu bạn phát hiện ra điều gì đó, vui lòng để lại nhận xét và chúng tôi sẽ cố gắng khắc phục

  • Cách mã trình tạo số tăng tự động trong php
    Chia sẻ cái này
  • Cách mã trình tạo số tăng tự động trong php
    Tweet cái này đi
  • Cách mã trình tạo số tăng tự động trong php
    Chia sẻ cái này

Cách đây một thời gian, tôi đang thực hiện một số thay đổi đối với một trang web và bắt gặp một khối mã khiến tôi ngây người nhìn vào màn hình của mình. Trang web tôi đang làm việc là một trang web xây dựng tùy chỉnh, được tạo bởi một nhà phát triển khác tại công ty mà tôi đang làm việc vào thời điểm đó. Tôi chưa bao giờ làm một PHP. CSI trên trang web này trước đây nhưng hãy nhớ rằng tôi đã rất ngạc nhiên với những gì tôi tìm thấy vào thời điểm đó nên tôi đã ghi chú lại để tham khảo sau này. Gần đây tôi đã suy nghĩ về cách tiếp cận phân tích mã

Mã tôi tìm thấy nằm trong một phương thức chèn một mục vào bảng cơ sở dữ liệu. Vì một số lý do mà tôi không thể hiểu được, nhà phát triển đã chọn không sử dụng ID gia tăng tự động và thay vào đó đã phát triển một phương pháp về cơ bản quyết định ngẫu nhiên số ID cho mặt hàng

Tôi không thể dán toàn bộ khối mã vào đây, nhưng tôi có thể bao gồm vùng mã khiến tôi phải vò đầu bứt tai

do {
  $ref = mt_rand(1, pow(2, 31)-1); // Generate a ref number
  $result = $mysqli->query("SELECT id FROM tblrefs WHERE ref = {$ref}");
} while($result->num_rows == 0);

Nếu bạn đủ kinh nghiệm, có lẽ bạn sẽ nhận ra vấn đề ở đây. Tôi nghĩ có thể là một ý kiến ​​hay để xem qua mọi thứ đang diễn ra tại đây

  • Đầu tiên chúng ta nhập một vòng lặp do-while. Điều này sẽ tiếp tục chạy trong khi điều kiện của while là đúng
  • Tiếp theo, chúng tôi tạo một số tham chiếu và lưu trữ nó trong biến $ref. Đây là một số ngẫu nhiên (được tạo bởi hàm mt_rand()) nằm giữa 1 và số lớn nhất của một số nguyên 32 bit (được tính bằng cách nâng 2 lên lũy thừa của 31 và trừ đi 1)
  • Dòng tiếp theo là một truy vấn SQL để tìm hiểu xem số ngẫu nhiên mà chúng tôi tạo đã tồn tại trong bảng cơ sở dữ liệu mà chúng tôi quan tâm hay chưa
  • Điều kiện trong khi sau đó được xem xét. Nếu số hàng được trả về từ truy vấn SQL không phải là 0 thì chúng tôi đã sử dụng số đó trong cơ sở dữ liệu và vì vậy chúng tôi cần lặp lại để tạo lại số, v.v. Nếu nó là 0 thì số mới và chúng ta có thể thoát khỏi vòng lặp do-while và tiếp tục chèn mục vào cơ sở dữ liệu

Điều này có một vài vấn đề

  • Để chèn bất cứ thứ gì vào bảng, trước tiên chúng ta cần truy vấn cơ sở dữ liệu để xem liệu chúng ta có ID phù hợp không
  • Vì một số lý do, chúng tôi đang tìm ra giá trị của một số nguyên tối đa bằng cách sử dụng toán học chứ không phải hằng số PHP tích hợp PHP_MAX_INT. Tính nhanh giá trị này bằng cách tăng 2 lũy thừa 31 thực sự là một phép toán khá tốn kém. Tại sao nhà phát triển quyết định không sử dụng PHP_MAX_INT ở đây nằm ngoài khả năng của tôi, nhưng đó không phải là vấn đề chính ở đây
  • Vì chúng tôi đang tạo một số ngẫu nhiên nên ngày càng có nhiều khả năng chúng tôi sẽ tạo một số đã tồn tại. Điều này có nghĩa là càng có nhiều mục trong cơ sở dữ liệu thì càng có nhiều khả năng chúng tôi sẽ tìm thấy một mục hiện có trong cơ sở dữ liệu và phải tạo lại số ngẫu nhiên của mình
  • Vì đây là một trang web bận rộn với một số biên tập viên đang viết nội dung nên có khả năng khối mã này sẽ tạo ra hai ID giống hệt nhau và cố gắng chèn chúng vào cơ sở dữ liệu cùng một lúc.  

Để kiểm tra nhanh, tôi quyết định xem phương pháp này sẽ mất bao lâu để tìm một số trùng lặp từ giá trị được tạo ngẫu nhiên. Tôi tập hợp một tập lệnh nhanh để tạo các số ngẫu nhiên bằng cách sử dụng cùng một phương pháp như trên cho đến khi tìm thấy một bản sao, tại thời điểm đó, chúng tôi đếm số lượng giá trị được tạo và bắt đầu lại

for ($outer = 0; $outer <= 100000; ++$outer) {
  // Reset refs array.
  $refs = array();

  do {
    // Generate the random number.
    $ref = mt_rand(1, pow(2, 31)-1);

    // Has it already been generated.
    if (in_array($ref, $refs)) {
      // Number already exists, record clash and break the loop.

      // Count the number of random numbers generated.
      $count = count($refs);

      // Record data to file.
      file_put_contents('counts.txt', $count . "\n", FILE_APPEND);

      // Break out while loop.
      break;
    }

    // Loop not broken, add the number to the list and continue.
    $refs[] = $ref;

  } while(1==1);
}

Sau khi chạy tập lệnh này (mất một lúc để hoàn thành), tôi đã chạy một số phân tích nhanh về tập lệnh đó. Đây là kết quả

Min: 824
Max: 200448
Mean: 58774.052132701
Standard Deviation: 8117.1541955524

Vì vậy, hóa ra là chúng tôi chỉ cần tạo vài nghìn mặt hàng trước khi chúng tôi bắt đầu xung đột số lượng. Tập lệnh này chỉ xem xét xung đột đầu tiên, nhưng rõ ràng là chúng tôi có khả năng tạo ID trùng lặp trong cơ sở dữ liệu nếu tình trạng này tiếp diễn càng lâu

Một cách tiếp cận tốt hơn

Trong khi cách tiếp cận này hoạt động, một giải pháp tốt hơn nhiều là chỉ cần sử dụng hệ thống tăng tự động hiện có trong MySQL. Tôi vẫn không thể hiểu tại sao nhà phát triển ban đầu không sử dụng hệ thống này

Ngay cả khi họ không sử dụng gia số tự động, họ vẫn có thể sử dụng thuật toán bảng băm để tạo ID cho mặt hàng. Điều này có thể được thực hiện bằng cách tạo hàm băm bằng cách sử dụng SHA của thông tin mà chúng tôi sắp đưa vào. Trong trường hợp không chắc xảy ra xung đột, cơ sở dữ liệu sẽ trả về lỗi, tại thời điểm đó, chúng tôi sẽ cần tìm ra một hàm băm mới. Ngay cả trong tình huống này, nó vẫn sẽ hiệu quả hơn là chỉ định ngẫu nhiên một ID cho một giá trị và xem liệu điều đó có tồn tại trước không

Sau khi mã đã đi theo lộ trình này, vấn đề là rất khó để hoán đổi sang một phương thức khác mà không cần gỡ nhiều lần. Khi tôi nhận thấy mã này, tôi đã báo cho người quản lý của mình biết mã này là một hoạt động tốn kém và có thể gây nguy hiểm và chúng tôi nên dành chút thời gian để khắc phục mã đó. Tôi đã rời công ty không lâu sau đó, nhưng tôi đã thấy trang web được chuyển sang một nền tảng khác nên tôi có thể yên tâm nói rằng mã này không còn được sản xuất nữa

Thêm trong loạt bài này

  • PHP. CSI - Nhận Giá Bằng Pence

PHP. CSI

  • Chia sẻ cái này
  • Tweet cái này đi
  • Chia sẻ cái này

Cách mã trình tạo số tăng tự động trong php

Được viết bởi. Philip Norton

Phil là người sáng lập và quản trị viên của #. viết mã và là một chuyên gia CNTT làm việc ở Tây Bắc Vương quốc Anh. Tốt nghiệp năm 2003 tại Đại học Aberystwyth với bằng Thạc sĩ Khoa học Máy tính Phil trước đây đã từng làm quản trị viên cơ sở dữ liệu, trên bàn trợ giúp CNTT, huấn luyện viên hệ thống, kiến ​​trúc web, tư vấn khả năng sử dụng, blogger và chuyên gia SEO. Phil có nhiều kinh nghiệm xây dựng và duy trì các trang web PHP cũng như làm việc với các công nghệ liên quan như JavaScript, HTML, CSS, XML, Flex, Apache, MySQL và Linux

Bạn muốn biết thêm?

Hãy để chúng tôi giúp. Thuê chúng tôi để cung cấp dịch vụ đào tạo, tư vấn, xử lý sự cố và hơn thế nữa

hỗ trợ chúng tôi

Hãy ủng hộ chúng tôi và cho phép chúng tôi tiếp tục viết bài

Cách mã trình tạo số tăng tự động trong php
Trở thành người bảo trợ

Cách mã trình tạo số tăng tự động trong php
Mua cho tôi một ly cà phê

Bình luận

liên kết cố định

Anh ấy đã sử dụng điều này có thể là do để tạo một số ngẫu nhiên duy nhất cho sản phẩm (thay vì hiển thị cho người dùng khóa chính) sẽ hiển thị ở cuối người dùng và từ back-end sẽ có khóa chính để ánh xạ rằng .
Có nhưng cái này khá đắt.

rajesh (Thứ Tư, 11/09/2019 - 10. 05)

liên kết cố định

Anh ấy đã sử dụng điều đó có thể là do để cung cấp cho sản phẩm một số duy nhất thay vì hiển thị cho anh ấy khóa chính