2011-10-04 34 views
30

Đây không phải là một vấn đề lớn đối với tôi (theo như tôi biết), đó là nhiều hơn một cái gì đó mà tôi quan tâm. Nhưng sự khác biệt chính, nếu có, sử dụng is_numeric trên preg_match (hoặc ngược lại) để xác thực giá trị nhập của người dùng.PHP is_numeric hoặc preg_match 0-9 xác nhận

Ví dụ Một:

<?php 
    $id = $_GET['id']; 
    if (!preg_match('/^[0-9]*$/', $id)) { 
     // Error 
    } else { 
     // Continue 
    } 
?> 

Ví dụ thứ hai:

<?php 
    $id = $_GET['id']; 
    if (!is_numeric($id)) { 
     // Error 
    } else { 
     // Continue 
    } 
?> 

tôi giả sử cả hai làm giống hệt nhau nhưng có bất kỳ sự khác biệt cụ thể mà có thể gây ra vấn đề sau bằng cách nào đó? Có một "cách tốt nhất" hay cái gì đó tôi không nhìn thấy mà làm cho họ khác nhau.

Trả lời

49

is_numeric() kiểm tra xem giá trị có phải là số hay không. Nó không nhất thiết phải là một số nguyên mặc dù nó có thể là một số thập phân hoặc một số trong ký hiệu khoa học.

Ví dụ preg_match() bạn chỉ được cung cấp séc rằng giá trị chứa các chữ số từ 0 đến 9; bất kỳ số nào trong số đó và theo bất kỳ trình tự nào.

Lưu ý rằng cụm từ thông dụng bạn đã đưa ra cũng không phải là trình kiểm tra số nguyên hoàn hảo, cách bạn đã viết.Nó không cho phép âm bản; nó cho phép một chuỗi có độ dài bằng 0 (nghĩa là không có chữ số nào cả, có lẽ không nên là hợp lệ?), và nó cho phép số có số 0 đứng đầu, một lần nữa có thể không phải là số dự định.

[EDIT]

Theo nhận xét của bạn, một biểu hiện thường xuyên hơn có thể trông như thế này:

/^[1-9][0-9]*$/ 

Điều này buộc các chữ số đầu tiên chỉ có từ 1 đến 9, vì vậy bạn không thể có số 0 đứng đầu. Nó cũng buộc nó phải dài ít nhất một chữ số, do đó giải quyết vấn đề chuỗi số không có độ dài.

Bạn không lo lắng về âm bản, do đó, đó không phải là vấn đề.

Bạn có thể muốn hạn chế số chữ số, vì khi mọi thứ đứng, nó sẽ cho phép các chuỗi quá lớn để được lưu trữ dưới dạng số nguyên. Để hạn chế điều này, bạn sẽ thay đổi sao thành một hạn chế chiều dài như vậy:

/^[1-9][0-9]{0,15}$/ 

này sẽ cho phép các chuỗi phải dài từ 1 đến 16 chữ số (tức là chữ số đầu tiên cộng với 0-15 chữ số thêm). Cảm thấy tự do để điều chỉnh các con số trong các dấu ngoặc nhọn cho phù hợp với nhu cầu của riêng bạn. Nếu bạn muốn một chuỗi có độ dài cố định, thì bạn chỉ cần chỉ định một số trong dấu ngoặc.

Hy vọng điều đó sẽ hữu ích.

+0

Vì vậy, với Regex bạn sẽ khắc phục vấn đề của số 0 đứng đầu như thế nào? Điều này có thể gây ra vấn đề cho tôi sau khi tất cả, vì đây là phương pháp tôi đã sử dụng. Nếu tôi chỉ muốn xác nhận rằng đó là một số nguyên (4,8,15,16,23,42,108 vv), không có số 0 đứng đầu, không có dấu thập phân, không âm, thì điều này sẽ đạt được như thế nào? – Joe

+0

