大家帮忙参考一下,管理后台用frameset好还是layout好?

我以前做的系统都是frameset的。这样有个好处就是代码精简,crud生成的代码基本够用。但有个不好的地方就是div的弹出不能超过边界。

我个人感觉如果用layout的话,则需要考虑到全局代码和提取数据,这样会+大代码复杂性。因为后台管理界面有时候是上下方式(上面菜单导航,下面主工作界面),有时候是上左右方式(上面菜单导航,下面是左右分开,左边子导航,右边主工作界面)。如果用一个layout还是做不到精简的样子。还得右边用widget。增加而外代码。如果用crud生成的代码是需要大改动的。

尽量少用frameset,因为用户体验不好(尤其是前后翻页)。layout用好的话是可以很灵活的。

我最近做的一个项目需要有1列,2列和3列三种不同的layout。我是这样组织的:

在layouts目录下有:

main layout:  main.php

child layout:  layout1.php, layout2.php, layout3.php

main.php和平常的一样,layoutX.php实现X列的layout,main.php是它的parent layout。下面是layout2.php的代码:



<?php $this->beginContent(); ?>





<div class="grid_4 alpha">


	<div class="sidebar">&nbsp;


	<?php foreach($this->portlets as $portlet) $this->renderPortlet($portlet); ?>


	</div>


</div>





<div class="grid_12 omega">


	<?php $this->widget('Breadcrumbs', array('crumbs'=>$this->crumbs)); ?>





	<div id="content">


		<?php echo $content; ?>


	</div>


</div>





<?php $this->endContent(); ?>


左边是一列portlets,右边上边是breadcrumbs,下边是主内容。

使用上略微复杂。下面是post list view:



<?php


$this->layout='layout2';





$this->portlets[]=array('class'=>'LetterFilterPortlet', 'selection'=>$form->letter);


$this->portlets[]=array('class'=>'StatusFilterPortlet', 'selection'=>$form->status);


$this->portlets[]=array('class'=>'CityFilterPortlet', 'selection'=>$form->city);


$this->portlets[]=array('class'=>'CategoryFilterPortlet', 'selection'=>$form->category);


?>





<h1>Posts</h1>





<?php $this->renderPartial('_list',array(


	'pages'=>$pages,


	'models'=>$models,


)); ?>


其中portlets的代码可以进一步优化(例如从数据库里读配置)。最前面的一段代码也可以移到controller里去做,或是通过一个函数来做。

怎么让main.php是layout2.php的父layout?我看了您在别的帖子写的

<?php $this->beginContent('/path/to/layoutB'); ?>


stuff for layout A


<?php echo $content; ?> this is from the view


stuff for layout A


<?php $this->endContent(); ?>

beginContent里面会调用父layout。但这里没有这么写?难道哪里可以配置吗?

谢谢指教。

假如beginContent()里没有参数,那么view的内容将被插入到当前controller缺省的layout,也就是main.php

action里面定义了layout属性,但没有找到layout,没有报错。只出view的内容。

	public function actionAdmin(){


		$this->layout='layout2';


...


		$this->render('admin',array(


			'parentOrgan'=>$parentOrgan,


			'organList'=>$organList,


			'pages'=>$pages,


			'sort'=>$sort,


		),false,true);





系统采用了module和theming了。layout2.php放在themes\classic\views\layouts下面,配置文件配置了classis 这个theming激活。

如果你这个action是在一个module里的话,layout2只在module的layouts目录下找。

<div class="grid_4 alpha">

&lt;div class=&quot;sidebar&quot;&gt;&amp;nbsp;


&lt;?php foreach($this-&gt;portlets as $portlet) $this-&gt;renderPortlet($portlet); ?&gt;


&lt;/div&gt;

</div>

不明白$this->renderPortlet($portlet);在这里的意义。为什么不直接widget,还要包装。是不是有哪些要处理?

renderPortlet是做了一些处理,不过你用widget也是可以的。看你自己的需要了。

我还是想不通,$portlet就两个属性,一个class一个selection,再怎么变数也没法用一个统一的renderPortlet来做处理啊?用下面代码

<?php foreach($this->portlets as $portlet) $this->widget($portlet->class,array($portlet->selection)); ?>应该可以的?

可以举例renderPortlet里有什么特殊处理吗?

差不多是这样。单独写个函数是为了看起来更清晰。事实上,可能写个renderPortlets更有意义。毕竟这个函数是需要在每个页面上调用的。

写了个cookbook教程:http://www.yiiframework.com/doc/cookbook/28/

Quote

写了个cookbook教程:http://www.yiiframework.com/doc/cookbook/28/

刚在你的教程下提了个问题,但格式有问题,我在这里在贴一下:

I have some issues to have this work with theme,

for example,

here is the index.php view file



    <?php


    $this->layout='column1';


    ?>


    TEST


and this is colum1.php layout file:



    <?php $this->beginContent(); ?>


    <div id="content">


    <?php echo $content; ?>


    </div> 


    <?php $this->endContent(); ?>


the problem is column1 layout was rendered, but main.php layout wasn't.

Any idea?

你的column1.php和main.php都在theme里么?

Quote

你的column1.php和main.php都在theme里么?

没错,都在 /themes/classic/views/layouts 同一个folder下

我刚试过,没问题啊。

我用的是yiic webapp产生的testdrive。在app config里使用classic theme。在index view里设定用column1.php。

Quote

我刚试过,没问题啊。

我用的是yiic webapp产生的testdrive。在app config里使用classic theme。在index view里设定用column1.php。

不好意思,确认了,在一般app里面是好的。

但使用Module时就不行,我现在用module command 建了一个module: testmodule, 在theme目录下建立:

/themes/classic/views/testmodule/layouts  (里面有 main.php, column1.php)

/themes/classic/views/testmodule/default (里面有 index.php)

php文件都是和上面中同样的内容, 现在的问题是, Yii 正确使用了

/themes/classic/views/testmodule/layouts/column1.php

但父layout文件使用的是:

/themes/classic/views/layouts/main.php

应该使用

/themes/classic/views/testmodule/layouts/main.php

有什么地方错了吗?

你的module没有设置layout属性吧?如果没设的话,用的是application的layout。

Quote

你的module没有设置layout属性吧?如果没设的话,用的是application的layout。

我在TestModule.php 里面加了:

	public function init()


	{


		// this method is called when the module is being created


		// you may place code here to customize the module or the application





		// import the module-level models and components


		$this->setImport(array(


			'testmodule.models.*',


			'testmodule.components.*',


		));


		$this->setLayoutPath('themes/classic/views/testmodule/layouts');


	}

还是一样的结果,设定有什么不对吗?

问题是,为什么可以找到module layout 的 column1.php 却不能找到 main.php?

我说的是module的layout属性。它的缺省值是null,意思是用application定义的layout。

用下面的代码就可以了:



class MyModule extends CWebModule {


    public $layout='main'; 


}


Quote

我说的是module的layout属性。它的缺省值是null,意思是用application定义的layout。

用下面的代码就可以了:



class MyModule extends CWebModule {


    public $layout='main'; 


}


明白了,谢谢!