2012-05-31 194 views
1

這是一個最佳實踐問題,而不是一個具體問題。 我對MVC方法和Yii相當陌生,現在已經開發了一段應用程序。我一直在看最好的實踐和什麼放在哪些文件(控制器,模型,視圖,助手等)的談話,但我還沒有找到任何具體的例子。mvc最佳實踐視圖/控制器/模型在php和yii

我現在有這樣的方法調用:在我看來,文件Model::function()以及像$var = app()->request->getParam(value, false);

我有像我型控制器文件調用::()函數和型號::模型()檢查 - > scope1( ) - > scope2() - > findAll()我也認爲我的控制器文件有點厚,但不知道如何以及在哪裏放一些膨脹,我一直在閱讀關於DRY,我想我不是可以這麼說,正在幹我的代碼。 你能給我一個更清晰的圖片,說明爲什麼會發生什麼,以及建議或理由:) 感謝任何建議,提前致謝。

這裏是在viewfile的示例調用

<?php 
$this->pageTitle = 'Edit Action'; 
$this->subTitle = '<i>for</i> <b>' . Vendors::getName($_GET['vendor']) . '</b>'; 
?> 

<div class="wrapper"> 
<?php echo $this->renderPartial('_form', array('model' => $model)); ?> 
</div> 

行getName是我在模型的功能,這是調用視圖中的一個功能的好方法?

又如視圖文件:

<div class="wrapper"> 
    <?php 

    if($this->action->id != 'create') { 
     $this->pageTitle = "New Media Contact"; 
     echo $this->renderPartial('_form', array('model'=>$model)); 
    } else { 
     $this->pageTitle = "New Vendor"; 
     echo $this->renderPartial('_form', array('model'=>$model)); 
    } 
    ?> 
</div> 

$模式設置類型爲控制器... 同樣的問題......這哪是做..清潔..?在MVC和可重用性/ DRY方面更好?

編輯 在閱讀了一些在這裏的回覆後, @Simone我重構我的代碼,並希望分享它是什麼樣子現在...

public function actionCreate() { 
    $model = new Vendors; 

    // Get and Set request params 
    $model->type = app()->request->getParam('type', Vendors::VENDOR_TYPE); 
    $vendorsForm = app()->request->getPost('Vendors', false); 
    // Uncomment the following line if AJAX validation is needed 
    $this->performAjaxValidation($model); 
    if ($vendorsForm) { 
     $model->attributes = $vendorsForm; 
     if ($model->save()) 
      $this->redirect(array('/crm/vendors', array('type' => $model->type))); 
    } 
    $model->categories = Categories::getAllParents($model->type); 
    $this->pageTitle = 'New ' . Lookup::item('VendorType', $model->type); 
    $this->render('create', array(
     'model' => $model, 
    )); 
} 

和視圖create.php

<div class="wrapper"> 
<?php echo $this->renderPartial('_form', array('model'=>$model));?> 

感謝所有respnses

+0

正如你的問題所示,它可能會被關閉。也許發佈一個具體的例子呢? –

+0

你已經在使用Yii ..它本身會拋出窗外的最佳做法 –

+0

@tereško請解釋一下你的意思,yii不使用最佳做法?你會建議使用哪種框架?我一直在看Symfony,並喜歡文件的數量等,但yii已經很容易與大多數工作... – SeventySix

回答

-3

在我看來,沒有「最佳做法」。只要您不在團隊中工作或想要將您的腳本作爲開源軟件發佈,幾十人必須使用它,不管您喜歡並需要它,都可以使用該框架。即使你在代碼上與其他人一起工作,也沒有「上帝賜予」的規則。

如果「真正允許」在視圖中使用靜態函數,還有比問題更重要的事情。

+0

謝謝,我實際上打算構建應用程序,以便團隊可以參與開發,這就是我要求的原因。因爲當時間到了,我想避免太多的重寫,所以我不妨從一個好的筆記開始...... – SeventySix

+0

