laravel-form-builder icon indicating copy to clipboard operation
laravel-form-builder copied to clipboard

Why are you turning the model into an array

Open AdamKyle opened this issue 6 years ago • 7 comments

so in this code

You take a laravel model object and turn it from a model into, for example - when I do $this->getModel():

array:1 [
  "Goblin" => array:15 [
    "id" => 1
    "name" => "Goblin"
    "strength" => 8
    "dexterity" => 10
    "intelligence" => 4
    "agility" => 12
    "health" => 40
    "damage" => 6
    "armor_class" => 8
    "has_antique_damage" => null
    "antique_damage" => null
    "casts_spells" => 0
    "cast_damage" => null
    "created_at" => "2019-02-09 23:18:32"
    "updated_at" => "2019-02-09 23:18:32"
  ]
]

Because of this I can no longer do: $this->getModel()->name because its an array. WTH?

The documentation wasn't even updated to reflect this change.

is there a work around to get my model back? Like this just seems dumb to me, in versions prior to tag 1.16.x it was never like this.

AdamKyle avatar Feb 10 '19 00:02 AdamKyle

in the short term, you can wrap the array in a collection (using collect helper) and then access as you wish.

Or, you can simply call as $this->getModel()[‘name’]

mikeerickson avatar Feb 10 '19 02:02 mikeerickson

@AdamKyle It only does this if !Arr::get($model, $dotName). Not always. How did you build your form, and what's its input?

rudiedirkx avatar Mar 29 '19 10:03 rudiedirkx

I encountered issue with this approach as well. I use attribute getters in order to convert ObjectID into string representation (mongo), and as soon as model being converted to array this whole mechanism of attribute getters does not apply any more and form does not work as expected. This happens to the named forms.

Consider next form:

$this
    ->add('id', Field::TEXT)
    ->add('name', Field::TEXT)
    ->add('relatedEntity', Field::ENTITY, ['class' => RelatedEntity::class, 'multiple' => true]);

And inside model we have next get mutator:

public function getRelatedEntityAttribute(array $values): array
{
    array_walk($values, static function (&$item) { $item = (string) $item; });

    return $values;
}

An everything works great with unnamed form cuz here:

protected function getModelValueAttribute($model, $name)
{
    $transformedName = $this->transformKey($name);
    if (is_string($model)) {
        return $model;
    } elseif (is_object($model)) {
        return object_get($model, $transformedName);
    } elseif (is_array($model)) {
        return array_get($model, $transformedName);
    }
}

Our model passed as an object. But as soon as we add name to the form, model being converted to array and it's no longer possible to use standard model features.

So it would be great to preserve model as it is.

Martyrer avatar Apr 03 '19 11:04 Martyrer

I'm still curious. How did you build your form, and what's its input?

rudiedirkx avatar Apr 03 '19 21:04 rudiedirkx

I'm still curious. How did you build your form, and what's its input?

In my case the form built as shown above and created using create method

/** @var Form $form */
$form = $formBuilder->create(ModelForm::class, [
    'method' => 'POST',
    'url' => route('model.update', $model->getId()),
    'model' => $model,
    'title' => sprintf('Edit - %s [%s]', $model->getAttributeValue('name'), $model->getId())
]);

where $model is an instance of a Jenssegers\Mongodb\Eloquent\Model model

Martyrer avatar Apr 05 '19 12:04 Martyrer

And how is your form named or not named? And why? Usually only child forms are named.

Named forms expect the model to be in the name in the model. This should work fine:

$form = $formBuilder->create(AddressForm::class, [
    'model' => ['address' => $addressModel],
    'name' => 'address',
]);

The form's name is address, and its model is inside 'address'. Probably for child form and/or non-form-collection reasons. @kristijanhusak knows all.

rudiedirkx avatar Apr 05 '19 13:04 rudiedirkx

@rudiedirkx actually, you are right, in case model assigned to the form using array 'model' => ['address' => $addressModel], it works as expected

Martyrer avatar Apr 06 '19 11:04 Martyrer