2010-11-04 4 views
7

Tôi đang viết mã cho bảng sắp xếp, trong đó nhấp vào liên kết trong tiêu đề thay đổi ORDER BY được thực hiện khi tạo tập hợp kết quả tìm kiếm (trường hợp không có thứ tự hợp lệ theo nguyên nhân truy vấn không được chạy theo thứ tự bởi và chỉ trả về kết quả theo thứ tự cơ sở dữ liệu trả về. điều này được thiết kế). Mã này được viết trong khuôn khổ do nhà tuyển dụng của tôi cung cấp.Hành vi lẻ trong câu lệnh chuyển đổi

Để xác thực phần ORDER BY của truy vấn, tôi chạy đầu vào thông qua hàm xác thực sau.

<?php 
function sortMode ($name) 
{ 
    $mode = ''; 
    switch ($name) 
    { 
     case 'resnum' : $mode = 'b_resnum';   break; 
     case 'state' : $mode = 'st_id';    break; 
     case 'name'  : $mode = 'lastname, firstname'; break; 
     case 'phone' : $mode = 'phone';    break; 
     case 'email' : $mode = 'email';    break; 
     case 'opened' : $mode = 'cs_created';   break; 
     default   : $mode = '';     break; 
    } 
    return ($mode); 
} 
?> 

Đang thử nghiệm Tôi phát hiện ra rằng nếu không có tham số nào được cung cấp thì thứ tự sắp xếp sẽ được tiếp tục. Sau khi thử nghiệm một số, tôi phát hiện ra rằng bộ lọc được xây dựng trong khung sẽ gây ra một yêu cầu cho một biến uninitialized chẳng hạn như một tham số GET unset để trả về số nguyên 0. Nếu mã trên được cho ăn 0 số nguyên như đầu vào, nó sẽ luôn luôn theo sau con đường thực hiện có sẵn cho nó.

Theo một thử nghiệm tôi đã cố gắng sắp xếp lại thứ tự của các trường hợp trong câu lệnh switch, và tìm thấy bất cứ điều gì là ở phía trên sẽ là những gì đã được thực hiện nếu chức năng này đã được thông qua một 0.

Giải pháp cho vấn đề là sử dụng switch (strval($name)) để vấn đề cụ thể được giải quyết, nhưng bây giờ tôi tò mò về hành vi chung của các câu lệnh chuyển đổi PHP. Liệu hành vi tôi đã chứng kiến ​​hành vi đúng đắn của PHP? Có một số lỗi trong PHP đó gây ra điều này, hoặc tôi đã thực hiện một lỗi trong mã của tôi mà tôi không biết?

Trả lời

12

Đó là vì cách php phôi chuỗi thành ints. Khi bạn vượt qua trong một 0, bạn đang yêu cầu nó làm một so sánh số nguyên, do đó, nó sẽ chuyển đổi tất cả các khóa trường hợp của bạn thành số nguyên. Khi php đặt một số string vào một số int, nó sẽ tìm số thực tại đầu chuỗi và gobbles số cho đến khi số lần truy cập không phải là số. Kể từ chuỗi "resnum" không có số, nó sẽ trả về 0. Xem ở đây:

php > echo (int)"100"; 
100 
php > echo (int)"300 dogs"; 
300 
php > echo (int)"resnum"; 
0 
php > echo (int)"resnum 100"; 
0 

Vì tất cả những chuỗi đúc 0, trường hợp đầu tiên sẽ đánh giá để true từ 0 == 0.

Resources:
String conversion to numbers
Type comparison tables


nitpick thời gian. Khi bạn đang thực hiện các câu lệnh case đơn giản để ánh xạ một chuỗi tới một chuỗi, hãy sử dụng một mảng. Đó là rõ ràng hơn nhiều và thực sự nhanh hơn:

function sortMode ($name) 
{ 
    $modeMap = array(
     'resnum' => 'b_resnum', 
     'state' => 'st_id', 
     'name'  => 'lastname, firstname', 
     'phone' => 'phone', 
     'email' => 'email', 
     'opened' => 'cs_created' 
    ); 

    return isset($modeMap[$name]) ? $modeMap[$name] : ''; 
} 

Nếu $name được thiết lập trên bản đồ, chúng ta trả về giá trị quan trọng mà được ánh xạ tới. Nếu không, chúng tôi trả lại một chuỗi rỗng, thay thế vị trí của trường hợp default.

Là phần thưởng, bạn sẽ nhận thấy lỗi trước đó nếu bạn đã thực hiện phương pháp trên, vì nó sẽ cố gắng truy cập $modeMap[0] và có thể đã trả về trường hợp mặc định của bạn thay thế.

+4

+1 dang! Đây là hành vi nguy hiểm. –

+1

PHP có thể là tà ác thuần túy. Việc chuyển đổi int tự động này đã gây ra nhiều thất vọng hơn thời gian "đã lưu". – GWW

+1

Ít nhất trong một nếu có thể sử dụng === và ngăn chặn điều này, nhưng tiếc là chuyển đổi/trường hợp là một == – UnkwnTech

0

Điểm mấu chốt là câu lệnh switch() thực hiện so sánh giữa tham số và nhãn. Điều đó có nghĩa là bạn phải đối phó với các quy tắc so sánh và nhập kiểu PHP.Chỉ cần nhìn thấy một số ví dụ:

<?php 

var_dump(''==0); // bool(true) 
var_dump('foo'==0); // bool(true) 
var_dump('0'==0); // bool(true) 
var_dump('0m'==0); // bool(true) 
var_dump('01'==0); // bool(false) 

Các tài liệu tham khảo có thể được tìm thấy tại địa chỉ:

Khởi tạo một tham số GET unset 0 là khá quyết định thiết kế kỳ lạ. Bạn nên đối phó với trường hợp cụ thể đó theo một cách riêng biệt để làm rõ rằng đây là một tình huống đặc biệt:

if($name===0){ 
    return ''; 
} 
switch($name){ 
    // ... 
}