2010-07-27 61 views
-1

我碰到了一些與我的項目有關的問題。像許多書呆子一樣,我決定創建自己的視頻遊戲評論網站。評論存儲在數據庫中,並且可以通過遊戲的標題檢索通過URL:處理'。'通過url傳遞給MySQL查詢的字符

http://www.example.com/reviews/ {gameName}/{可選 pageOfReview}

不幸的是,測試的邊緣情況時,我來到發生奇怪的錯誤 - 如果遊戲在標題中有一段時間,我無法檢索它。如果這段時間是標題的主角(如.hack),我會得到一個Kohana堆棧跟蹤錯誤屏幕,告訴我評論(或者更確切地說,遊戲)不存在。如果它位於標題的中間或末尾,我會收到一條自己的錯誤消息,說明無法檢索評論(遊戲)。有沒有辦法解決?這是MySQL解析一段時間或其他問題的問題嗎?

編輯:所有查詢都通過Kohana 2的ORM功能使用MySQLi驅動程序進行處理。節能審查(管理控制器):

public function saveReview() 
{ 
    $this->checkAdmin(); 

    if (isset($_POST['submit'])) { $this->storeReview(); } 
    else { header('Location: /admin'); } 
} 

private function storeReview($id = null) 
{ 
    if (!preg_match("/^[a-zA-Z0-9\-_:!'. ]*$/", $_POST['gameTitle']) || empty($_POST['gameTitle'])) { $gameTitle = false; } 
    else { $gameTitle = ucwords($this->clean($_POST['gameTitle'])); } 

    if (!is_numeric($_POST['genre'])) { $genre = false; } 
    else { $genre = $_POST['genre']; } 

    $platformCheckArray = array_map('is_numeric', $_POST['platforms']); 

    $platformCheck = true; 
    foreach ($platformCheckArray as $pca) 
    { 
     if (!$pca) 
     { 
      $platformCheck = false; 
      break; 
     } 
    } 

    $proCheck = true; 
    $cleanedPros = array(); 

    foreach ($_POST['pros'] as $pro) 
    { 
     if (!preg_match("/^[a-zA-Z0-9\-_:!' ]*$/", $pro)) 
     { 
      $proCheck = false; 
      break; 
     } 

     if (!empty($pro)) { $cleanedPros[] = $this->clean($pro); } 
    } 

    $conCheck = true; 
    $cleanedCons = array(); 

    foreach ($_POST['cons'] as $con) 
    { 
     if (!preg_match("/^[a-zA-Z0-9\-_:!' ]*$/", $con)) 
     { 
      $conCheck = false; 
      break; 
     } 

     if (!empty($con)) { $cleanedCons[] = $this->clean($con); } 
    } 

    if (!is_numeric($_POST['score'])) { $score = false; } 
    else { $score = $_POST['score']; } 

    if (empty($_POST['content'])) { $content = false; } 
    else { $content = true; } 

    // save review if all tests pass, display error otherwise 

    if ($gameTitle && $genre && $platformCheck && $proCheck && $conCheck && $score && $content) 
    { 
     $gameTitle = $gameTitle; 
     $platforms = $_POST['platforms']; 
     $reviewContent = $_POST['content']; 
     $prosText = implode(', ', $cleanedPros); 
     $consText = implode(', ', $cleanedCons); 

     $game = ORM::factory('game'); 
     $game->title = $gameTitle; 
     $game->genre_id = $genre; 
     $game->platforms = $platforms; 
     $game->save(); 

     $storedGenre = ORM::factory('genre')->where('id', $genre)->find(); 
     $storedGenre->platforms = $platforms; 
     $storedGenre->save(); 

     $review = ORM::factory('review', $id); 
     $review->content = $reviewContent; 
     $review->score = $score; 
     $review->game_id = $game->id; 
     $review->date_added = date('Y-m-d H:i:s'); 
     $review->platforms = $platforms; 
     $review->save(); 

     $pros = ORM::factory('pro'); 
     $pros->review_id = $review->id; 
     $pros->text = $prosText; 
     $pros->save(); 

     $cons = ORM::factory('con'); 
     $cons->review_id = $review->id; 
     $cons->text = $consText; 
     $cons->save(); 

     if ($game->saved && $storedGenre->saved && $review->saved && $pros->saved && $cons->saved) { $this->success('review'); } 
     else { $this->showError("Something went wrong with saving the review. Please try again."); } 
    } 
    else { $this->showError("All fields must contain values. Please try again."); } 
} 