如果你沒有把事情做錯(低劣?)的方式,至少不要不鼓勵別人也這樣做。 –

+0

@SamyDindane在你看來是錯誤的?在我看來錯了?我的朋友邁克爾認爲錯誤?在yii團隊或wordpress團隊的意見?還是誰? @ SeventySix只要你的團隊使用相同的指導方針,這將是沒有問題的。如果您使用Yii,儘可能遵循Yii準則。 – Oliver

0

簡單地將一個視圖看作是一個組件,只有顯示數據。它不應該進行數據庫調用,與模型交互,創建新變量(或很少)等。如果你想做一個檢查,或使用一些數據等創建一個HTML塊,使用助手的目的。
視圖將顯示的數據將來自控制器。

控制器是maestro誰將完成您應用中的大部分工作:它將回答請求,根據需要向模型請求數據,將數據傳遞給視圖並呈現它等等。

在您的第一個示例中,只需將Vendors::getName($_GET['vendor'])保存在控制器中的變量中,然後將其傳遞給視圖。
此外,如果您不需要全部model的數據,請不要傳遞整個對象。

關於您的第二個片段,首先您可以將echo s移出if聲明,因爲它們是相同的。
好事是做檢查if ($this->action->id != 'create')在你的控制器,並給您的視圖一個簡單的布爾:

if ($this->action->id != 'create') { // not sure if $this->action->id would remain the same, I don't know Yii 
    $media = true; 
    // or 
    // $page = 'media'; 
} else { 
    $media = false; 
    // or 
    // $page = 'vendor'; 
} 

而且使部分取決於由控制器返回的值。

+0

謝謝你的幫助,你能否給我提供一個如何調用上述函數以及如何將它傳遞給視圖的例子?再次感謝,現在更有意義:) – SeventySix

+0

對不起,但我不知道Yii如何工作,所以我不能告訴你如何做*的東西*。我相信它的文檔可以幫助你。祝你好運! :) –

+0

我同意,但我會說這對View來說只是在只讀的基礎上與模型進行交互並不差,但直接從視圖中直接同意數據庫調用,但是簡單的模型數據 - 爲什麼要用這個來控制控制器?每個對他們自己我猜; o) –

3

我不是太熟悉Yii框架但可以提供你提到的幾個具體的事情了幾點建議:

