2010-09-26 29 views
2

我想弄清楚如何在我的第一個CI應用程序(並且只有第二個PHP應用程序)中編寫語句,並且我卡住了。如何使用PHP&CodeIgniter編寫此語句

我有一個從各自的表中保存book_id和user_id的聯結表。我想找出誰讀了一本書並回應,但我需要的格式是有道理的。下面是該查詢:

$readQuery = $this->db->get_where('books_users', array('book_id' => $isbn)); 

這是我的邏輯,一個人

// Get my user info 
$user = $this->ion_auth->get_user(); 
// Tell me who has read it. 
$this->db->select('user_id'); 
$readQuery = $this->db->get_where('books_users', array('book_id' => $isbn)); 
// If only one person has read it 
if ($readQuery->num_rows() == 1) { 
    $readResult = $readQuery->row(); 
    // And if that person was me... 
    if ($readResult->user_id == $user->id) { 
     $message = 'You have read this.'; 
    // If it was someone else... 
    } else { 
     $reader = $this->ion_auth->get_user($readResult->user_id); 
     $message = "$reader->first_name $reader->last_name has read this"; 
    } 
// If two people have read it 
} 

所以我好,如果只有一個人讀過它。但是,當兩個人都讀過它時,我想讓它說「名字一和名字二已經讀過這個。」如果登錄的人沒有閱讀它。如果他們是兩個人中的一個,那麼應該說「你和名字二已經讀過這個」。

等等爲3-5。如果有3-5個人閱讀過,則選項爲「姓名一,姓名二,姓名三已閱讀此項」或「你,姓名二,姓名三已閱讀此項。」多達五人

如果它是6或更多,它應該只是說他們兩個的名字,IE「你,名字2和其他5人都讀過這個。」

我認爲爲每個實例做一個條件,然後將所有用戶推送到一個數組。然後,我可以使用in_array()來查看登錄用戶是否已經閱讀並嘗試回報,但我在處理邏輯時遇到了一些麻煩。

有沒有更簡單的方法?

感謝很多提前, 馬庫斯

回答

2
$users = array(); 
while($row) 
{ 
    if(currentuser) 
    { 
    array_unshift($users,'You') 
    } 
    else 
    { 
    $users[] = row[name] 
    } 
} 

$count = $max = count($users); 
if($max >= 6) 
{ 
    $max = 2; 
} 

$str = ''; 
for($i=0;$i<$max;$i++) 
{ 
    $str .= ($str == '' ? '' : ($i == $count-1 && $count < 6 ? ' And ' : ', ')) . $users[$i]; 
} 

if($count >= 6) 
{ 
    $str .= ' and '.$count-2.' others' 
} 

這會幫助你一起。這幾乎是僞代碼,但邏輯是在那裏實現你想要的(我相信)。如果您只是展示了許多用戶,但顯然可以輕鬆完成,那麼您顯然不想獲取所有行。

+0

我更喜歡這種設置更多 - 它看起來更乾淨 - 但我無法爲我的場景實現它。我的大部分困惑來自這一行:$ str。=($ str ==''?'':($ i == $ count-1 && $ count <6?'And':','))。 $用戶[$ i]於;有什麼建議麼?我對三元論的看法不是很好,也不明白我在第一個陳述中的引號。 – Marcus 2010-09-27 21:45:52

+0

三元語句僅用於連接 - 所以如果str是空白的,不要追加任何內容,否則追加結果(如果我們是str的結尾,並且少於6,則追加並附加逗號)。我用逗號分隔事物時總是用這個,所以你在開頭或結尾處沒有額外的逗號 – methodin 2010-09-28 02:12:48

+0

不錯。在你解釋之後,我能夠實現這一點,它縮短了40行(30行vs 70行),並且更容易維護。再次感謝。 – Marcus 2010-09-29 19:20:08

3

我會說使用與範圍的switch語句。你必須做一些雜技來處理包括「你」的問題。下面的代碼未經測試,但給你的一般想法。

$message = ""; 
$readers = array(); 
$me_included = 0; // Counter increment if you're included in the reader list 

$this->db->select('user_id'); 
$readQuery = $this->db->get_where('books_users', array('book_id' => $isbn));  
foreach ($readQuery->result() as $row) { 
    if ($row->user_id == $user->id) { 
    $message = "You"; 
    $me_included = 1; 
    } else { 
    $readers[] = $this->ion_auth->get_user($row->user_id); 
    } 
} 

