0

在 yii framework demos 中有一个 blog demo。在这个博客演示中,一个 Post 控制器有两个不同的操作:索引和视图。

/**
 * Lists all models.
 */
public function actionIndex()
{
    $criteria=new CDbCriteria(array(
        'condition'=>'status='.Post::STATUS_PUBLISHED,
        'order'=>'update_time DESC',
        'with'=>'commentCount',
    ));
    if(isset($_GET['tag']))
        $criteria->addSearchCondition('tags',$_GET['tag']);

    $dataProvider=new CActiveDataProvider('Post', array(
        'pagination'=>array(
            'pageSize'=>Yii::app()->params['postsPerPage'],
        ),
        'criteria'=>$criteria,
    ));

    $this->render('index',array(
        'dataProvider'=>$dataProvider,
    ));
}


/**
 * Displays a particular model.
 */
public function actionView()
{
    $post=$this->loadModel();
    $comment=$this->newComment($post);

    $this->render('view',array(
        'model'=>$post,
        'comment'=>$comment,
    ));
}

和索引视图是:

<?php $this->widget('zii.widgets.CListView', array(
    'dataProvider'=>$dataProvider,
    'itemView'=>'_view',
    'template'=>"{items}\n{pager}",
)); ?>

和视图是:

<?php $this->renderPartial('_view', array(
    'data'=>$model,
)); ?>

但是索引和视图都使用_view:</p>

<div class="author">
    posted by <?php echo $data->author->username . ' on ' . date('F j, Y',$data->create_time); ?>
</div>
<div class="content">
    <?php
        $this->beginWidget('CMarkdown', array('purifyOutput'=>true));
        echo $data->content;
        $this->endWidget();
    ?>
</div>

这是我的问题:我可以理解视图分配'data' => $model,所以在_view中,$data是有效的。在索引操作中,应用了小部件 clistview,但我不明白 $data 变量在哪里设置?我知道 $data 表示当前帖子(来自 dataprovider)。我只是不知道 yii 是如何以及在哪里做到这一点的?谢谢你的帮助。

4

2 回答 2

0

上面的代码首先为 Post ActiveRecord 类创建了一个数据提供者。然后它使用 CListView 显示数据提供者返回的每个数据项。显示是通过名为“_post”的局部视图完成的。此部分视图将为每个数据项呈现一次。在视图中,可以通过变量 $data 访问当前数据项。

通过使用用于呈现每个数据项的 CListView 的 itemView 属性。此属性值将作为第一个参数传递给 CController 属性 renderpartial 以呈现每个数据项。

public string renderPartial(string $view, array $data=NULL, boolean $return=false, boolean $processOutput=false)

public function renderPartial($view,$data=null,$return=false,$processOutput=false)
{
    if(($viewFile=$this->getViewFile($view))!==false)
    {
        $output=$this->renderFile($viewFile,$data,true);
        if($processOutput)
            $output=$this->processOutput($output);
        if($return)
            return $output;
        else
            echo $output;
    }
    else
        throw new CException(Yii::t('yii','{controller} cannot find the requested view "{view}".',
            array('{controller}'=>get_class($this), '{view}'=>$view)));
}

渲染视图。

如果 $data 是一个关联数组,它将被提取为 PHP 变量并提供给脚本 命名视图是指一个 PHP 脚本。通过 getViewFile 解析的脚本 在 renderPartial 方法中使用 getViewFile 的脚本,如下所示

public function getViewFile($viewName)
{
    if(($theme=Yii::app()->getTheme())!==null && ($viewFile=$theme->getViewFile($this,$viewName))!==false)
        return $viewFile;
    $moduleViewPath=$basePath=Yii::app()->getViewPath();
    if(($module=$this->getModule())!==null)
        $moduleViewPath=$module->getViewPath();
    return $this->resolveViewFile($viewName,$this->getViewPath(),$basePath,$moduleViewPath);
}

根据给定的视图名称查找视图文件。

renderItems 是 CBaseListView ClassFile 中定义的抽象方法

/**
     * Renders the data items for the view.
     * Each item is corresponding to a single data model instance.
     * Child classes should override this method to provide the actual item rendering logic.
     */

    abstract public function renderItems(); 

并且这个方法被 ClistView 类覆盖

于 2013-06-26T12:18:58.160 回答
0

CListView小部件循环通过$dataProvider,并且对于每个项目,它都会执行以下操作:

$this->renderPartial($itemView, array(
   'data'=>$model,
));

配置中$itemView设置的视图文件在哪里?CListView

就是这样。

编辑:为了澄清如何CListView 迭代 dataprovider 项目:它在中定义CListView::renderItems,简而言之,最重要的部分是:

// Get dataprovider data as array
$data=$this->dataProvider->getData();
...
// Get viewfile
$viewFile=$owner->getViewFile($this->itemView);
...
// Loop thru $data items
foreach($data as $i=>$item)
{
    ...
    // Here data is assigned from dataprovider item
    $data['data']=$item;
    ...
    // Render view file
    $owner->renderFile($viewFile,$data);
}
于 2013-06-26T12:19:23.940 回答