不要太趕上了「最佳實踐」爲像所有的設計模式MVC可以在不同開發者的許多不同的方式下被實現並且在某些情況下被解釋。那麼這是什麼意思?它意味着儘可能多地在MVC上進行閱讀,然後簡單地去做:o)你很快就會發現什麼時候在什麼地方以及爲什麼當你提出問題時(通常是按照「這是哪裏」屬於,控制器還是型號?...'

從哪裏來,你可以谷歌/搜索stackoverflow或讀無數書籍許多explinations什麼應該做什麼,去哪裏,但從代碼片段你提供了我會建議:

查看文件 :(除非這是一個Yii特定的事情)在我看來你的視圖文件有點髒你直接與模型交談(這實際上是古典的方法的MVC,而不是一些PHP應用程序採用'控制器是隻有一個人可以對模型的方法說話),但看起來你的視圖試圖直接獲取請求數據,對我而言,這不應該在視圖附近。控制器應該處理請求,使用模型進行驗證,然後將輸出傳遞到視圖中。

模型:從小片段看起來似乎沒問題,但一般來說要記住的一件重要事情是模型!=數據庫(儘管有人認爲它是這樣的)。

控制器:再次從你的代碼片段看起來很好,但是爲了解決你的控制器中的膨脹問題,沒有看到你的控制器之一,很難提供一個建議。有一件事總是值得考慮的是使用服務。基本上可以通過封裝大量重複/複雜的模型來大大簡化您的控制器。因此,不要在控制器中調用單獨的驗證和持久性模型,而只是實例化一個服務類,它可能只是調用一個方法的情況(它通常會返回一個bool來向控制器指示操作的成功或失敗)然後你的控制器只需要處理它最好的做法(應該只做)應用程序的流程(即重定向到另一個頁面,顯示錯誤等)。

+0

謝謝STeve,好吧,所以我學會了如何使用$ this作爲控制器,但是如果我要從不同的模型中調用控制器,而不是與其鏈接的控制器。 Post postscontroller或在我的案例供應商 - > vendorscontroller,但我需要從模型類別的類別名稱標籤...我應該怎麼做..? $ this-> getCategory(),但似乎我在賣家控制器中放入類別特定的代碼......?對不起,如果我沒有得到它... – SeventySix

+0

你應該儘量不要想到模型被鏈接到控制器,確實可以在你的應用程序中的同一文件夾/模塊下找到類別模型和控制器(用於組織目的真)。但模型可以在任何控制器中調用,但是您需要閱讀Yii的方法。通常你必須確保你的自動加載器是爲此設置的。我認爲你一定要對服務進行研究,因爲這會簡化你的控制器。 –

+0

只是覺得我對文件夾組織的上述評論可能不適用於所有應用程序。有些僅使用通用模型,控制器文件夾,其他則使用更多模塊組織方式。使用MVC有許多好處,但總是把其中之一看作是在應用程序中組織代碼庫的一種方式。我認爲你確實需要對OOP有一個牢固的把握,這會讓MVC更容易理解。 –

2

我會告訴你一個重構你的代碼的例子。這是你的代碼

<div class="wrapper"> 
    <?php 
     if($this->action->id != 'create') { 
      $this->pageTitle = "New Media Contact"; 
      echo $this->renderPartial('_form', array('model'=>$model)); 
     } else { 
      $this->pageTitle = "New Vendor"; 
      echo $this->renderPartial('_form', array('model'=>$model)); 
     } 
    ?> 
</div> 

第一個問題是:爲什麼要用renderPartial寫兩次同一行?第一重構:

<div class="wrapper"> 
<?php 
    if($this->action->id != 'create') { 
     $this->pageTitle = "New Media Contact"; 
    } else { 
     $this->pageTitle = "New Vendor"; 
    } 
    echo $this->renderPartial('_form', array('model'=>$model)); 
?> 
</div> 

現在第二步驟:

<?php $this->pageTitle = $this->action->id != 'create' ? "New Media Contact" "New Vendor"; ?> 

<div class="wrapper"> 
<?php echo $this->renderPartial('_form', array('model'=>$model)); ?> 
</div> 

對我來說是更具有可讀性。我有很多最佳實踐。但是,在惡劣環境下使用會變得糟糕。所以...重寫代碼真的很有用嗎?對我來說是的!因爲我的目標是代碼的可維護性。易於閱讀,易於管理。但是你需要找到你的標準或你的團隊標準。另外,我更喜歡移動控制器中的任何一種邏輯。例如,我可以在控制器設置的默認PAGETITLE並重新定義它在actionCreate方法:

class SomeController extends CController 
{ 

    public $pageTitle = "New Vendor"; 

    function actionCreate() 
    { 
     $this->setPageTitle("New Media Contact") 
     $this->render('view'); 
    } 

} 

而且我viewfile將成爲剛:

<div class="wrapper"> 
    <?php echo $this->renderPartial('_form', array('model'=>$model)); ?> 
</div> 

我認爲我們必須理解事物的責任:視圖只是一個看法。

+0

謝謝西蒙妮,這非常有幫助:)我一直在挑選東西,但在我看來,關於如何真正做好事很少寫,所有(簡單)的例子似乎都是非常糟糕的做法,那麼應該怎麼學習? – SeventySix

+0

在閱讀本文後,我回頭看了看代碼,並試圖將所有邏輯確定爲控制器中的輸出,但如果需要更多類型,還要保持它的靈活性,所以我使用Lookup :: item('VendorType ',$ type)函數的類型來自請求字符串。現在我面臨着訪問控制方面的問題,因爲一個角色被允許訪問一個類型而不是另一個,但是在yii中,訪問控制似乎僅限於動作,而不是參數...... – SeventySix