$reader_count = $sizeof($readers) + $me_included; 
switch(TRUE) 
{ 
    // One reader, not you 
    case(($reader_count == 1) && ($me_included == 0)): 
    $message .= $readers[0]->first_name . " " . $readers[0]->last_name . " has read this."; 
    break; 
    // Only you 
    case(($reader_count == 1) && ($me_included == 1)): 
    $message .= " have read this."; 
    break; 
    // Two readers 
    case(($reader_count == 2)): 
    for ($i = 0; $i <= sizeof($readers); $i++) { 
     if ($i == sizeof($readers)) { 
     $message .= " and "; 
     } 
     $message .= $readers[i]->first_name . " " . $readers[i]->last_name; 
    } 
    $message .= " have read this."; 
    break; 
    case(($reader_count > 3) && ($reader_count < 6)): 
    if ($me_included) { 
     $message .= ", "; 
    } 
    for ($i = 0; $i <= sizeof($readers); $i++) { 
     if ($i == sizeof($readers)) { 
     $message .= " and "; 
     } 
     $message .= $readers[i]->first_name . " " . $readers[i]->last_name; 
     if ($i != sizeof($readers)) { 
     $message .= ", "; 
     } else { 
     $message .= " have read this."; 
     } 
    } 
    break; 
    case(($reader_count > 6)): 
    if ($me_included) { 
     $message .= ", " . $readers[0]->first_name . " " . $readers[0]->last_name . " and " . ($reader_count - 2) . " others have read this."; 
    } else { 
    for ($i = 0; $i <= 1; $i++) { 
     $message .= $readers[0]->first_name . " " . $readers[0]->last_name . ", " . $readers[1]->first_name . " " . $readers[1]->last_name . " and " . ($reader_count - 2) . " others have read this."; 
    } 
    break; 
    } 
+0

我能夠在修改一下後成功實現這一點。可悲的是,我沒有足夠的空間在這裏發佈整個代碼,但是一旦修改就可以工作。謝謝您的幫助。 – Marcus 2010-09-27 21:47:06

+0

我討厭看到無用的邏輯表達式:)在工作中,我總是要處理if(something){} else {做一些工作} ...或者如果(true)...讓我生氣 – methodin 2010-09-28 02:17:31

1

實際上有幾個地方我們可以優化這個。

1)在初始查詢做一個與用戶表連接,所以我們不必多次再次查詢只爲每個名字:

$readers = $this->db->select('id', 'first_name', 'last_name')->from('books_users')->join('users', 'books_users.id =users.id', 'left')->where('book_id' => $isbn); 

2)此外,我們才能避免在迭代整個(可能很大)結果集只是爲了看看讀它,做一個單獨的查詢:

$you_read = $this->db->get_where('books_users', array('book_id' => $isbn, 'user_id' => $user->id)); 
0

只是爲了完整起見,這裏是我使用的最終代碼。希望這會對某人有用。

// Find out who has read this book 
    // Get the users 
    $current_user = $this->ion_auth->get_user(); 
    $users = $this->ion_auth->get_users(); 
    // Get the readers 
    $this->db->select('user_id'); 
    $query = $this->db->get_where('books_users', array('book_id' => $isbn)); 
    // If there were results 
    $readers = array(); 
    if ($query->num_rows() > 0) { 
     foreach ($users as $user) { 
      if ($current_user->id == $user->id) { 
       array_unshift($readers, 'You'); 
      } else { 
       $readers[] = $user->first_name . ' ' . $user->last_name; 
      } 
      $count = $max = count($readers); 
      if ($max >= 6) { 
       $max = 2; 
      } 
      $message = ''; 
      for ($i = 0; $i < $max; $i++) { 
       $message .= ($message == '' ? '' : ($i == ($count - 1) && ($count < 6) ? ' and ' : ', ')) . $readers[$i]; 
      } 
      if ($count >= 6) { 
       $message .= ' and ' . ($count - 2) . ' others'; 
      } 
      $message .= ($count == 1 && !$current_user->id ? ' has ' : ' have ') . 'read this.'; 
     } 
    } else { 
     $message = '<a href="' . base_url() . 'books/' . $bookResult->filename . '">Be the first to read this.</a>'; 
    }