Php 在atk4中,如何使用ajax更新视图

Php 在atk4中,如何使用ajax更新视图,php,ajax,frameworks,agile,atk4,Php,Ajax,Frameworks,Agile,Atk4,我目前定义了一个页面,它以行的形式显示一些数据。在每一行的末尾,都有一个视图,其中显示了从mysql中提取的总数 $r->add('View_PointsLeft', 'pleft', 'pointsleft') ->setPoints($row['points_left']) ->setBacklog($row['backlog_ref']) ->setID($row['id'].'-points-lef

我目前定义了一个页面,它以行的形式显示一些数据。在每一行的末尾,都有一个视图,其中显示了从mysql中提取的总数

$r->add('View_PointsLeft', 'pleft', 'pointsleft')
           ->setPoints($row['points_left'])
           ->setBacklog($row['backlog_ref'])
           ->setID($row['id'].'-points-left');
视图是使用如下模板定义的

<!-- points left -->
<div  class='target points_left'>
  <div class='sticky green'>
    <div class='story'><?$backlog?></div>
    <div id='<?$name?>' class='big_points big_point_margin'><?$pointsleft?></div>
  </div>
</div>
<!-- end 0000-points-left -->
 $r->add('View_PointsLeft', 'pleft', 'pointsleft')
               ->loadData($row['id']);
<div id='<?$name?>' class='target points_left'>
  <div class='sticky green'>
    <div class='story'><?$backlog_ref?></div>
    <div class='big_points big_point_margin'><?$points_left?></div>
  </div>
</div>
<?php
class View_PointsLeft extends View_Sticky {

   function loadData($id){
  $this->setModel('Story')->loadData($id);
   }

   function init(){
      parent::init();
   }

   function defaultTemplate(){
      return array('view/scrumwall/pointsleft');
   }
}
我想在页面上发生更改时更新数据库,并更新总视图(以减少计数器)

首先,我想知道我是否采用了错误的方法(每个视图都应该是自包含的)-我是否应该将id字段传递给视图,将相关模型附加到lib/view/pointsleft.php中的视图,并使用模型值调用set字段

其次,如果我以这种方式进行更改,那么当使用ajax更改数据库值时,是否可以更轻松地使用特定id更新视图?如果是,我该如何做

第三,如果我还想根据客户端javascript上的一个操作触发对数据库的更新,我会把这段代码放在哪里?例如,在非atk4版本的代码中,我有一个名为using$.post(“update.php”)的脚本,它会更新mysql。我应该把这样的脚本放在ATK4的什么地方

提前谢谢


罗马人回答后更新

伙计,四块石头它比我预期的做得更多,我正忙于在视图中创建函数来填充每个字段名,所以现在使用addModel重做它

页面中的调用如下所示

<!-- points left -->
<div  class='target points_left'>
  <div class='sticky green'>
    <div class='story'><?$backlog?></div>
    <div id='<?$name?>' class='big_points big_point_margin'><?$pointsleft?></div>
  </div>
</div>
<!-- end 0000-points-left -->
 $r->add('View_PointsLeft', 'pleft', 'pointsleft')
               ->loadData($row['id']);
<div id='<?$name?>' class='target points_left'>
  <div class='sticky green'>
    <div class='story'><?$backlog_ref?></div>
    <div class='big_points big_point_margin'><?$points_left?></div>
  </div>
</div>
<?php
class View_PointsLeft extends View_Sticky {

   function loadData($id){
  $this->setModel('Story')->loadData($id);
   }

   function init(){
      parent::init();
   }

   function defaultTemplate(){
      return array('view/scrumwall/pointsleft');
   }
}
模板/视图如下所示

<!-- points left -->
<div  class='target points_left'>
  <div class='sticky green'>
    <div class='story'><?$backlog?></div>
    <div id='<?$name?>' class='big_points big_point_margin'><?$pointsleft?></div>
  </div>
</div>
<!-- end 0000-points-left -->
 $r->add('View_PointsLeft', 'pleft', 'pointsleft')
               ->loadData($row['id']);
<div id='<?$name?>' class='target points_left'>
  <div class='sticky green'>
    <div class='story'><?$backlog_ref?></div>
    <div class='big_points big_point_margin'><?$points_left?></div>
  </div>
</div>
<?php
class View_PointsLeft extends View_Sticky {

   function loadData($id){
  $this->setModel('Story')->loadData($id);
   }

   function init(){
      parent::init();
   }

   function defaultTemplate(){
      return array('view/scrumwall/pointsleft');
   }
}
我有一个if块,在页面中看起来像这样。我添加了Model_任务,并根据GET参数加载值,这样我还可以获得更多信息,包括它所涉及的故事,因此如果状态现在完成,我还可以更新点

   if($_GET['task'] && $_GET['status'])
   {
        $new_status=$_GET['status'];
        $task_id=$_GET['task'];
        $t=$p->add('Model_Task')->loadData($task_id);
        $old_status=$t->get('status');
        $task_points=$t->get('points');

        if ($new_status<>$old_status & ($new_status=='D' | $old_status=='D'))
        {
           $s=$p->add('Model_Story')->loadData($t->get('story_id'));
           if ($old_status='D')
           {
             $s->set('points_left',$s->get('points_left')+$task_points);
           } else {
             $s->set('points_left',$s->get('points_left')-$task_points);
           }
           $s->update();

           $story=$t->get('story_id');
        }
    $t->set('status',$new_status);
    $t->update();
   }
然后在处理GET时在if块中调用它

       $pleft=$this->pl_arr[$story];
       $pleft->js()->reload()->execute();
但它失败了,出现了一个错误

AJAXec响应中的错误:语法错误:缺少;声明前 致命错误:在C:\wamp\www\paperless\page\scrumwall.php第247行的非对象上调用成员函数js()


最终更新

最后一个错误是因为我没有在我想要更新的整个视图的外部div中使用id。一旦我改变了这个,它就不再是空的

因此,第一次加载页面时,我将所有视图名称存储在一个关联数组中的循环中,并将它们放在页面上

    $st = $p->add('Model_Story');
    $result = $st->getRows();

    foreach ($result as $row) {
    if (is_array($row)) {
         $r=$p->add('View_Scrumwall_StoryRow')
               ->setWorkspace('ws-'.$row['id']);

        ... other code here ...

      $points_left[$row['id']]=$r->add('View_PointsLeft', null, 'pointsleft')
                      ->loadData($row['id']);
    }
然后让if GET块像这样

   if($_GET['task'] && $_GET['status'])
   {
        $new_status=$_GET['status'];
        $task_id=$_GET['task'];
        $t=$p->add('Model_Task')->loadData($task_id);
        $old_status=$t->get('status');
        $task_points=$t->get('points');

        if ($new_status<>$old_status && ($new_status=='D' || $old_status=='D'))
        {
           $s=$p->add('Model_Story')->loadData($t->get('story_id'));
           if ($new_status=='D')
           {
             $s->set('points_left',$s->get('points_left')-$task_points);
           } else {
             $s->set('points_left',$s->get('points_left')+$task_points);
           }
           $s->update();
           $story=$t->get('story_id');
           //reload the points left sticky note for the story of the task
           $js[]=$points_left[$story]->js()->reload();
        }
        $t->set('status',$new_status);
        $t->update();
        $js[]=$this->js()->reload();
        $this->js(null,$js)->execute();
   }

用ATK4解决的问题:)

您的结构似乎正常。如果对其使用setModel(),它将包含“pointsleft”和“backlog”字段,这些字段将自动填充

虽然我不知道setID是如何定义的,但是您可以扩展setModel,调用parent,然后执行它

我注意到的另一件事是,在模板中,最顶级的div应该具有id=''。这为视图提供了唯一的选择器,js()默认使用该选择器

您正在查找的.post函数是univ()->ajaxec()。它将数据发送到服务器,接收javascript并执行它,因此得名。它的行为与表单类似

$mybutton->js('click')->ajaxec($this->getDestinationURL(null,array('a'=>'b'));

if($_GET['a']){
    // update database
    $r->getElement('plfat')->js()->reload()->execute();
}
通常,为了使代码具有通用性,可以将上述代码放到视图中,但最好使用对象的名称,而不是“a”,如下所示。这样就不需要单独的页面处理更新:

$this->mybutton->js('click')->ajaxec($this->getDestinationURL(null,
     array($this->name=>'reload'));

if($_GET[$this->name]){
    // update database
    $this->js()->reload()->execute();
}

更新

要澄清其执行顺序,请执行以下操作:

  • 页面将呈现为发送到浏览器的HTML
  • 与页面一起发送Javascript链。定义js的第一个参数的所有参数,例如js(true)、js('click')。在我的代码中有js('click'),所以它被发送到浏览器
  • 用户执行诸如单击按钮之类的操作。这将触发ajaxec()函数
  • ajaxec函数使用您在其中指定的参数对页面执行AJAX请求
  • PHP再次被执行,但这次它进入if()分支。将创建一个不带参数的js(),并->执行()将javascript发送到浏览器
  • 浏览器接收js()…->execute()的输出并对其求值。在本例中,它包含其他元素的reload()
  • atk4_loader小部件用于执行页面其他部分的重新加载,它向服务器发送AJAX请求
  • PHP使用cut_对象参数执行。它重新初始化原始页面,但仅选择性地呈现一个对象。该对象的输出将发送回前端
  • PHP也会像#2中那样重新生成JS链,但只与该对象相关
  • 前端的atk4_加载器接收代码,替换元素的HTML并重新计算javascript
  • 回到#3

  • 听起来好像有很多动作。实际上,每次点击2个请求,如果您立即重新加载,您可以消除一个请求。请注意,还可以将参数传递给reload(),然后从“get”获取该参数。我不完全理解是什么触发了您原始脚本中的操作,也许我们可以在?

    中找到这一点。好的,为了得到更清晰的答案,我收集了一个示例:

    也许这里的例子更好地回答了这个问题

    在您的情况下,因为您使用的是模型,所以应该更容易进行设置。对于性能,我决定使用两个列表器,但理论上也可以将每个人和任务作为一个视图


    我在会话中存储关联(通过记忆),在您的情况下,您可以将它们存储在数据库中

    好的,我现在有了一个模型,它根据原始问题的更新填充视图中的字段。我还将id移到了外部div(它位于内部div上,基于之前使用jquery直接更新左侧点的方式[没有ATK4的好处])。因此,我想在特定操作上执行视图的重新加载-不是单击按钮,但我假设主体将是相同的-我需要在视图中的哪个函数中放置js()->reload()->execute()的代码;我在星期四的其他地方怎么称呼它