Skip to content

Conversation

@Seb-C
Copy link
Contributor

@Seb-C Seb-C commented Apr 26, 2016

I'm not sure wether or not this may be a breaking change (in that case it's for a future version), but this part of the code is wrong and can never succeed. It causes crashes in some cases for example when trying to save a sub-field from a has-one relation in a crud.

The line $obj->{$val_name} can't succeed because it's inside an if (empty($obj)).

@shaoshiva
Copy link
Collaborator

Wow, this method is ugly and hard to understand ! However it seems that neither the old code nor your code are correct.

In the old code the related object was never created but in the new code it is always created.

Just to illustrate the mess in this method :

$item->setOrCreateRelation('related->property->subrelated->subproperty', $value)
... will set $value for related->property and for related->subrelated->subproperty.

$item->setOrCreateRelation('related->property1->property2->property3', $value)
... will set $value for related->property1, related->property2 and related->property3...

😓

@shaoshiva
Copy link
Collaborator

This code should work :

    protected function &setOrCreateRelation($name, $value)
    {
        $arr_name = explode('->', $name);
        $obj = $this;
        foreach ($arr_name as $val_name) {
            $rel = $obj->relations($val_name);
            if (!empty($rel)) {
                // Gets the existing related item
                $related = &$obj->get($val_name);
                if (empty($related)) {
                    // No existing related item, creates a new one
                    $model_to = $rel->model_to;
                    $related = $model_to::forge();
                    if ($rel->singular) {
                        $obj->{$val_name} = $related;
                    } else {
                        $obj->{$val_name}[] = $related;
                    }
                }
                $obj = $related;
            } else if (array_key_exists($val_name, $obj::properties())) {
                $obj->set($val_name, $value);
            } else {
                throw new \Exception('Property or relation `'.$val_name.'` does not exists on model `'.get_class($obj).'`');
            }
        }
        return $obj;
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants