creatoro / jelly

A flexible ORM for Kohana 3.1+
http://jelly.jonathan-geiger.com
MIT License
72 stars 13 forks source link

Get value for relationship without loading the relation #99

Open marcalj opened 13 years ago

marcalj commented 13 years ago

Hi, when finetunning one application I saw that Jelly_Model->as_array(), on relationships load all items in the database. I was using it as a way to get "raw" data of a model.

So I implement a workaround:

    /**
     * This function is useful to retrieve just the primary key of "BelongsTo" or "HasOne" fields without loading it.
     */
    protected function get_raw($field)
    {
        // Alias the name to its actual name
        $name = $field->name;

        if (array_key_exists($name, $this->_changed))
        {
            $value = $this->_changed[$name];
        }
        else
        {
            $value = $this->_original[$name];
        }

        return $value;
    }

    /**
     * @note ACL checks are calculated in the API controller.
     * @note We cannot load all values with as_array() function because will invoke a select() on all relationships. Don't want it here (it's not the intended behaviour).
     */
    public function get_api_data()
    {
        $db_data = array();

        foreach ($this->meta()->fields() as $name => $field)
        {
            if ($field instanceof Jelly_Field_HasMany OR $field instanceof Jelly_Field_ManyToMany)
            {
                // Do nothing
            }
            elseif ($field instanceof Jelly_Field_HasOne OR $field instanceof Jelly_Field_BelongsTo)
            {
                $db_data[$name] = $this->get_raw($field);
            }
            else
            {
                $db_data[$name] = $this->get($name);
            }
        }

        return array(
            'id' => $this->id,
            'db' => Arr::extract($db_data, $this->meta()->fields_acl('read')),
//          'update_fields' => $this->meta()->fields_acl('update'),
            'frontend_data' => $this->frontend_data(),
        );
    }

So basically for Jelly_Field_HasMany and Jelly_Field_ManyToMany do not call "get" method, and for Jelly_Field_HasOne and Jelly_Field_BelongsTo I'm using the "get_raw" custom function.

Happy tunning :)

nex2hex commented 12 years ago

Your method don't returned unmapped to db fields, get() do this.

Fixed version:

public function get_raw($name)
{
    if ($field = $this->_meta->field($name))
    {
        // Alias the name to its actual name
        $name = $field->name;

        if (array_key_exists($name, $this->_changed))
        {
            return $this->_changed[$name];
        }
        else
        {
            return $this->_original[$name];
        }
    }
    // Return unmapped data from custom queries
    elseif (isset($this->_unmapped[$name]))
    {
        return $this->_unmapped[$name];
    }
}
marcalj commented 12 years ago

What do you mean with "unmapped".

Sorry but I don't use any ORM in my projects, just Model_Database amb DB class. I need more low level tunning.

nex2hex commented 12 years ago

unmapped fields on't have column in table in db

marcalj commented 12 years ago

Ups, ok got it! ;)