spController修改成员变量后,模板内不能更新

#1 dhs789520

代码如下:
 
class main extends spController
{
function index(){
  $this->title='你好';
  $this->title='再见';//此句修改对模板无效
  $this->display('index.html');
}
}

分析原因:
模板assign是在spController 中的 __set()函数中设置的
但是修改变量却没有相应代码更新
解决方案:
1.注释掉没用的魔术函数__set()
2.将 private $v ;/应该对代码没有影响吧??
3.在display()中对模板assign赋值
增加代码如下:
 
$array=get_object_vars($this);
foreach($array as $name => $value){
if(TRUE == $GLOBALS['G_SP']['view']['enabled'] && false !== $value){
   $this->v->engine->assign(array($name=>$value));
}
$this->__template_vals[$name] = $value;
}


请问jake老大,这样可好??
我是开发中遇到问题才想改框架的

2011-04-27 11:49:20

#2 jake

之前不是回复过了吗?
http://speedphp.com/bbs/thread-1513-1-1.html

2011-04-27 12:46:08

#3 dhs789520

回复 2 jake

jake老大,貌似上次已经解决了问题,可问题的实质是使用__set()函数的缺陷,所以不能使用此函数为模板赋值,

2011-04-27 12:55:27

#4 jake

这个我还在研究当中,我没觉得__set有什么问题,主要在于语言结构方面的思量。

你可以根据你的需要来改。
对了,你打开PHP的notice就会明白了。

2011-04-27 13:06:45

#5 dhs789520

回复 4 jake

我不知道jake为什么会对一个重要的流程控制漏洞置之不理

一。当新增一个不存在的变量时,通过__set()  assign在模板中相应新增一个变量
二。当修改一个已存在的变量时,没有修改模板变量中的值,不是问题吗?

流程应该在display()中设置模板变量,也就是最后

2011-04-27 14:38:08

#6 jake

呵呵,我不明白你希望的是什么?

原生PHP没有规定这样是模板赋值,对吧?

$this->赋值这个方法,是一个框架给出的“规则”,现在考虑的是否修改“规则”,明白吗?

当然,如果你不能理解“规则”和“原生语法”,那么我也无话可说了。

2011-04-27 19:07:08

#7 windman

没觉得有什么问题啊,_set原来就是魔术方法,这个魔术方法的作用就是给没赋值的成员赋值,你
$this->title='你好';//这是第一次赋值,用的是_set
$this->title='再见';//这是第二次赋值,起了作用,但赋值是正常的赋值,没用到_set,当然修改不了,这个相当于变成成员变量了。

2011-04-27 20:36:08

#8 dhs789520

但是你使用smarty模板的时候,模板变量的值就只能是第一次赋的值了,永远不会改变

2011-04-27 20:44:37

#9 dhs789520

回复 6 jake
不知道jake用不用自己的框架,我们总会修改变量值吧,可是修改后的值在”!模板!”中却不能修改,不知道群主可理解我不善于表达的语言?

2011-04-27 20:52:49

#10 windman

这就是_set魔术方法的作用,基本框架都这么做的,方便传值给模板。至于修改值,你方法不对,JAKE在另一贴已经说过,你可以先用临时变量赋值,最后才用$this-title,前面你完全可以用$title

2011-04-27 21:10:13

#11 dhs789520

回复 10 windman

哈哈哈哈,所以我觉得稍微改一下框架,删除__set()函数,在display()中增加模板变量定义就可以完全避免模板内外变量不一致的问题,难道这会制约框架的简约性吗?

2011-04-27 21:22:57

#12 windman

或许不会,但你要明白,一个是给控制器用的普通成员变量,一个是赋给视图用作模板变量的。
你这样不是提前赋值,而是display的时候才赋值,如果多个display呢?重复赋值?

2011-04-27 21:59:00

#13 dhs789520

重复赋值会怎么样?效率低?赋错值又会怎么样?

2011-04-27 22:09:11

#14 windman

效率低不低不知道了,不过你可以看下display的流程,先C的display,再V的display,再到模板引擎的display,不知道你所说的赋错值如何理解

2011-04-27 22:49:58

#15 jake

能否先打开php的notice试过后,才来研究这个问题呢?

这样说吧,我见过另一个框架,它的模板赋值,是通过display的第二个参数传入的,为什么它不用$this->传值呢?这都是规则。

或许这个规则需要改变,但我个人最近没时间,最近有太多的新想法了,希望过了这段时间后能一一实现。请原谅。

这里可以介绍一个很简单的方法,可以达成楼主的想法,就是如同继承于spModel一样,做个继承于spController的类,然后继承重写display,那么就可以做到了。或者说想怎么用都可以。

2011-04-27 23:11:38

#16 dhs789520

回复 15 jake


  最近我在反复考虑我发的帖子和我们之间的谈话内容,

发现了一个重要问题,如果一个团队之间沟通出现了问题,那项目基本不会完成



原来我所表达的意思,发到网上来之后却变成了另一个样子了,

所以导致jake的误解,以为我要修改 框架规则,修改$this->的赋值方法,



其实我并不是修改用户的操作,($this->赋值非常好),

也不想在display()函数中增加一个参数,

所以我的目的不是修改框架用户的用户操作方式及用户体验,

用户的操作方式还是和以前一样,$this->赋值

用户不在display()中增加任何参数

用户不修改任何代码

而是框架设计者在spController中修改后台代码,

1.让$this->赋值在刚赋值的时候遵守php语法的严格性,并且成为spController中的成员变量

2.__set()   函数对新建的成员变量不直接赋值给smarty模板,

因为spController类中的变量在display()函数前都有被用户更改的可能性

而更改成员变量并没有在spController的代码中对smarty中的变量做相应操作

3.所以我觉得通过在spController中的display函数中增加代码,让用户在display()时

再查找所有的成员变量给smarty模板赋值.

关键代码:
 /**
* 输出模板
*
* @param $tplname 模板路径及名称
* @param $output 是否直接显示模板,设置成FALSE将返回HTML而不输出
*/
public function display($tplname, $output = TRUE)
{
//水哥新增加代码部分
//获得所有public成员变量,赋值给模板
$array=get_object_vars($this);
foreach($array as $name => $value){
if(TRUE == $GLOBALS['G_SP']['view']['enabled'] && false !== $value){
$this->v->engine->assign(array($name=>$value));
}
$this->__template_vals[$name] = $value;
}
//ends of 水哥

@ob_start();
if(TRUE == $GLOBALS['G_SP']['view']['enabled']){
$this->v->display($tplname);
}else{
extract($this->__template_vals);
require($tplname);
}
if( TRUE != $output )return ob_get_clean();
}

2011-05-02 07:53:02

#17 jake

好的,楼上的意见很好,我明白楼上的意思。

不过,这里需要时间研究一下,毕竟此问题的讨论比较多,希望楼上别介意。

任何一个提出的问题,我从来没有说过不修改,但是也没说过一提就改。

另外,感谢一下楼上的坚持:)

2011-05-02 23:47:23