【问题标题】:Zend Framework - Passing a variable within a controller for an ajax callZend 框架 - 在控制器中传递变量以进行 ajax 调用
【发布时间】:2009-07-07 19:11:30
【问题描述】:

你好,在斯塔克兰!这是我的问题:

我想使用我的 Zend 控制器从数据库中加载一个数组,然后将它传递给 javascript。我决定最好的方法是使用 ajax 向控制器询问它的数组,将其编码为 json,然后将其传递下来。但是,我不知道如何将我在第一个操作中加载的变量传递给通过 ajax 调用它时将其传递下来的操作。

产生视图的原始动作

public function indexAction()
    {
            $storeid = $this->getStoreId();

            if(!$storeid)
            {
                 $this->_forward('notfound');
                 return;
            }

            $store = $this->_helper->loadModel('stores');
            $store->getByPrimary($storeid);
    }

将通过 ajax 调用的操作

public function getdataAction()
        {
            $this->_helper->Layout->disableLayout(); // Will not load the layout
            $this->_helper->viewRenderer->setNoRender(); //Will not render view

            $jsonResponse = json_encode($store);
            $this->getResponse()->setHeader('Content-Type', 'application/json')
                                ->setBody($jsonResponse);

        }

我想要的是将 indexAction 中的 $store 传递给 getdataAction,以便它可以将 store 作为 jsonResponse 发送。请注意,它们在两个不同的时间被调用。

我尝试过但没有奏效的方法:

  1. 在 indexAction 中设置 $this->getRequest()->setParam('store', $store),然后在 getdataAction 中使用 $this->getRequest()->getParam('store')。我认为这不起作用,因为它们是不同的 http 请求,所以附加一个新参数是没用的。

  2. 在控制器本身中使用受保护的 $_store,然后使用 indexAction 保存到它,并在 getdataAction 中使用它。我不确定为什么这不起作用。

有没有一种以这种方式传递变量的好方法?有没有办法在不同的控制器之间传递变量?(我假设一个的答案是另一个的答案)。我可以将它存储在控制器助手中吗?我是否必须使用我知道会起作用但似乎没有必要的会话?有没有更好的方法将变量传递给javascript?我问的问题太多了吗?任何帮助都会非常出色。谢谢。

