fuel / orm

Fuel PHP Framework - Fuel v1.x ORM
http://fuelphp.com/docs/packages/orm/intro.html
151 stars 95 forks source link

from_array() doesn't deal with related objects very well #418

Closed WanWizard closed 4 years ago

WanWizard commented 6 years ago

see https://github.com/fuel/orm/commit/2abf7ca57dbe42a570cc3587255d595fefca1bb4

ysshir commented 6 years ago

Thank you for creating this issue.

To do this properly requires a recusive function, nested loops are very ugly and not scalable.

yeah, I totally agree with you. so I wrote the function that works recursively in comments. I added comment to the code.

I'm sure you write better code than I do. so please resulve this issue. thanks.

    public function from_array(array $values)
    {
        foreach($values as $property => $value)
        {
            if (in_array($property, static::primary_key()))
            {
                continue;
            }

            if (array_key_exists($property, static::properties()))
            {
                $this->_data[$property] = $value;
            }
            elseif (array_key_exists($property, static::relations()) and is_array($value))
            {
                $rel = static::relations($property);
                if ($rel->singular)
                {
                    if ( ! isset($this->_data_relations[$property]))
                    {
                        $this->_data_relations[$property] = call_user_func(static::relations($property)->model_to.'::forge', $value);
                    }
                    else
                    {
                        // use from_array() recursively
                        $this->_data_relations[$property]->from_array($value);
                    }
                }
                else
                {
                    if ( ! isset($this->_data_relations[$property]))
                    {
                        $this->_data_relations[$property] = array();
                    }

                    foreach($value as $id => $data)
                    {
                        if (is_array($data))
                        {
                            if (array_key_exists($id, $this->_data_relations[$property]))
                            {
                                // use from_array() recursively
                                $this->_data_relations[$property][$id]->from_array($data);
                            }
                            else
                            {
                                $this->_data_relations[$property][] = call_user_func(static::relations($property)->model_to.'::forge', $data);
                            }
                        }
                    }
                }
            }
            elseif (property_exists($this, '_eav') and ! empty(static::$_eav))
            {
                $this->_set_eav($property, $value);
            }
            else
            {
                $this->_custom_data[$property] = $value;
            }
        }

        return $this;
    }
WanWizard commented 4 years ago

This issue should be adressed, as forge() now calls from_array() to populate a new object, including related objects.