@JoeMottershaw - Tôi sẽ chỉnh sửa câu trả lời để thêm thông tin .... – Spudley

+0

Cảm ơn bạn Spudley, đó là một lời giải thích rất rõ ràng - chắc chắn có một sự hiểu biết tốt hơn về sự khác biệt của họ. Có vẻ như tôi sẽ quay lại và điều chỉnh một số mã của tôi! :) – Joe

1

Nếu bạn đang chỉ kiểm tra xem đó có phải là số, is_numeric() là nhiều nhiều hơn tốt hơn tại đây. Nó dễ đọc hơn và nhanh hơn một chút so với regex.

Vấn đề với regex của bạn ở đây là nó sẽ không cho phép giá trị thập phân, vì vậy về cơ bản bạn vừa viết is_int() trong regex. Biểu thức chính quy chỉ nên được sử dụng khi có định dạng dữ liệu không chuẩn trong đầu vào của bạn; PHP có rất nhiều chức năng xác thực được xây dựng, thậm chí là email validator without regex.

+0

Tôi không nghĩ rằng 'is_int() 'làm những gì bạn nghĩ nó - nó thực sự kiểm tra kiểu của biến được kiểm tra; nó không phải là một trình xác nhận chuỗi. – Spudley

4

is_numeric sẽ chấp nhận "-0.5e + 12" làm ID hợp lệ.

5

Không hoàn toàn giống nhau.

Từ các tài liệu PHP của is_numeric:

'42' is numeric 
'1337' is numeric 
'1e4' is numeric 
'not numeric' is NOT numeric 
'Array' is NOT numeric 
'9.1' is numeric 

Với regex của bạn, bạn chỉ kiểm tra giá trị số 'cơ bản'.

Ngoài ra is_numeric() sẽ nhanh hơn.

+0

Vì vậy, bằng cách sử dụng 'is_numeric' để kiểm tra mục nhập bài đăng trên diễn đàn có tất cả ID duy nhất được chỉ định bởi' auto_increment', nó có thể gây ra sự cố vì cơ sở dữ liệu chỉ có số nguyên, số thập phân, ký hiệu, v.v. – Joe

+0

@Joe Mottershaw: trường hợp bạn sẽ sử dụng 'is_int()' – PeeHaa

+0

@JoeMottershaw: hoặc có lẽ tốt hơn bạn nên gõ nó vào một int: '$ id = (int) $ _REQUEST ['id']; ' – PeeHaa

7

is_numeric() cho phép bất kỳ hình thức số nào. nên 1, 3.14159265, 2.71828e10 là tất cả "số", trong khi regex của bạn nắm để tương đương với is_int()

+0

Không chắc chắn cách nó hoạt động trở lại' 11. Nhưng bây giờ 'is_int' và' is_integer' thực sự trả về false cho bất kỳ chuỗi đã cho nào – cvsguimaraes

3

is_numeric kiểm tra hơn:

Finds liệu biến nhất định là số. Các chuỗi số bao gồm dấu tùy chọn, số chữ số bất kỳ, phần thập phân tùy chọn và phần mũ tùy chọn. Như vậy + 0123.45e6 là một giá trị số hợp lệ. Ký hiệu thập lục phân (0xFF) cũng được phép nhưng không có dấu, phần thập phân và mũ.

10

Theo số http://www.php.net/manual/en/function.is-numeric.php, số không phải là một số giống như "+ 0123.45e6" hoặc "0xFF". Tôi nghĩ rằng đây không phải là những gì bạn mong đợi.

preg_match có thể chậm, và bạn có thể có một cái gì đó giống như 0000 hay 0051.

Tôi thích sử dụng ctype_digit (chỉ làm việc với các chuỗi, đó là ok với $ _GET).

<?php 
    $id = $_GET['id']; 
    if (ctype_digit($id)) { 
     echo 'ok'; 
    } else { 
     echo 'nok'; 
    } 
?> 
+0