【问题讨论】:

    标签: php javascript jquery zend-framework


    【解决方案1】:

    也许我读错了问题,但您应该可以将 $store 移到构造函数中:

    public function __construct() {
        $store = $this->_helper->loadModel('stores');
        $store->getByPrimary($storeid);
    }
    

    并使其可在所有 *Action 方法中访问。使用会话似乎不适合这个。

    【讨论】:

    • 当我尝试它时,我得到致命错误:StoresController::__construct() 的声明必须与 C:\xampp\htdocs\BC\application\ 中 Zend_Controller_Action_Interface::__construct() 的声明兼容第 177 行的 controllers\StoresController.php 你知道这是什么意思吗?
    • 你的 __construct 必须与父类声明相同,在这种情况下是: public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array()) { .. . } 另外,不要忘记调用 parent::__construct($request, $response, $invokeArgs);在构造函数的末尾。
    • 使用 ::preDispatch - 或者更好的是受保护的 ::_getStore($id) 类型调用。
    • @JustinJohnson 我知道这个问题已经很老了,但是你能解释一下如何解决这个问题吗 __construct() 必须与 Zend_Controller_Action_Interface 兼容
    • 调用 parent::__construct 方法最简单的方法是在扩展类的 __construct 中添加call_user_func_array("parent::__construct", func_get_args());。如果 Zend_Controller_Action_Interface::__construct 的形式参数发生变化,这允许您向前兼容(至少在您的扩展类中)。
    【解决方案2】:

    (免责声明:我对 ZF 很陌生,所以我对此处找到的其他答案很感兴趣,并且没有测试过以下内容!)

    在您看来,您将 ajax 调用放在哪里,您可能会像这样处理它:

    (见ZF Documentation

    <?= $this->ajaxLink("Example 2",
                        "/YourController/getdata",
                        array('update' => '#content',
                              'class' => 'someLink'),
                        array('store' => $this->store)); ?>
    

    请注意,在您的 indexAction 中,您通过以下方式存储商店:

     $this->view->store = $storeid;
    

    当然,您应该注意,网络用户可以修改通过 URL 传递的 store 参数。

    【讨论】:

    • 想到了,但它的安全性太大了。
    【解决方案3】:

    将一个方法简单地添加到您的 IndexController、一个帮助程序或某个地方,以返回一个 Store 的实例,这将是更好的架构。在 indexAction 和 getdataAction 中使用该方法(将其称为 ajaxAction 会更有意义)。此外,您忘记调用 sendResponse()(请记住,您禁用了 autoRender):

        private function indexAction()
        {
            $this->getStore();
            //blah blah
        }
    
        private function getStore()
        {
            $storeid = $this->getStoreId();
            if(!$storeid)
            {
                 $this->_forward('notfound');
                 return;
            }
            $store = $this->_helper->loadModel('stores');
            $store->getByPrimary($storeid);
            return $store;
        } 
    
        public function ajaxAction()
        {
            $this->_helper->Layout->disableLayout(); // Will not load the layout
            $this->_helper->viewRenderer->setNoRender(); //Will not render view
    
            $jsonResponse = json_encode($this->getStore());
            $this->getResponse()->setHeader('Content-Type', 'application/json')
                                ->setBody($jsonResponse)
                                ->sendResponse();
    
        }
    

    The manual says:

    发送响应输出,包括 标头,使用 sendResponse()。

    http://framework.zend.com/manual/en/zend.controller.response.html

    【讨论】:

    • 好吧,我试图简化我的问题,这样就不会让人难以理解。现在,我们将假设 $store 是一个数组。我不想进行两次 sql 调用来将数据放入 $store 数组。我想在 indexAction 中进行一次调用,然后能够在 getdataAction 中访问该数据。这可能吗?
    • 如果您的控制器要进行该查询,您应该将其存储在控制器的 init()(构造函数)方法中初始化的类变量中。然后可以通过任何操作访问它。我对你的理解正确吗?
    • 如 init(){$store = $this->getStore()}?这仍然不会让我使用 getdataAction 获取 $store。
    • 什么意思?我可以看到您正在 indexAction() 中初始化存储。如果您移动了语句 $storeid = $this->getStoreId();到 init(),而是使用 $this->storeid = $this->getStoreId(); 然后它可以在控制器中的任何地方使用,前提是您将私有 $store 变量添加到您的类(私有 $store = null;)例如。初始化后,您可以从控制器中的任何位置以 $this->store 的形式访问它。
    • 好的,我明白你现在的意思了,但这仍然意味着每次调用一个动作时都会调用 init,这意味着有几个不必要的 SQL 调用。我的问题不是这个特定的页面,而是能够调用 SQL 一次,然后在我的控制器(以及理想情况下,其他控制器)中传递一个已经创建的对象。有没有办法做到这一点?对不起,如果我打扰你了。
    【解决方案4】:

    好吧,对于那些也想知道这个问题的人,我只是把它吸了起来并使用了 session。我在引导程序中放了一个 Zend_Session->start() 。然后我创建了一个插件来为每个控制器添加一个私有变量 $session。然后我将 $this->session 设置为 Zend_Session_Namespace。为了传递一些东西,我通过会话传递它,所以我使用 $this->session->store = $store.然后我可以使用 $this->session->store 在别处获取它。感谢那些试图提供帮助的人!

    【讨论】:

    • 是什么让这很糟糕?是您应用的非面向对象的方法,是会话的使用(可能在您的两次调用之间过期)还是这里有一些不安全的东西? (也许这应该是一个独立的问题)
    【解决方案5】:

    只是对 cme​​ts 的快速添加。要从控制器中将数组输出为 JSON,请使用:

    $array = array('hi' => array('Hello' => 'World');
    $this->_helper->json($array);
    

    这会发送响应并设置 JSON 响应的特定标头

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-01
      • 2020-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多