passing an array from view to controller to model

by Nathanael   Last Updated March 11, 2018 17:10 PM

I have a component made with Component Creator. I am trying to form an array in the view, pass that array through the controller to the model, and save it to the database via a function in the model. Somewhere along the line I am losing the array, and I am hoping somebody can show me where I am going wrong.

entry() is an array of rows to be fed to the database line by line. Each row contains two comma-separated strings.

Here is my frontend view code, storing rows in entry() based on user-selected checkboxes:

$entry = array();

<form id="form-order"
      action="<?php echo JRoute::_('index.php?option=com_merakiac&task=order.save'); ?>"
      method="post" class="form-validate form-horizontal" enctype="multipart/form-data">

    <?php foreach ($session_items as $i => $item) : ?>
<div class="topb">
   <div class="sessind" id="sess_<?php echo $i; ?>"></div>
   <div class="fll"><?php echo $item->time; ?></div>
   <div class="fll"><?php echo $item->title; ?></div>
   <div class="dropbtn" data-id="<?php echo $i; ?>" id="dbtn_<?php echo $i; ?>"><span id="span_<?php echo $i; ?>">open</span></div>
</div>
<div class="moredta" id="data_<?php echo $i; ?>">
   <div class="leftc">
      <p><b>teacher:</b> <?php echo $item->teacher; ?></p></div>
   <div class="rightc">
      <p><b>level:</b> <?php echo $item->lvl; ?></p></div>
   <div class="notes">
      <p><b>notes:</b> <?php echo $item->notes; ?></p></div>

    <table class="table table-striped" id="studentList">
        <tbody>
        <?php foreach ($student_items as $student_item) : ?>
            <tr class="row<?php echo $i % 2; ?>">
<td>
    <input type="checkbox" name="jform[entry][]" value="<?php echo $student_item->name; ?>,<?php echo $item->sid; ?>"> <?php echo $student_item->name; ?>
</td>
            </tr>

        <?php endforeach; ?>
        </tbody>
    </table>

</div>
<?php endforeach; ?>

<div class="control-group">
    <div class="controls">
        <?php if ($this->canSave): ?>
            <button type="submit" class="validate btn btn-primary">
                <?php echo JText::_('JSUBMIT'); ?>
            </button>
        <?php endif; ?>
        <a class="btn"
           href="<?php echo JRoute::_('index.php?option=com_merakiac&task=orderform.cancel'); ?>"
           title="<?php echo JText::_('JCANCEL'); ?>">
            <?php echo JText::_('JCANCEL'); ?>
        </a>
    </div>
</div>

Here is my controller save() function.

public function save($key = NULL, $urlVar = NULL)
    {
        // Check for request forgeries.
        JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

        // Initialise variables.
        $app   = JFactory::getApplication();
        $model = $this->getModel('OrderForm', 'MerakiacModel');

        // Get the user data.
        $data = JFactory::getApplication()->input->get('jform', array(), 'array');

        // Validate the posted data.
        $form = $model->getForm();

        if (!$form)
        {
            throw new Exception($model->getError(), 500);
        }

        // Validate the posted data.
        $data = $model->validate($form, $data);

        // Check for errors.
        if ($data === false)
        {
            // Get the validation messages.
            $errors = $model->getErrors();

            // Push up to three validation messages out to the user.
            for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
            {
                if ($errors[$i] instanceof Exception)
                {
                    $app->enqueueMessage($errors[$i]->getMessage(), 'warning');
                }
                else
                {
                    $app->enqueueMessage($errors[$i], 'warning');
                }
            }

            $input = $app->input;
            $jform = $input->get('jform', array(), 'ARRAY');

            // Save the data in the session.
            $app->setUserState('com_merakiac.edit.order.data', $jform);

            // Redirect back to the edit screen.
            $id = (int) $app->getUserState('com_merakiac.edit.order.id');
            $this->setRedirect(JRoute::_('index.php?option=com_merakiac&view=orderform&layout=edit&id=' . $id, false));

            $this->redirect();
        }

        // Attempt to save the data.
        $return = $model->save($data[0]);

        // Check for errors.
        if ($return === false)
        {
            // Save the data in the session.
            $app->setUserState('com_merakiac.edit.order.data', $data);

            // Redirect back to the edit screen.
            $id = (int) $app->getUserState('com_merakiac.edit.order.id');
            $this->setMessage(JText::sprintf('Save failed', $model->getError()), 'warning');
            $this->setRedirect(JRoute::_('index.php?option=com_merakiac&view=orderform&layout=edit&id=' . $id, false));
        }

        // Check in the profile.
        if ($return)
        {
            $model->checkin($return);
        }

        // Clear the profile id from the session.
        $app->setUserState('com_merakiac.edit.order.id', null);

        // Redirect to the list screen.
        $this->setMessage(JText::_('COM_MERAKIAC_ITEM_SAVED_SUCCESSFULLY'));
        $menu = JFactory::getApplication()->getMenu();
        $item = $menu->getActive();
        $url  = (empty($item->link) ? 'index.php?option=com_merakiac&view=orders' : $item->link);
        $this->setRedirect(JRoute::_($url, false));

        // Flush the data from the session.
        $app->setUserState('com_merakiac.edit.order.data', null);
    }

My understanding is that the array entry() is now stored as the first entry in the array data(). However, when I try to pass $data[0] only to the model save() function, I get

error 1136 Column count doesn't match value count at row 1

Here is my model code and save() function:

public function save($data)
{

    $id    = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('order.id');
    $state = (!empty($data['state'])) ? 1 : 0;
    $user  = JFactory::getUser();

    if ($id)
    {
        // Check the user can edit this item
        $authorised = $user->authorise('core.edit', 'com_merakiac.order.' . $id) || $authorised = $user->authorise('core.edit.own', 'com_merakiac.order.' . $id);
    }
    else
    {
        // Check the user can create new items in this section
        $authorised = $user->authorise('core.create', 'com_merakiac');
    }

    if ($authorised !== true)
    {
        throw new Exception(JText::_('JERROR_ALERTNOAUTHOR'), 403);
    }

    $db = JFactory::getDbo();
    $query = $db->getQuery(true);

    $columns = array('name','sid');

    $testme = array();
    $testme[] = '1, "one"';
    $testme[] = '2, "two"';
    $testme[] = '3, "three"';
    $testme[] = '999, "nineninetynine"';

    $query->insert($db->quoteName('#__merakiac_orders'));
    $query->columns($columns);
    $query->values($data);
    $db->setQuery($query);
    $db->query();
}

I have also tried to pass the whole $data array to the model's save() function and then save only $data[0] in the SQL query ($query->values($data[0]);), but this still results in

error 1136 Column count doesn't match value count at row 1

For reference, $query->values($testme); saves to the database just fine.

What am I doing wrong? I need to feed entry() and its rows of comma-seperated values directly into the database, but can't seem to access the array from my controller. I appreciate any pointers. Thank you!



Related Questions


Showon does not work in frontend

Updated March 28, 2016 08:04 AM

How do I save Repeatable data in my component model?

Updated October 25, 2016 09:04 AM

Radio form field - can value be a string?

Updated May 16, 2017 15:10 PM

Problems with Custom form field select list

Updated April 11, 2018 16:10 PM

Tags filter field - how to add custom "placeholder"?

Updated February 01, 2018 09:10 AM