2014-11-22 70 views
4

我正在使用PHP PDO通過JSON將對象檢索到iOS應用程序。 有一個包含事件對象的數據庫表。它有三個字段來存儲日,月和年。數據庫的所有者不想將日期存儲在日期字段中,這意味着我必須處理它。PHP PDO語句篩選記錄

該應用程序發送一個網址使用參數,就像這樣:

http://..hidden domain./myfile.php?dia_inicio=16&dia_final=15&mes_inicio=11&mes_final=12&ano_inicio=2014&ano_final=2015 

這意味着,我要尋找從16Nov2014到15Dec2015事件。

這是我的PHP代碼:

$sql = 'SELECT * FROM tbagenda WHERE (dia_evento => :di AND mes_evento = :mi AND ano_evento = :ai) OR (dia_evento <= :df AND mes_evento = :mf AND ano_evento = :af) '; 

    // use prepared statements, even if not strictly required is good practice 
    $stmt = $dbh->prepare($sql); 
    $stmt->bindParam(':di', $dia_inicio, PDO::PARAM_INT); 
    $stmt->bindParam(':df', $dia_final, PDO::PARAM_INT); 
    $stmt->bindParam(':mi', $mes_inicio, PDO::PARAM_INT); 
    $stmt->bindParam(':mf', $mes_final, PDO::PARAM_INT); 
    $stmt->bindParam(':ai', $ano_inicio, PDO::PARAM_INT); 
    $stmt->bindParam(':af', $ano_final, PDO::PARAM_INT); 
    // execute the query 
    $stmt->execute(); 

    // fetch the results into an array 
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC); 

    // convert to json 
    $json = json_encode($result); 

    // echo the json string 
    echo $json 

我應該如何改變我的說法,使其與日期一樣工作:16Nov2014到28Nov2014(同月),16Nov2014到5Dec2014(不同的月份,同年)和16Nov2014到2015年5月02日(不同年份)?

後來補充:

iOS的登錄顯示的URL發送到PHP文件:

recuperar_eventos_dia.php?dia_inicio=11&dia_final=26&mes_inicio=11&mes_final=11&ano_inicio=2014&ano_final=2014 

PHP部分:

$start = "$ano_inicio-$mes_inicio-$dia_inicio"; 
$end = "$ano_final-$mes_final-$dia_final"; 

// In the SQL, concatenate the columns to make a YYYY-MM-DD date string 
// and cast it to a MySQL DATE type. 
// That makes it possible to use BETWEEN 
$sql = 'SELECT 
    * 
FROM tbagenda 
WHERE STR_TO_DATE(CONCAT_WS('-', ano_evento, mes_evento, dia_evento), "%Y-%m-%d") 
    BETWEEN :start AND :end'; 

// Bind and execute the statement with 2 parameters: 
$stmt = $dbh->prepare($sql); 
$stmt->bindParam(':start', $start, PDO::PARAM_STR); 
$stmt->bindParam(':end', $end, PDO::PARAM_STR); 
$stmt->execute(); 

// fetch, etc... 
$result = $stmt->fetchAll(PDO::FETCH_ASSOC); 

     // convert to json 
     $json = json_encode($result); 

     // echo the json string 
     echo $json; 

而且現在從表tbagenda截圖: enter image description here

+1

_The所有者不希望存儲日期在日期field_ - 爲什麼不能過?至少要添加一個適當的日期字段,除了使這類問題容易處理外。 – 2014-11-22 03:07:51

+0

@MikeW,感謝您的評論,但它沒有幫助。 – novato 2014-11-22 03:13:58

回答

3

對不起,你卡在這個不幸的表結構。

我建議連接表的列以形成可用的日期字符串,並通過MySQL的內置函數STR_TO_DATE()將它們轉換爲日期值。對查詢字符串輸入值執行相同操作,以便與BETWEEN運算符進行適當的日期比較。

// Begin by concatenating the input values into single date strings YYYY-MM-DD 
$start = "$ano_inicio-$mes_inicio-$dia_inicio"; 
$end = "$ano_final-$mes_final-$dia_final"; 

// In the SQL, concatenate the columns to make a YYYY-MM-DD date string 
// and cast it to a MySQL DATE type. 
// That makes it possible to use BETWEEN 
$sql = "SELECT * 
     FROM tbagenda 
     WHERE STR_TO_DATE(CONCAT_WS('-', ano_evento, mes_evento, dia_evento), '%Y-%m-%d') 
      BETWEEN :start AND :end"; 

// Bind and execute the statement with 2 parameters: 
$stmt = $dbh->prepare($sql); 
$stmt->bindParam(':start', $start, PDO::PARAM_STR); 
$stmt->bindParam(':end', $end, PDO::PARAM_STR); 
$stmt->execute(); 

// fetch, etc... 
$result = $stmt->fetchAll(PDO::FETCH_ASSOC); 

字符串操作將影響此查詢的性能。如您所知,如果日期存儲爲適當的DATE,那麼MySQL將不需要將它們投入進行比較。他們也可以被索引。

還要注意,我沒有包含日期​​字符串的驗證。您可能會考慮在執行查詢之前檢查它們以確保它們生成有效的日期。

// strtotime() would return false for invalid date strings... 
if (strtotime($start) && strtotime($end)) { 
    // The dates are valid, and so you can proceed with the query 
    $sql = 'SELECT.....'; 
} 
數據庫的
+0

比你邁克爾,你的答案是一個非常聰明的解決方案,但輸出是一個空白數組,並且至少有5條記錄匹配查詢。 – novato 2014-11-22 03:20:12

+1

當你說輸出是空白時,你的意思是整個屏幕是空白的?如果是這樣,那可能是因爲在將SQL字符串中的單個字符更改爲double wuotes之前的語法問題。始終調試與PHP代碼分開的查詢。使用MySQL客戶端,使用'BETWEEN'2014-11-16'AND'2015-05-02''等靜態值對其進行測試。一旦你在MySQL客戶端中工作,你可以回到PHP來調試它。我可以很容易在這裏輸入錯別字。 – 2014-11-22 03:22:49

+0

不,數組是[],因爲我在互聯網瀏覽器中檢查了執行帶有參數的php文件。 – novato 2014-11-22 03:25:44