Magento – Using Magento’s ORM to Insert a Specific ID Field

model

Is there a way to use Magento's simple ORM (Mage_Core_Model_Abstract and Mage_Core_Model_Resource_Abstract) to insert model rows with a specific primary key?

For example, if I ran the following against an empty Magento system

Mage::getModel('core/website')->setData(array (
    'website_id' => 2,
    'code' => 'foo',
    'name' => 'Main Website',
    'sort_order' => 0,
    'default_group_id' => 1,
    'is_default' => 1,
)); 

I'd expect a new entry in the core_website table. However, Magento silently does nothing here.

Digging into the resource, it looks like I'm falling afoul of this in the database resource class

#File: app/code/core/Mage/Core/Model/Resource/Db/Abstract.php
if (!is_null($object->getId()) && (!$this->_useIsObjectNew || !$object->isObjectNew())) {
    //update stuff here
}
else
{
    //insert stuff here
}

Because the model has an id (i.e. I'm inserting a specific ID), and because _useIsObjectNew is hard coded to false, my save request is always routed to the insert path.

Is there a way to force an insert with the default Magento models? (without a rewrite/class-replacement).

Yes, raw SQL is an option, but then event functionality gets lost.

Best Answer

So, yeah. (edit:) The trick is to use a Mage_Core_Model_Abstract subclass which does not have the id field that the resource model expects:

$evil = Mage::getModel('core/store'); // that's a store object, baby!
$evil->setData(
    array (
        'website_id' => 99,
        'code' => 'foo',
        'name' => 'Main Website9',
        'sort_order' => 0,
        'default_group_id' => 1,
        'is_default' => 1,
    )
);

Mage::getResourceModel('core/website')->forsedSave($evil);

Mage::dispatchEvent('website_save_commit_after', [...]) is only event I see being consumed in core. It could be as simple as following with

Mage::getModel('core/website')->setData($evil->getData())->afterCommitCallback();

In any event, I need a shower.