Cakephp 3无效的数据类型,必须是数组或\ ArrayAccess实例

时间:2016-02-14 23:56:40

标签: cakephp

我已经烘焙了这个标准的添加类,它可以正常工作。

class ClientsController extends AppController
{
 /**
 * Add method
 *
 * @return \Cake\Network\Response|void Redirects on successful add, renders view otherwise.
 */
 public function add()
 {
    $client = $this->Clients->newEntity();
    if ($this->request->is('post')) {
        $client = $this->Clients->patchEntity($client, $this->request->data);
        if ($this->Clients->save($client)) {
            $this->Flash->success(__('The client has been saved.'));
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error(__('The client could not be saved. Please, try again.'));
        }
    }
    $this->set(compact('client'));
    $this->set('_serialize', ['client']);
}

使用此add.ctp文件 - 输出应该是:

<div class="clients form large-9 medium-8 columns content">
<?= $this->Form->create($client) ?>
<fieldset>
    <legend><?= __('Register Customer') ?></legend>
    <?php
        echo $this->Form->input('company_indicator');
        echo $this->Form->input('name');
        echo $this->Form->input('name2');
        echo $this->Form->input('address_id');
        echo $this->Form->input('address_street');
        echo $this->Form->input('address_street_number');
        echo $this->Form->input('address_postal_code');
        echo $this->Form->input('address_city');
        echo $this->Form->input('address_country');
        echo $this->Form->input('address_lat');
        echo $this->Form->input('address_lng');
        echo $this->Form->input('phone1');
        echo $this->Form->input('phone2');
        echo $this->Form->input('fax');
        echo $this->Form->input('website');
        echo $this->Form->input('logo');
        echo $this->Form->input('vat_number');
        echo $this->Form->input('taxId');
        echo $this->Form->input('tax_office');
    ?>
 </fieldset>
 <?= $this->Form->button(__('Submit')) ?>
 <?= $this->Form->end() ?>
</div>

我尝试使用向导步骤

class ClientsController extends AppController
{
/**
 * use beforeRender to send session parameters to the layout view
 */
 public function beforeRender(Event $event) {
    parent::beforeRender($event);
    $params = $this->request->session()->read('Form.params');
    $this->set(compact('params'));
}

/**
 * delete session values when going back to index
 * you may want to keep the session alive instead
 */
public function regIndex() {
    $this->request->session()->delete('Form');
}

/**
 * this method is executed before starting 
 * the form and retrieves one important parameter:
 * the form steps number by counting the number 
 * of files that start with reg_step
 */
public function regSetup() {
        $clientsViewFolder = new Folder(APP.'Template'.DS.'Clients');
        $steps = count($clientsViewFolder->find('reg_step.*\.ctp'));
        $this->request->session()->write('Form.params.steps', $steps);
        $this->request->session()->write('Form.params.maxProgress', 0);
        $this->redirect(array('action' => 'regStep', 1));
}

