Tuần trước David Walsh đã đăng về việc xác thực các giá trị số và chữ số bằng PHP trên blog tuyệt vời của anh ấy. Tôi đã đăng nhận xét của riêng mình về bài đăng cụ thể của anh ấy nhưng chúng không bao giờ xuất hiện nên tôi quyết định đăng phản hồi tốt hơn tại đây
Điểm quan trọng trong bài đăng của David là anh ấy cần có khả năng xác thực giữa việc tìm kiếm một giá trị số [có thể là số dấu phẩy động và do đó chứa dấu thập phân] và liệu một số chỉ chứa các chữ số
Giải pháp của anh ấy là thế này
/* numeric, decimal passes */ function validate_numeric[$variable] { return is_numeric[$variable]; } /* digits only, no dots */ function is_digits[$element] { return !preg_match ["/[^0-9]/", $element]; }
Như tôi đã lưu ý trong nhận xét của mình [không được xuất bản], tôi không chắc tại sao bạn lại bọc is_numeric[] vào hàm validate_numeric[] của anh ấy khi tất cả những gì nó làm là gọi is_numeric[]. Tại sao không chỉ gọi is_numeric[] thay thế?
Mặt khác, hàm is_digits[] thực sự khá tốt. Ban đầu tôi nghĩ có thể có một số vấn đề với nó nhưng nó hoạt động tốt nhưng có một giải pháp thay thế đơn giản hơn
is_integer – không tốt
Trong nhận xét của mình, tôi đã gợi ý rằng anh ấy có thể sử dụng hàm is_integer[] miễn là giá trị được chấp nhận nằm trong phạm vi kiểu số nguyên và các giá trị dương và âm đều được chấp nhận. Tất nhiên, giá trị chỉ có chữ số có thể không nằm trong phạm vi số nguyên, ví dụ: is_integer[12345678901234567890] sẽ trả về false nhưng chỉ chứa số
Vấn đề với giả định ban đầu của tôi là trong dữ liệu PHP được gửi từ biểu mẫu *does* chỉ chứa các chữ số và *is* trong phạm vi số nguyên sẽ vẫn trả về false từ is_integer[] vì nó sẽ được coi là một chuỗi. Ví dụ
Và sau đó làm điều này khi biểu mẫu được gửi
echo [int]is_integer[[int]$_POST['foo']];
sẽ in 0, nghĩa là sai. D'oh. Ngoài ra, một số nguyên có thể chứa - nếu nó là một giá trị âm thì -123 sẽ trả về true mặc dù nó chứa nhiều hơn chỉ các chữ số
ctype_digit – không tốt hơn nhiều
Một giải pháp thay thế khác là hàm ctype_digit[] giúp tiết kiệm việc phải loay hoay với các biểu thức thông thường. ctype_digit kiểm tra xem tất cả các ký tự trong giá trị được truyền vào có phải là số không. Chỉ các số từ 0 đến 9 là hợp lệ và không thành vấn đề nếu giá trị được nhập dưới dạng chuỗi, đó là điều sẽ xảy ra từ một bài đăng biểu mẫu
Tuy nhiên, ctype_digit nó yêu cầu đầu vào là một chuỗi và sẽ trả về false nếu giá trị được truyền vào là một số nguyên…
Ví dụ
var_dump[ctype_digit[123]]; var_dump[ctype_digit['123']]; var_dump[ctype_digit[12345678901234567890]]; var_dump[ctype_digit['12345678901234567890']];
Những màn hình này
bool[false] bool[true] bool[false] bool[true]
Bạn sẽ có thể sử dụng [string], strval[], v.v. để truyền giá trị dưới dạng chuỗi trước rồi chuyển nó tới ctype_digit nhưng tôi thấy nếu số quá lớn thì nó vẫn không hoạt động
Ví dụ: bốn cái đầu tiên bên dưới trả về true, nhưng cái cuối cùng trả về false
ctype_digit[strval[12345678901]]; ctype_digit[strval[123456789012]]; ctype_digit[strval[1234567890123]]; ctype_digit[strval[12345678901234]]; ctype_digit[strval[123456789012345]];
Sử dụng biểu thức chính quy
Vì vậy, suy nghĩ ban đầu của tôi là chỉ sử dụng is_integer[] và một người khác đã đề xuất sử dụng ctype_digit nhưng hóa ra sử dụng biểu thức chính quy với preg_match lại là giải pháp tốt nhất. Chỉ cần nhớ khi sử dụng các biểu thức chính quy với PHP để sử dụng các hàm preg* chứ không phải các hàm ereg* vì các hàm sau không được dùng trong PHP 6
Hãy xem xét nhiệm vụ đơn giản này. bạn nhận được một biến từ một nguồn không xác định [biểu mẫu, cơ sở dữ liệu, v.v.] phải là một số nguyên hợp lệ. Nó có thể là một số nguyên dương hoặc âm và được lưu trữ trong một chuỗi hoặc một số nguyên, nhưng nó phải là một số nguyên thực được tạo thành từ các chữ số. Đây là danh sách kiểm tra của chúng tôi
- Chỉ xác thực số nguyên, không phải số float, chuỗi, mảng hoặc booleans
- Cho phép số nguyên dương và âm
- Không cho phép ký hiệu thập lục phân, kỹ thuật và các ký hiệu khác
- Cho phép chuỗi và int làm đầu vào
PHP cung cấp cho chúng ta các cách sau để thực hiện tác vụ này gần như nhưng không hoàn toàn
is_int
hoặcis_integer
is_numeric
- biểu thức chính quy
ctype_digit
filter_var
Giả sử bạn muốn xác thực rằng một biến phù hợp với hóa đơn. Bạn làm nghề gì?
Phản xạ đầu tiên của bạn là thử is_int
, còn được gọi là is_integer
, nhưng bạn đã nhầm. Các hàm này sẽ trả về false cho một chuỗi, ngay cả khi nó chứa một số nguyên. Trước tiên, bạn có thể truyền chuỗi của mình thành một số nguyên bằng
if[ctype_digit[ltrim[[string]$int, '-']]]{
echo["This is a valid integer"];
}
1, sau đó áp dụng is_int
, nhưng vì PHP sẽ truyền khá nhiều thứ mà không đưa ra lỗi, nên bạn có thể là một mảng và dù sao thì nó cũng sẽ truyền thành 0 hoặc 1Khỏe. Điều đó có ý nghĩa. Bây giờ thì sao về is_numeric
?
Điều đó để lại cho chúng tôi ba lựa chọn. ctype_digit
, filter_var
và biểu thức chính quy. Sử dụng các biểu thức thông thường sẽ chậm, không thể đọc được và quá mức cần thiết cho một tác vụ đơn giản như vậy, vì vậy hãy xem ctype_digit
. ctype_digit
tương đương với
1, điều này thật tuyệt, ngoại trừ việc nó không cho phép giá trị âm và nó chỉ hoạt động với chuỗiĐiều đó không hoàn toàn dễ đọc, vì vậy hãy thử tùy chọn cuối cùng của chúng ta, filter_var
. Có vẻ như filter_var
là đối sánh gần nhất, nhưng nó không hoàn hảo vì nó cho phép
4, nhưng chặn
5 [đã sửa trong PHP 5. 4. 11],
6 và
7. Đối với hầu hết các trường hợp, có vẻ như filter_var
vẫn là chức năng tốt nhất để sử dụngNếu những nhược điểm này phù hợp với bạn, thì đây là đoạn mã bạn nên sử dụng
if[filter_var[$value, FILTER_VALIDATE_INT] !== false]{
echo["This is a valid integer"];
}
Nếu bạn cũng muốn cho phép các giá trị như
5,
6 và
7, nhưng muốn chặn
4, hãy sử dụng ctype_digit
như thế này để thay thếif[ctype_digit[ltrim[[string]$int, '-']]]{
echo["This is a valid integer"];
}
Đúng rồi. Đây là cách bạn kiểm tra một số nguyên trong PHP. Đơn giản nhỉ?
Đây là thử nghiệm nhanh mà tôi đã sử dụng trên máy chủ thử nghiệm cũ nát của mình. Như bạn có thể thấy, ctype_digit
là phương pháp duy nhất hoạt động 100% thời gian, mặc dù nó hoàn toàn không thể đọc được