檢索複審(從評論控制器):

public function show($id, $page = 1) 
{ 
    if (is_numeric($id)) { $game = ORM::factory('game', $id); } 
    else 
    { 
     $id = ucwords(stripslashes($id)); 
     $game = ORM::factory('game')->where('title', $id)->find(); 
    } 

    if ($game->loaded) { $this->showReview($game->id, $page); } 
    else { HandiError::factory('Could not retrieve the specified review. Please check that you entered the correct value.'); } 
} 

private function showReview($id, $page = 1) 
{ 
    $page = (int)$page; 

    if ($page < 1) { $page = 1; } 

    if ($id) 
    { 
     $game = ORM::factory('game', $id); 
     $review = ORM::factory('review')->where('game_id', $game->id)->find(); 
     $genre = ORM::factory('genre')->where('id', $game->genre_id)->find(); 
     $revPlatforms = $this->db->query("SELECT * FROM platforms 
             INNER JOIN platforms_reviews AS pr ON platforms.id = pr.platform_id 
             INNER JOIN reviews ON pr.review_id = reviews.id 
             WHERE reviews.id = ?", $review->id); 
     $revPros = ORM::factory('pro')->where('review_id', $review->id)->find(); 
     $revCons = ORM::factory('con')->where('review_id', $review->id)->find(); 

     $platforms = array(); 
     foreach($revPlatforms as $rp) { $platforms[] = $rp->name; } 
     $pros = explode(', ', $revPros->text); 
     $cons = explode(', ', $revCons->text); 

     $pages = explode('&lt;split /&gt;', $review->content); 
     $count = count($pages); 

     if ($page > ($count)) { $content = $pages[0]; } 
     else { $content = $pages[$page - 1]; } 

     $view = new View('reviews/show_review'); 
     $view->content = $content; 
     $view->gameTitle = $game->title; 
     $view->genre = $genre->name; 
     $view->platforms = implode(', ', $platforms); 
     $view->pros = $pros; 
     $view->cons = $cons; 
     $view->score = $review->score; 
     $view->pages = $pages; 
     $view->render(true); 
    } 
    else { HandiError::factory('Could not retrieve the specified review. Please check that you entered the correct value.'); } 
} 

編輯2:嗯,我發現了一些關於超前時段情況:

在我的管理員索引中,我有幾個查詢用於根據遊戲標題,平臺,流派等列出評論。它基本上是一個窮人的維基。請參閱:

public function index() 
{ 
    /* show a wiki-like page with reviews listed by title, 
    * game title, genre, and platform 
    */ 

    $numGenres = $this->db->query("SELECT COUNT(id) AS num FROM genres"); 
    $numPlatforms = $this->db->query("SELECT COUNT(id) AS num FROM platforms"); 

    $genreCount = $numGenres[0]->num; 
    $platformCount = $numPlatforms[0]->num; 
    $scoreCount = 5; 

    $genreResults = array(); 
    $platformResults = array(); 
    $scoreResults = array(); 

    $gameResults = $this->db->query("SELECT LEFT(title, 1) AS letter, COUNT(id) AS count FROM games GROUP BY letter ORDER BY letter ASC"); 

    for($i = 1; $i < ($genreCount + 1); ++$i) 
    { 
     $genreResults[] = $this->db->query("SELECT genres.id AS id, genres.name AS name, COUNT(reviews.id) AS num FROM reviews 
              INNER JOIN games ON reviews.game_id = games.id 
              INNER JOIN genres ON games.genre_id = genres.id 
              WHERE genres.id = ?", $i); 
    } 

    for($j = 1; $j < ($platformCount + 1); ++$j) 
    { 
     $platformResults[] = $this->db->query("SELECT platforms.id AS id, platforms.name AS name, COUNT(reviews.id) AS num FROM reviews 
               INNER JOIN platforms_reviews AS pr ON reviews.id = pr.review_id 
               INNER JOIN platforms ON pr.platform_id = platforms.id 
               WHERE platforms.id = ?", $j); 
    } 

    for($k = 1; $k < ($scoreCount + 1); ++$k) 
    { 
     $scoreResults[] = $this->db->query("SELECT score, COUNT(id) AS num FROM reviews WHERE score = ?", $k); 
    } 

    $view = new View('reviews/index'); 
    $view->gamesByLetter = $gameResults; 
    $view->genres = $genreResults; 
    $view->platforms = $platformResults; 
    $view->scores = $scoreResults; 
    $view->render(true); 
} 

當我將這些查詢的結果傳遞給視圖時,我循環遍歷它們並創建基於元類別的鏈接。因此,它顯示了多少遊戲以字母A,B等開始,並且點擊其中一個鏈接將用戶帶到鏈接列表,每個鏈接都帶有評論(所以,A-> Afterburner(等等)), - >對Afterburner的評論)。

當我將鼠標懸停在具有領先期的組上時,我的狀態欄顯示鏈接中缺少該時間段,即使它顯示在源中。所以,即使源代碼顯示鏈接爲site.com/reviews/game/。瀏覽器將其顯示爲site.com/reviews/game/這讓我相信這段時間甚至沒有被傳遞到方法中,堆棧跟蹤似乎證實(它聲稱有一個缺失的參數,這將是期間)。

編輯3:好吧,我看看我的路線,並找不到任何東西。這就是說,我確實有一個.htaccess文件,mod_rewrite的路線看起來漂亮的SEO,所以我想知道如果這可能是問題。我自己從來沒有寫過mod_rewrite文件 - Kohana論壇上的人給了我這個,它工作,所以我去了。我可以理解一些涉及的regEx,但是我的regEx Fu很弱。我相信最後一行是'魔術'。

# Turn on URL rewriting 
Options +FollowSymlinks 
RewriteEngine On 

# Put your installation directory here: 
# If your URL is www.example.com/, use/
# If your URL is www.example.com/kohana/, use /kohana/ 
RewriteBase/

# Do not enable rewriting for files or directories that exist 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 

# For reuests that are not actual files or directories, 
# Rewrite to index.php/URL 

# Original rule: 
# RewriteRule ^(.*)$ index.php/$1 [PT,L] 

# Alternative rule: 
# RewriteRule .* index.php/$0 [PT,L] 

# 2nd alternative rule that works on ICDSoft: 
RewriteRule .* index.php?kohana_uri=$0 [PT,QSA,L] 

如果我正在閱讀這個權利,那麼'。'只是指任何單個字符。

Can a'。'除了表示文件擴展名或網址後綴(.com,.org等)之外,還可以在格式正確的URL中使用?我的意思是,當我將鼠標懸停在他們的鏈接上時,它們並未出現在Firefox的狀態欄中,這導致我認爲這是瀏覽器/格式良好問題,而不是編碼問題。

+0

你能張貼您用來檢索查詢評價? PHP代碼將會很有幫助,如果可能的話,它會在發送給MySQL之前將最終語句的回顯/打印輸出。 – Mike 2010-07-27 20:54:08

+0

我不使用Kohana - 是否(或可以)堆棧跟蹤包括導致問題的SQL查詢? – Mike 2010-07-27 21:08:31

+0

從我能看到的,沒有。 – 2010-07-27 21:14:04

回答

0

時間檢查所有生成的查詢與探查。

in Controller :: __ construct()put

new Profiler;

並找到可能損壞的查詢。

其他可能的解決方案: 走線槽你的代碼,有時未關閉/未終止的數據庫查詢例如可以打破(或合併)的其他查詢...

0

MySQL在列數據中的句點沒有問題。但是,該時段用於將表名與列名分開:table.column。如果您的查詢未正確轉義並引用,則該時間段可能會錯誤地解釋爲表格/列分隔符。

您是如何準備查詢的?

0

我認爲,這個問題是在Kohana框架中,而不是在SQL中。 Chchk out從url過濾參數。試着打印你的查詢,看看它在執行的時刻看起來是什麼樣子,並觀察你的期間發生了什麼。

0

編輯:對不起,我沒有看到你使用Kohana版本2.x.我懷疑這適用於你。

只是一個猜測,但你有沒有設置你的路線,以允許在網址期間? Kohana默認不允許句點。您需要設置路線)的第三個參數::集(到這樣的事情:

Route::set('reviews', 'reviews/<name>(/<page>)', array('name' => '[^/,;?]++', 'page' => '\d+') 
    ->defaults(array(
     'controller' => 'reviews', 
     'action'  => 'load', 
     'name'  => NULL, 
     'page'  => 1, 
    )); 

查看論壇發帖http://forum.kohanaframework.org/comments.php?DiscussionID=4320

相關問題