    /**
     * this is the core step handling method
     * it gets passed the desired step number, performs some checks to prevent smart users skipping steps
     * checks fields validation, and when succeding, it saves the array in a session, merging with previous results
     * if we are at last step, data is saved
     * when no form data is submitted (not a POST request) it sets this->request->data to the values stored in session
     */
    public function regStep($stepNumber) {

        $this->log('regStep($stepNumber)= ' . $stepNumber , 'debug');

        /**
         * check if a view file for this step exists, otherwise redirect to index
         */
        if (!file_exists(APP.'View'.DS.'Clients'.DS.'reg_step'.$stepNumber.'.ctp')) {
                        $this->redirect('/clients/reg_index');
        }

      $session = $this->request->session();

        /**
         * determines the max allowed step (the last completed + 1)
         * if choosen step is not allowed (URL manually changed) the user gets redirected
         * otherwise we store the current step value in the session
         */
        $maxAllowed = $this->request->session()->read('Form.params.maxProgress') + 1;
        if ($stepNumber > $maxAllowed) {
                        $this->redirect('/clients/reg_step/'.$maxAllowed);
        } else {
                        $session->write('Form.params.currentStep', $stepNumber);
        }

        $client = $this->Clients->newEntity();
        $client->name = 'Tiknas';

        /**
         * check if some data has been submitted via POST
         * if not, sets the current data to the session data, to automatically populate previously saved fields
         */
        if ($this->request->is('post')) {
                /**
                 * set passed data to the model, so we can validate against it without saving
                 */
                 $client = $this->Clients->patchEntity($client, $this->request->data);

                /**
                 * if data validates we merge previous session data with submitted data, using CakePHP powerful Hash class (previously called Set)
                 */
                if ($this->Client->validates($client)) {
                        $prevSessionData = $session->read('Form.data');
                        $currentSessionData = Hash::merge( (array) $prevSessionData, $this->request->data);

                        /**
                         * if this is not the last step we replace session data with the new merged array
                         * update the max progress value and redirect to the next step
                         */
                        if ($stepNumber < $session->read('Form.params.steps')) {
                                $session->write('Form.data', $currentSessionData);
                                $session->write('Form.params.maxProgress', $stepNumber);
                                $this->redirect(array('action' => 'reg_step', $stepNumber+1));
                        } else {
                                /**
                                 * otherwise, this is the final step, so we have to save the data to the database
                                 */
                                if ($this->Client->save($currentSessionData))
                                {
                                        $this->Flash->success(__('Customer created!'));
                                        return $this->redirect('/clients/reg_index');
                              } else {
                                        $this->Flash->error(__('The client could not be saved. Please, try again.'));
                                }
                        }
                }
        } else {
                $this->request->data = $session->read('Form.data');
        }

        $this->set(compact('client'));
        $this->set('_serialize', ['client']);

        /**
         * here we load the proper view file, depending on the stepNumber variable passed via GET
         */
        $this->render('reg_step'.$stepNumber);
    }

}

使用此reg_step1.ctp文件会导致错误:

<div class="clients form large-9 medium-8 columns content">
<?= $this->Form->create($client) ?>
<fieldset>
    <legend><?= __('Register Customer') ?></legend>
    <?php
        echo $this->Form->input('company_indicator');
        echo $this->Form->input('name');
        echo $this->Form->input('name2');
        echo $this->Form->input('address_id');
        echo $this->Form->input('address_street');
        echo $this->Form->input('address_street_number');
        echo $this->Form->input('address_postal_code');
        echo $this->Form->input('address_city');
        echo $this->Form->input('address_country');
        echo $this->Form->input('address_lat');
        echo $this->Form->input('address_lng');
        echo $this->Form->input('phone1');
        echo $this->Form->input('phone2');
        echo $this->Form->input('fax');
        echo $this->Form->input('website');
        echo $this->Form->input('logo');
        echo $this->Form->input('vat_number');
        echo $this->Form->input('taxId');
        echo $this->Form->input('tax_office');
    ?>
</fieldset>
<?= $this->Html->link('Next step',
    array('action' => 'reg_step', $params['currentStep'] + 1),
    array('class' => 'button')); ?>
<?= $this->Form->end(); ?>
</div>

错误明细

==&GT;无效的数据类型,必须是数组或\ ArrayAccess实例。 ==&GT; InvalidArgumentException

⟩Cake \ View \ Helper \ FormHelper-&gt;输入 APP / Template \ Clients \ reg_step1.ctp,第9行 这对应于这一行             echo $ this-&gt; Form-&gt; input(&#39; company_indicator&#39;);

我尝试了同样的评论这一行,但我得到了同样的错误。

我检查了两个示例中为空的$ client。 (YES $ client是一个实体)

我搜索了这个错误,但发现只有HASH错误与这种情况无关。控制器中一定有错误,但我找不到它。为什么在此上下文中引发此错误?我在哪里搜索才能找到真正的问题?有什么想法吗?

StackTrace:

2016-02-15 21:50:50 Error: [InvalidArgumentException] Invalid data type, must be an array or \ArrayAccess instance.
Request URL: /pam/clients/reg-step/1
Referer URL: http://localhost/pam/clients/regIndex
Stack Trace:
#0  C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\Network\Request.php(1158): Cake\Utility\Hash::get(NULL, 'company_indicat...')
#1 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\View\Form\EntityContext.php(208): Cake\Network\Request->data('company_indicat...')
#2 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\View\Helper\FormHelper.php(2385): Cake\View\Form\EntityContext->val('company_indicat...')
#3 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\View\Helper\FormHelper.php(1387): Cake\View\Helper\FormHelper->_initInputField('company_indicat...', Array)
#4 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\View\Helper\FormHelper.php(1115): Cake\View\Helper\FormHelper->checkbox('company_indicat...', Array)
#5 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\View\Helper\FormHelper.php(1023): Cake\View\Helper\FormHelper->_getInput('company_indicat...', Array)
#6 C:\Users\D052192\OneDrive\xampp\htdocs\pam\src\Template\Clients\reg_step1.ctp(9): Cake\View\Helper\FormHelper->input('company_indicat...', Array)
#7 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\View\View.php(992): include('C:\\Users\\D05219...')
#8 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\View\View.php(952): Cake\View\View->_evaluate('C:\\Users\\D05219...', Array)
#9 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\View\View.php(587): Cake\View\View->_render('C:\\Users\\D05219...')
#10 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\Controller\Controller.php(611): Cake\View\View->render('reg_step1', NULL)
#11 C:\Users\D052192\OneDrive\xampp\htdocs\pam\src\Controller\ClientsController.php(250): Cake\Controller\Controller->render('reg_step1')
#12 [internal function]: App\Controller\ClientsController->regStep('1')
#13 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\friendsofcake\crud\src\Controller\ControllerTrait.php(51): call_user_func_array(Array, Array)
#14 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\Routing\Dispatcher.php(114): App\Controller\AppController->invokeAction()
#15 C:\Users\D052192\OneDrive\xampp\htdocs\pam\vendor\cakephp\cakephp\src\Routing\Dispatcher.php(87): Cake\Routing\Dispatcher->_invoke(Object(App\Controller\ClientsController))
#16 C:\Users\D052192\OneDrive\xampp\htdocs\pam\webroot\index.php(37): Cake\Routing\Dispatcher->dispatch(Object(Cake\Network\Request), Object(Cake\Network\Response))
#17 {main}

1 个答案:

答案 0 :(得分:4)

查看堆栈跟踪,请求数据(Request::$data)为null,而Hash::get()不喜欢这样。

问题源于您的第二次$session->read('Form.data')调用,在某些时候该值尚不存在/不再存在,因此该方法将返回null,并且您将使用它覆盖请求数据

根据您的向导逻辑的适用性,确保您要么检索一个空数组(就像您在第一次调用时所做的那样),或者在这些情况下不要覆盖请求数据。