2

I'm trying to save a checkbox group as a serialized string in my main model's database table. AudienceGroups is simply a property of my main eloquent model. If I simply do

{{Form::checkbox('AudienceGroups[]', 'preschool');}}
{{Form::checkbox('AudienceGroups[]', 'elementary');}}

with no logic in my model, then the database column is set as the string Array. If I drop the brackets and just use {{Form::checkbox('AudienceGroups', 'preschool');}} then the column is set to the value of the last checkbox, in my case "seniors".

If I serialize the array before saving the instance of my model, it saves as a serialized array like it's supposed to, but I'm having trouble getting it to repopulate the proper checkboxes on page load (from old input or from the the saved model).

How should I attack this? Serialize the array myself and then use my own logic to control the third parameter to Form::checkbox() which controls the checked status? If so, can someone help me with that bit. I attempted it with Input::old and in_array but could never get it to work.

Thanks

2 Answers 2

2

First, it's not a best solution to put properties serialized in one column. You should not do that because if you want to search something in future in DB for this data you won't be able to do that.

Solution for your problem is not complicated I think.

I've prepared 2 simple routes:

Route::get('/checkbox',function() {

    // normally you would get it from model and unserialize it
    $fromModel = ['preschool','elementary','something'];

    return View::make('form')->with('fromModel',$fromModel);

});

Route::post('/checkbox-post',function() {

    $agroups = Input::get('AudienceGroups');

    foreach ($agroups as $item) {
        echo $item."<br />";

    }
    $toModel = serialize($agroups);

    echo $toModel;

    // now you insert it into model

});

and form:

{{ Form::open(['url' => 'checkbox-post', 'role' => 'form']) }}
Preschool:
{{Form::checkbox('AudienceGroups[]', 'preschool', (in_array('preschool', $fromModel) ? true : false))}}<br />

Elementary:
{{Form::checkbox('AudienceGroups[]', 'elementary', (in_array('elementary', $fromModel) ? true : false))}}<br />

Something else:
{{Form::checkbox('AudienceGroups[]', 'somethingelse', (in_array('somethingelse', $fromModel) ? true : false))}}<br />

Something:
{{Form::checkbox('AudienceGroups[]', 'something', (in_array('something', $fromModel) ? true : false))}}<br />

{{Form::submit('Send')}}

{{ Form::close() }}

You can run it using http://localhost/yourproject/checkbox - form is initalized with 3 checkbox checked. In blade you can use in_array to check correct checkboxes and in POST route you can simple use this Input::get('AudienceGroups') as array and serialize it.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the detailed reply. However, since your example didn't use form-model binding it wasn't affected by the issue I was facing. It do however motivate me to continue exploring the underlying problem rather then just abandon the form macros for checkbox groups.
Also, the serialized column is due to an existing system. Not my design.
2

Update

Looks like the html helper was removed from the core repo without this ever being fixed. https://github.com/laravel/framework/issues/5078


The problem I was running into was that the third parameter of Form::checkbox() doesn't function as expected when form-model binding is used.

The laravel documentation states that the value priority is:

  1. Session Flash Data (Old Input)
  2. Explicitly Passed Value
  3. Model Attribute Data

However, if you look at getCheckboxCheckedStatus() in /Illuminate/Html/FormBuilder.php, you'll see that the priority for checked status is actually:

  1. Old Input
  2. Model Data
  3. Explicitly Passed Value

    protected function getCheckboxCheckedState($name, $value, $checked)
    {
        if (isset($this->session) && !$this->oldInputIsEmpty()
            && is_null($this->old($name))
        ) {
            return false;
        }
        if ($this->missingOldAndModel($name)) {
            return $checked;
        }
        $posted = $this->getValueAttribute($name);
        return is_array($posted) ? in_array($value, $posted) : (bool)$posted;
    }
    


While I was in the code I also saw that Laravel has in_array built in provided that the parameter is an array. So I unserialized $myModelInstance->AudienceGroups right before calling View::make() in my controller.

3 Comments

If anyone is interested in this laravel behavior, I've contributed to this bug: github.com/laravel/framework/issues/5078
The docs are misleading and should be adjusted. However, why would you consider this as bug?
I'm new to Laravel, but to me it would make sense to have it function as the docs describe, with the third parameter able to override model data, rather then act like a fallback.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.