PHP 和 Yii 中的 MVC 最佳实践视图/控制器/模型


mvc best practice view/controller/model in php and yii

这是一个最佳实践问题,而不是一个特定的问题。我对 MVC 方法和 Yii 相当陌生,并且在应用程序上开发已经有一段时间了。我一直看到关于最佳实践以及将什么放入哪个文件(控制器、模型、视图、帮助程序等)的讨论,但我还没有找到任何具体的例子。

我目前有这样的调用:我的视图文件中的Model::function()以及$var = app()->request->getParam(value, false);

我的控制器文件中有调用,例如 Model::function() 和 Model::model()->scope1()->scope2()->findAll() 我也认为我的控制器文件变得有点厚,但不确定如何以及在哪里放置一些膨胀,我一直在阅读有关 DRY 的信息,我认为我并没有完全 DRY 我的代码可以这么说。您能否更清楚地了解什么去哪里,以及为什么:)的建议或原因感谢任何建议,提前感谢。

下面是视图文件中的示例调用

<?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>

$model在控制器中设置,类型为...同样的问题...这能做到吗..清洁工。。?在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,
    ));
}

和视图创建.php

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

感谢所有回复

我对 Yii 框架不太熟悉,但可以就你提到的一些具体事情提供一些建议:

不要太纠结于"最佳实践",因为就像所有设计模式MVC都可以实现一样,在某些情况下,不同的开发人员可以以许多不同的方式进行解释。这是什么意思呢?这意味着尽可能多地阅读MVC,然后简单地试一试:o)当您遇到问题时,您很快就会发现哪些插槽在哪里以及为什么(这通常是沿着"这属于哪里,控制器或型号?..."的思路。

就什么去哪里而言,

你可以谷歌/搜索stackoverflow或在无数的书中阅读许多关于应该做什么和去哪里的解释,但从你提供的代码片段中,我建议:

查看文件:(除非这是 Yii 特定的东西)在我看来,您的视图文件有点脏。您直接与模型交谈(这实际上是MVC的经典方法,而不是某些PHP应用程序采用"控制器是唯一允许与模型对话"的方法),但似乎您的视图正在尝试直接获取请求数据,对我来说,这不应该靠近视图。控制器应处理请求,使用模型进行验证,然后将输出传递到视图中。

模型

从小片段来看,这似乎没问题,但总的来说,要记住的一件重要事情是模型!=数据库(尽管有些人建议它是)。

控制器

从您的代码段来看似乎也很好,但是要解决控制器中的膨胀问题,如果没有看到您的控制器之一,很难提供建议。始终值得考虑的一件事是服务的使用。基本上,服务可用于通过封装大量重复/复杂的模型内容来大大简化您的控制器。因此,您不必在控制器中调用单独的验证和持久性模型,而只需实例化一个服务类,它可能只是调用一种方法(该方法通常返回一个布尔值以指示控制器操作的成功或失败),然后控制器只需要处理它最擅长(并且应该只执行)应用程序流的操作(即重定向到另一个页面, 显示错误等)。

我将向您展示一个重构代码的示例。这是你的代码

<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>

第一个问题是:为什么要用 renderPart 写两行相同的行?第一次重构:

<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');
    }
}

我的视图文件将变为:

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

我认为我们必须理解事物的责任:观点只是一种观点。

只需将视图视为显示数据的组件即可。它不应该执行数据库调用,与模型交互,创建新变量(或很少)等。如果要执行检查或使用某些数据等创建HTML块,请使用帮助程序来实现此目的。
视图将显示的数据将来自控制器。

控制器是大师,它将完成应用中的大部分工作:它将回答请求,在需要时向模型请求数据,将数据传递给视图并呈现它,等等。

在第一个示例中,只需将Vendors::getName($_GET['vendor'])保存在控制器中的变量中,然后将其传递给视图。
此外,如果您不需要 model 的所有数据,请不要传递整个对象。

关于您的第二个代码段,首先您可以将echo移出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';
}

并根据控制器返回的值呈现部分。

在我看来,没有"最佳实践"。只要你不在一个团队中工作,或者想把你的脚本作为开源发布,几十个人必须使用它,就按照你喜欢和需要的方式使用框架。即使你和其他人一起处理代码,也没有"上帝赐予"的规则。

还有比问题更重要的事情,如果你"真的被允许"在你的视图中使用静态函数。