Using boolean fields with Magento ORM
Asked Answered
A

2

3

I am working on a backend edit page for my custom entity. I have almost everything working, including saving a bunch of different text fields. I have a problem, though, when trying to set the value of a boolean field.

I have tried:

$landingPage->setEnabled(1);
$landingPage->setEnabled(TRUE);
$landingPage->setEnabled(0);
$landingPage->setEnabled(FALSE);

None seem to persist a change to my database.

How are you supposed to set a boolean field using magento ORM?

edit Looking at my database, mysql is storing the field as a tinyint(1), so magento may be seeing this as an int not a bool. Still can't get it to set though.

Albumin answered 30/8, 2012 at 20:47 Comment(13)
setEnabled() looks like a function that might not just be a regular setter, are you sure it is? Also, if this is a newly created field, be sure to delete the entire var/cache/ directoryHightest
Enabled is my field name. It might be a reserved word issue though, ill test that. All caching is off.Albumin
Just side note from my side. If the fields are newly created and you did't cleared your cache you may also have some issues with saving them, because in the cache Magento / Zend Framework keeps some information about the DB ... like table columns and etc. Magento also keeps some caches, even if the cache is disabled!Bluhm
Tried it with a different field name, no luck.Albumin
@Bluhm - which caches are kept when cache is disabled? To the OP: what is your column type, exactly? Representing (bool) true as (int) 1 is something PHP and MySQL have been doing for quite some time.Ammieammine
@Ammieammine According to mysql, the col type is actually tinyint(1).Albumin
Deleted the cache folders and it seems to be working. Very odd, considering I didnt need to delete it for any other thing before (including adding the new model)Albumin
@Ammieammine honestly, I can't answer at the moment. I just referred on something, that I've read in the past: https://mcmap.net/q/972628/-magento-custom-model-won-39-t-allow-db-table-changes when I had problem with my new columns, because they weren't sorted. Do you think, that my comment is distracting and it's not right for this topic? Let me know and I will take it of ;)Bluhm
@Bluhm no, it was on topic.... and correct. Weird though.Albumin
@Ammieammine db schema is cached, I think the only way to clear it is to delete var/cache/ - even clearing cache via admin I don't think does it.Hightest
@Albumin I guess I'll take the answer then :)Hightest
@Ammieammine Some checks before hitting the bed :) I checked some files in var/cache/mage--6 and in file mage---6f8_DB_PDO_MYSQL_DDL_customer_eav_attribute_1 in found serialized data, which keeps the information about table structure: gist.github.com/3544634 ... if we use Flush Magento Cache the schema files aren't cleared, but if we use Flush Cache Storage they gone. May be tomorrow morning I can "dive" deeper and to where and how these files are read.Bluhm
@Bluhm I've been re-confirming things as well. Found that if cache is not active the scheme should never be cached. However, because the cache key for the DDL cache is not registered with the app, the cache will not be invalidated when flushing Magento-specific cache.Ammieammine
H
5

Delete var/cache/* - your DB schema is cached by Magento even though the new column is already added to the MySQL table.

Hightest answered 30/8, 2012 at 22:43 Comment(0)
L
6

This topic has bring curiosity to me. Although it has been answered, I'd like to share what I've found though I didn't do intense tracing.

It doesn't matter whether the cache is enabled / disabled, the table schema will be cached.

It will be cached during save process.

Mage_Core_Model_Abstract -> save()

Mage_Core_Model_Resource_Db_Abstract -> save(Mage_Core_Model_Abstract $object)


Mage_Core_Model_Resource_Db_Abstract

public function save(Mage_Core_Model_Abstract $object)
{
    ...
    //any conditional will eventually call for:
    $this->_prepareDataForSave($object);
    ...
}

protected function _prepareDataForSave(Mage_Core_Model_Abstract $object)
{
    return $this->_prepareDataForTable($object, $this->getMainTable());
}

Mage_Core_Model_Resource_Abstract

protected function _prepareDataForTable(Varien_Object $object, $table)
{
    $data = array();
    $fields = $this->_getWriteAdapter()->describeTable($table);
    foreach (array_keys($fields) as $field) {
        if ($object->hasData($field)) {
            $fieldValue = $object->getData($field);
            if ($fieldValue instanceof Zend_Db_Expr) {
                $data[$field] = $fieldValue;
            } else {
                if (null !== $fieldValue) {
                    $fieldValue   = $this->_prepareTableValueForSave($fieldValue, $fields[$field]['DATA_TYPE']);
                    $data[$field] = $this->_getWriteAdapter()->prepareColumnValue($fields[$field], $fieldValue);
                } else if (!empty($fields[$field]['NULLABLE'])) {
                    $data[$field] = null;
                }
            }
        }
    }
    return $data;
}

See the line: $fields = $this->_getWriteAdapter()->describeTable($table);

Varien_Db_Adapter_Pdo_Mysql

public function describeTable($tableName, $schemaName = null)
{
    $cacheKey = $this->_getTableName($tableName, $schemaName);
    $ddl = $this->loadDdlCache($cacheKey, self::DDL_DESCRIBE);
    if ($ddl === false) {
        $ddl = parent::describeTable($tableName, $schemaName);
        /**
         * Remove bug in some MySQL versions, when int-column without default value is described as:
         * having default empty string value
         */
        $affected = array('tinyint', 'smallint', 'mediumint', 'int', 'bigint');
        foreach ($ddl as $key => $columnData) {
            if (($columnData['DEFAULT'] === '') && (array_search($columnData['DATA_TYPE'], $affected) !== FALSE)) {
                $ddl[$key]['DEFAULT'] = null;
            }
        }
        $this->saveDdlCache($cacheKey, self::DDL_DESCRIBE, $ddl);
    }

    return $ddl;
}

As we can see:

$ddl = $this->loadDdlCache($cacheKey, self::DDL_DESCRIBE);

will try to load the schema from cache.

If the value is not exists: if ($ddl === false)

it will create one: $this->saveDdlCache($cacheKey, self::DDL_DESCRIBE, $ddl);

So the problem that occurred in this question will be happened if we ever save the model that is going to be altered (add column, etc).

Because it has ever been $model->save(), the schema will be cached. Later after he add new column and "do saving", it will load the schema from cache (which is not containing the new column) and resulting as: the data for new column is failed to be saved in database

Lixiviate answered 31/8, 2012 at 17:44 Comment(0)
H
5

Delete var/cache/* - your DB schema is cached by Magento even though the new column is already added to the MySQL table.

Hightest answered 30/8, 2012 at 22:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.