I have been working on importing external data into SilverStripe(SS) models. This post is for advanced users of SilverStripe CMS.
Assume we have SS models, Food and FoodCategory to which we want to import data into.
Food.php
class Food extends DataObject { public static $db = array( 'ImportID' => 'Int', //reference primary key from old table 'Name' => 'Varchar', 'Slug' => 'Varchar', ); public static $has_one = array( 'FoodCategory' => 'FoodCategory' ); public static $summary_fields = array( 'Name', 'Slug' ); }
FoodCategory.php
class FoodCategory extends DataObject { public static $db = array( 'Type' => 'Varchar', ); public static $has_one = array( 'Food' => 'Food' ); public static $summary_fields = array( 'Type' ); }
I am importing the data via ModelAdmin and the below class FoodImporter.php is being used. It extends the CsvBulkLoader framework class.
food_id, fk_foodcategory, name
and slug
are table fields in old tbl_food table which are mapped to the corresponding new SilverStripe Food table.
The importer checks for unique food titles and id’s to avoid duplicates.
FoodImporter.php
class FoodImporter extends CsvBulkLoader { public $columnMap = array( 'food_id' => 'ImportID', 'fk_foodcategory' => 'FoodCategoryID', 'name' => 'Name', 'slug' => 'Slug', ); public $duplicateChecks = array( 'ID' => array( 'callback' => 'findDuplicateByImportID' ), 'Name' => array( 'callback' => 'findDuplicateByFoodName' ) ); public function __construct($objectClass = 'Food') { parent::__construct($objectClass); } /** * Find an existing object based on unique id * columns specified via {@link self::$duplicateChecks} * * @param int $ImportId CSV id column * @param array $record CSV data column * @return first array record */ protected function findDuplicateByImportID($ImportId, $record) { if(!$ImportId) return; if(!singleton('Food')->hasDatabaseField($this->columnMap['food_id'])) return; return Food::get()->filter($this->columnMap['food_id'], $ImportId)->First(); } /** * Find existing objects based on food title/name * columns specified via {@link self::$duplicateChecks} * * @param string $name CSV food name column * @param array $record CSV data column * @return first array record */ protected function findDuplicateByFoodName($name, $record) { if(!$name) return; if(!singleton('Food')->hasDatabaseField($this->columnMap['name'])) return; return Food::get()->filter($this->columnMap['name'], $name)->First(); } }