Vì vậy, 'ctype_digit' chỉ kiểm tra các số được làm tròn, còn nếu đó là số dương hoặc số âm? Nó hoạt động như thế nào? – Joe

+0

Nó chỉ hoạt động với số dương, tôi nghĩ rằng nó có thể hữu ích cho một id (Tôi không có Id âm trong mã của tôi): var_dump (ctype_digit ('- 5')); // trả về false –

5

kiểm tra is_numeric cho dù đó là bất kỳ loại số, trong khi kiểm tra regex của bạn cho dù đó là một số nguyên, có thể với leading 0s. Đối với một id, được lưu trữ dưới dạng một số nguyên, có khả năng chúng ta sẽ không có các số 0 hàng đầu. Sau câu trả lời Spudley, chúng tôi có thể làm:

/^[1-9][0-9]*$/ 

Tuy nhiên, như Spudley lưu ý, chuỗi kết quả có thể là quá lớn để có thể lưu dưới dạng một ứng dụng 32-bit hoặc 64-bit giá trị số nguyên. Giá trị tối đa của một số nguyên 32 bit có chữ ký là 2,147,483,647 (10 chữ số) và giá trị tối đa của một số nguyên 64 bit có chữ ký là 9,223,372,036,854,775,807 (19 chữ số). Tuy nhiên, nhiều số nguyên 10 và 19 chữ số lớn hơn số nguyên 32 bit và 64 bit tối đa tương ứng. Một giải pháp regex chỉ đơn giản sẽ là:

/^[1-9][0-9]{0-8}$/ 

hoặc

/^[1-9][0-9]{0-17}$/ 

tương ứng, nhưng những "giải pháp" không hạnh hạn chế từng đến 9 và 19 số nguyên chữ số; hầu như không một kết quả thỏa mãn. Một giải pháp tốt hơn có thể giống như sau:

$expr = '/^[1-9][0-9]*$/'; 
if (preg_match($expr, $id) && filter_var($id, FILTER_VALIDATE_INT)) { 
    echo 'ok'; 
} else { 
    echo 'nok'; 
} 
1

Chức năng is_numeric của PHP cho phép nổi cũng như số nguyên. Đồng thời, hàm is_int quá nghiêm ngặt nếu bạn muốn xác nhận hợp lệ dữ liệu biểu mẫu (chỉ chuỗi). Do đó, bạn thường sử dụng các biểu thức chính quy tốt nhất cho việc này.

Nói đúng, số nguyên là số nguyên dương và âm, và cũng bao gồm số không. Đây là một biểu hiện thường xuyên cho việc này:?

/^ 0 $ |^[-] [1-9] [0-9] * $/

OR, nếu bạn muốn cho phép số không hàng đầu:

/^ [-] [0] | [1-9] [0-9] $/

Lưu ý rằng điều này sẽ cho phép các giá trị như -0000? , mà không gây ra vấn đề trong PHP, h nợ. (MySQL cũng sẽ truyền các giá trị đó là 0.)

Bạn cũng có thể muốn giới hạn độ dài của số nguyên để cân nhắc 32/64-bit PHP platform features và/hoặc khả năng tương thích của cơ sở dữ liệu. Ví dụ: để giới hạn độ dài của số nguyên thành 9 chữ số (không bao gồm ký hiệu tùy chọn), bạn có thể sử dụng:

/^ 0 $ |^[-]? [1-9] [0-9 ] {0,8} $/

0

trong khi đó, tất cả các giá trị trên sẽ chỉ hạn chế các giá trị để nguyên, vì vậy tôi sử dụng

/^[1-9][0-9\.]{0,15}$/ 

để cho phép các giá trị float quá.

0

Bạn có thể sử dụng mã này để xác nhận số:

if (!preg_match("/^[0-9]+$/i", $phone)) { 
     $errorMSG = 'Invalid Number!'; 
     $error = 1; 
    } 
Các vấn đề liên quan