2011-09-25 91 views
6

我使用笨了一段時間一直在和有MVC,PHP等高脂模型瘦控制器在笨

然而體面的知識,我發現它堅持高脂模型瘦控制器硬風氣。

我見過很多,包括在每個文件中包含哪些僞代碼,但沒有實際的例子。 (請鏈接到一些文章,如果我錯過了任何明顯的!)

我發現很難將窗體邏輯移動到模型。例如,我爲我的認證系統使用自定義庫,該系統擁有自己的模型。我應該讓一個網站用戶模型登錄用戶嗎?或者我應該製作一個網站模型來做到這一點?或者一個表單模型?

爲了幫助我,誰能告訴我如何skinnify這個控制器?我意識到這是很多代碼,但簡單的指針會很棒。 (請注意,我剛剛寫了這個代碼,因此它並沒有被重構多,但它應該給如何我的一些方法是失控的一個很好的例子。)

public function register() 
{ 
    session_start(); 
    if ($this->tf_login->logged_in()) 
    { 
     redirect('profile'); 
    } 
    if ($_GET['oauth'] == 'true') 
    { 
     $type = $_GET['type']; 
     try 
     { 
      $token = $this->tf_login->oauth($type, '', 'email'); 
     } 
     catch (TFLoginCSRFMismatchException $e) 
     { 
      $this->tf_assets->add_data('error_message', $e->getMessage()); 
     } 
     catch (TFLoginOAuthErrorException $e) 
     { 
      $this->tf_assets->add_data('error_message', $e->getMessage()); 
     } 
     if ($token) 
     { 
      $user_details = $this->tf_login->call('https://graph.facebook.com/me?fields=email,first_name,last_name,username&access_token=' . $token); 
      $user_details_decoded = json_decode($user_details); 
      if ($user_details_decoded->email) 
      { 
       try 
       { 
        $id = $this->tf_login->create_user($user_details_decoded->username, 
        md5($user_details_decoded->username . time()), 
        $user_details_decoded->email, 
        '', 
        TRUE, 
        TRUE); 
       } 
       catch (TFLoginUserExistsException $e) 
       { 
        try 
        { 
         if ($this->tf_login->oauth_login($type, $user_details_decoded->email, $token)) 
         { 
          $this->session->set_flashdata('success_message', 'You have successfully logged in.'); 
          redirect('profile'); 
         } 
         else 
         { 
          $this->session->set_flashdata('error_message', 'An account with these details exists, but currently isn\'t synced with ' . $type . '. Please log in to sync the account.'); 
         } 
        } 
        catch (Exception $e) 
        { 
         $this->session->set_flashdata('error_message', $e->getMessage()); 
        } 
       } 
       catch (TFLoginUserNotCreated $e) 
       { 
        $this->tf_assets->add_data('error_message', 'You could not be registered, please try again.'); 
       } 
       if ($id) 
       { 
        $this->tf_login->add_user_meta($id, 'first_name', $user_details_decoded->first_name); 
        $this->tf_login->add_user_meta($id, 'surname', $user_details_decoded->last_name); 
        $this->tf_login->sync_accounts($id, $type, $token); 
        $this->session->set_flashdata('success_message', 'Welcome ' . $this->input->post('first_name', TRUE) . ' ' . $this->input->post('surname', TRUE) . '. Your account has been sucessfully created. You will shortly receive an email with a verification link in.'); 
        redirect('login'); 
       } 
      } 
      else 
      { 
       $this->session->set_flash_data('error_message', 'You could not be logged in, please try again.'); 
      } 
     } 
     // Redirect to clear URL 
     redirect(current_url()); 
    } 

    if ($this->form_validation->run() !== FALSE) 
    { 
     try 
     { 
      $id = $this->tf_login->create_user($_POST['username'], $_POST['password'], $_POST['email'], '', FALSE); 
     } 
     catch (Exception $e) 
     { 
      $this->tf_assets->add_data('error_message', $e->getMessage()); 
     } 
     if ($id) 
     { 
      $this->tf_login->add_user_meta($id, 'first_name', $_POST['first_name']); 
      $this->tf_login->add_user_meta($id, 'surname', $_POST['surname']); 
      if ($this->tf_login->register_verification_email()) 
      { 
       $this->session->set_flashdata('success_message', 'Welcome ' . $this->input->post('first_name', TRUE) . ' ' . $this->input->post('surname', TRUE) . '. Your account has been sucessfully created. You will shortly receive an email with a verification link in.'); 
       redirect('login'); 
      } 
      else 
      { 
       $this->tf_login->login_user($id); 
       $this->session->set_flashdata('success_message','Your account has been sucessfully created.'); 
       redirect('profile'); 
      } 
     } 
     else 
     { 
      $this->tf_assets->add_data('error_message', $this->tf_login->get_errors()); 
     } 
    } 
    if (validation_errors()) 
    { 
     $this->tf_assets->add_data('error_message', validation_errors()); 
    } 
    $this->tf_assets->set_content('public/register'); 
    $this->tf_assets->add_data('page_title', "Register"); 
    $this->tf_assets->render_layout(); 
} 

謝謝提前!

+2

「胖模型」的傳講適用於原始的MVC模式。 [這不是什麼PHP框架](http://stackoverflow.com/questions/1549857/simple-php-mvc-framework/1549970#1549970)。這對你來說也不是很好。將控制器視爲表單處理接口並不存在真正的問題。 – mario

+1

[Understanding MVC:模型上的「Fat」的概念是什麼,控制器上的「Skinny」是什麼意思?](http://stackoverflow.com/questions/3109715/understanding-mvc-whats-the-concept-of- fat-on-models-skinny-on-controllers) – Gordon

+3

當我搜索以前沒有出現的問題時。我會通讀,歡呼:) – Toddish

回答

3

從我所知道的,大部分或全部代碼都屬於控制器或組件,所以我認爲你的問題不是模型/控制器的混淆。

然而,由於深層嵌套結構和未能將特定任務分解到自己的方法中,代碼難以閱讀。您將從中受益的主要重構是創建新的私有方法,以分離出正在執行的離散子任務。這對澄清當前方法的高級結構具有額外的重要好處。所以,你最終會得到的東西看起來像(只給你一個粗略的例子):

public function register() 
{ 
    session_start(); 
    if ($this->tf_login->logged_in()) 
    { 
     redirect('profile'); 
    } 
    if ($_GET['oauth'] == 'true') 
    { 
     $this->oauthRegister(); 
    } 

    $this->normalRegister(); 
} 

同樣,oatuhRegister方法和normalRegister方法將會被分解成更小的方法本身,這樣,當你完全完成每種方法將堅持SRP,並可能會少於10行代碼。這將極大地提高代碼的可讀性和可維護性。我還建議檢查Clean Code,這對於保持您的方法簡短有很有力的論據。

+0

我曾想過將它分解成獨立的私有方法,但後來我認爲這些可以交給模型。 然後我認爲我真的不喜歡模型handeling重定向,設置錯誤等 我想我會分裂它,專注於使它更具可讀性。我會很快將這個標記爲公認的答案,除非有人發表了一些啓發性的話,因爲到目前爲止這是最有意義的。 – Toddish

+0

根據你的直覺,你完全可以保持重定向不在模型中。還有一件事可能會對你有所幫助,當我詢問是否應該在模型或控制器中進行驗證時,我在別處收到了一個答案:http://pastebin.com/SKvpjrk0。所以雖然你說得對,一般來說,模型中的模型會隨着代碼的變化而變化,但典型的情況是,身份驗證進入控制器,這從字面上看是一種「控制」訪問的行爲。 – Jonah