Magento Data Scripts

Magento data scripts that are located within the modules’ data directory were introduced in Magento Community/Open Source version 1.6.

The naming convention for the data script files have a similar naming convention to setup scripts that are found within the modules’ sql directory.

The data file names themselves are proceeded with a data- prefix.

An example of data scripts can be found within the Magento’s Mage_Cms module.


$content = '
<div class="links">
    <div class="block-title">
        <strong><span>Company</span></strong>
    </div>
    <ul>
        <li><a href="{{store url=""}}about-magento-demo-store/">About Us</a></li>
        <li><a href="{{store url=""}}contacts/">Contact Us</a></li>
        <li><a href="{{store url=""}}customer-service/">Customer Service</a></li>
        <li><a href="{{store url=""}}privacy-policy-cookie-restriction-mode/">Privacy Policy</a></li>
    </ul>
</div>';

$cmsBlock = array(
    'title'         => 'Footer Links Company',
    'identifier'    => 'footer_links_company',
    'content'       => $content,
    'is_active'     => 1,
    'stores'        => 0
);

Mage::getModel('cms/block')->setData($cmsBlock)->save();

Here Magento is simply saving data into tables already created through setup scripts in the sql directory. If you aren’t familiar with how install setup and upgrade scripts work in Magento, be sure to check out this article.

During the initialisation process of Magento, there is an applyAllDataUpdates() method found in the run() method within the Mage_Core_Model_App class.


public function run($params)
{
    $options = isset($params['options']) ? $params['options'] : array();
    $this->baseInit($options);
    Mage::register('application_params', $params);

    if ($this->_cache->processRequest()) {
        $this->getResponse()->sendResponse();
    } else {
        $this->_initModules();
        $this->loadAreaPart(Mage_Core_Model_App_Area::AREA_GLOBAL, Mage_Core_Model_App_Area::PART_EVENTS);

        if ($this->_config->isLocalConfigLoaded()) {
            $scopeCode = isset($params['scope_code']) ? $params['scope_code'] : '';
            $scopeType = isset($params['scope_type']) ? $params['scope_type'] : 'store';
            $this->_initCurrentStore($scopeCode, $scopeType);
            $this->_initRequest();
            Mage_Core_Model_Resource_Setup::applyAllDataUpdates();
        }
        $this->getFrontController()->dispatch();
    }
    return $this;
}

The applyAllDataUpdates() method then proceeds to find out the setup class being used within the <setup> nodes in the Magento configuration.

This class is then instantiated and the applyDataUpdates() method is run.


static public function applyAllDataUpdates()
{
    if (!self::$_schemaUpdatesChecked) {
        return;
    }
    $resources = Mage::getConfig()->getNode('global/resources')->children();
    foreach ($resources as $resName => $resource) {
        if (!$resource->setup) {
            continue;
        }
        $className = __CLASS__;
        if (isset($resource->setup->class)) {
            $className = $resource->setup->getClassName();
        }
        $setupClass = new $className($resName);
        $setupClass->applyDataUpdates();
    }
}

Within the applyDataUpdates() method, we check the versions of the resource name in the core_resource database table, and the version that is set in module’s configuration


public function applyDataUpdates()
{
    $dataVer= $this->_getResource()->getDataVersion($this->_resourceName);
    $configVer = (string)$this->_moduleConfig->version;
    if ($dataVer !== false) {
         $status = version_compare($configVer, $dataVer);
         if ($status == self::VERSION_COMPARE_GREATER) {
             $this->_upgradeData($dataVer, $configVer);
         }
    } elseif ($configVer) {
        $this->_installData($configVer);
    }
    return $this;
}

If a record is found for the resource name in the database table, we then compare this version and the module’s version together. If the module’s version is higher, we call the _upgradeData() method. If not, then we don’t perform any upgrade whatsoever.

If a record for the resource name is not found in the database table, we run the _installData() method.


protected function _installData($newVersion)
{
    $oldVersion = $this->_modifyResourceDb(self::TYPE_DATA_INSTALL, '', $newVersion);
    $this->_modifyResourceDb(self::TYPE_DATA_UPGRADE, $oldVersion, $newVersion);
    $this->_getResource()->setDataVersion($this->_resourceName, $newVersion);

    return $this;
}

Both the _installData() and _upgradeData() methods call the _modifyResourceDb() method.


protected function _modifyResourceDb($actionType, $fromVersion, $toVersion)
{
    switch ($actionType) {
        case self::TYPE_DB_INSTALL:
        case self::TYPE_DB_UPGRADE:
            $files = $this->_getAvailableDbFiles($actionType, $fromVersion, $toVersion);
            break;
        case self::TYPE_DATA_INSTALL:
        case self::TYPE_DATA_UPGRADE:
            $files = $this->_getAvailableDataFiles($actionType, $fromVersion, $toVersion);
            break;
        default:
            $files = array();
            break;
    }
    if (empty($files) || !$this->getConnection()) {
        return false;
    }

    $version = false;

    foreach ($files as $file) {
        $fileName = $file['fileName'];
        $fileType = pathinfo($fileName, PATHINFO_EXTENSION);
        $this->getConnection()->disallowDdlCache();
        try {
            switch ($fileType) {
                case 'php':
                    $conn   = $this->getConnection();
                    $result = include $fileName;
                    break;
                case 'sql':
                    $sql = file_get_contents($fileName);
                    if (!empty($sql)) {

                        $result = $this->run($sql);
                    } else {
                        $result = true;
                    }
                    break;
                default:
                    $result = false;
                    break;
            }

            if ($result) {
                $this->_setResourceVersion($actionType, $file['toVersion']);
            }
        } catch (Exception $e) {
            throw Mage::exception('Mage_Core', Mage::helper('core')->__('Error in file: "%s" - %s', $fileName, $e->getMessage()));
        }
        $version = $file['toVersion'];
        $this->getConnection()->allowDdlCache();
    }
    self::$_hadUpdates = true;
    return $version;
}

The method firstly checks the $actionType variable, and stores either the database or data files into a $files array.

The foreach around these files is then made, and depending on the files extensions, which can be either .php or .sql, Magento will either include the files, or call the run() method for any .sql database/data files.

So an example of a data script could look like the following.


<?php
 
$people = array(
    array(
        'name' => 'John',
        'description' => 'Some description about John',
    ),
    array(
        'name' => 'Alice',
        'description' => 'Some description about Alice',
    ),
);
 
foreach ($people as $person) {
    Mage::getModel('somemodule/people')
        ->setData($person)
        ->save();
}

And an upgrade script might look like the following.


<?php
 
$people = Mage::getModel('somemodule/people')->getCollection();
 
foreach ($people as $person) {
    $person->setDescription("They are human.")
           ->save();
}

Both these data scripts assume that you have created your own custom model, resource model and collection. You will then be able to simply call the save() method in order for your data to be saved into the database.

Note: This article is based on Magento Community/Open Source version 1.9.