ZF-5819: Zend_Db_Table_Row_Abstract::setFromArray removes data key/value pair if key is not a DB column

Description

Data provided to row by 'setFromArray' method are deleted if the key is not a DB column (key is not present in self::_data array) without call '_transformColumn'.

\


public function setFromArray(array $data)
{
    $data = array_intersect_key($data, $this->_data);

    foreach ($data as $columnName => $value) {
        $this->__set($columnName, $value);
    }

    return $this;
}

public function setFromArray(array $data)
{
    foreach ($data as $columnName => $value) {
        $this->__set($columnName, $value);
    }

    return $this;
}

The magic method '__set' (invoked in setFromArray for each key/value pair):

  • call the self::_transformColumn method (used for inflection, for example);
  • check the existence of 'column' in self::_data array (raising an exception if not found).

public function __set($columnName, $value)
{
    $columnName = $this->_transformColumn($columnName);
    if (!array_key_exists($columnName, $this->_data)) {
        require_once 'Zend/Db/Table/Row/Exception.php';
        throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is not in the row");
    }
    $this->_data[$columnName] = $value;
    $this->_modifiedFields[$columnName] = true;
}

So ``` may be safely removed.

Comments

When using Oracle the database column names are usually in uppercase, while the names of the input fields are in lower. For that we use the _transformColumn function. When using the setFromArray, when posting data from a form, the array_intersect_key function will return an empty array, and no data will be set.

So, I vote for this issue to be resolved.

If the array_intersect_key function must be, I suggest that the _transformColumn function is used before, so the array keys have been transformed before removal.

Hope this will be fixed. For now I have overwritten the setFromArray function and removed the following line

```

ps. I am using 1.7.8

I wholeheartedly concur. In my applications I prefer to hide the column names from the user in forms and rely on _transformColumn for column name mapping. So in some cases where setFromArray is used I have to override that function in my concrete row class rather than modifying core.

I dont see an issue with removing the array_intersect_key function, as the current implementation of __set() will catch column names that do not exist in the row.

I agree.

For example:

The db table has tow columns: test_1, test_2 .

my _transformColumn function is:

'test_one' => 'test_1', 'test_two' => 'test_2',

when I invoke setFromArray(array('test_one' => 'abc', 'test_two' => 'abc)), and no data will be set.