Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

Import CSV with $belongs_many_many records


Go to End


6 Posts   2628 Views

Avatar
kindleman.com.au

Community Member, 70 Posts

5 February 2014 at 7:26pm

Hi

I want to be able to import a csv of locations that belong_many_many services. Both locations and services are dataobjects

In the locations model admin, there is a csv import function, which seems to understand exactly what i want to do and is helpfully suggesting the csv format i should use. The trouble is - I don't understand what it is telling me:

Database columns

Lat
Lat
Lng
Lng
Address
Address
Suburb
Suburb
State
State
Postcode
Postcode
Country
Country
Relations

Services
Service

what should the format of my csv be to get a location with a couple of services imported?

Thanks for any guidance

Will

Avatar
martimiz

Forum Moderator, 1391 Posts

6 February 2014 at 5:01am

At this point I don't think you can csv-import many_many relations out of the box... Maybe someone can prove me wrong, but else you could do something like this:

- in your csv-file create a column called 'Service', containing a comma-separated list of service titles

- extend the CsvBulkLoader to LocationCsvBulkLoader

- tell your ModelAdmin to use the new extension:

	private static $model_importers = array(
	    'Location' => 'LocationCsvBulkLoader'
	);

- in your LocationCsvBulkLoader create a function that will add the comma-separated list to each new Location object

	public function linkServicesByTitle(&$obj, $val, $record) {
		$obj->ServiceList = $val;
	}

Again, in your LocationCsvBulkLoader map the csv-file 'Service' column to your function:

	public $columnMap = array(
		...
		'Service' => '->linkServicesByTitle'
	);

Now in your Locations' onAfterWrite() function, you can use $this->ServiceList to collect the Services with the requested title(s), and add them to your many_many relation, using:

if ($this->ServiceList) {
	...
	$this->Services()->add($aPageYouFound);
}

Of course this goes for existing services. You could probably build on this by creating/writing Services on the fly, but that would be more complex.

Avatar
kindleman.com.au

Community Member, 70 Posts

6 February 2014 at 1:52pm

Ok, cool thanks for that. I had a slight feeling it wouldn't do it automatically and then the spec came up.

I should be able to get it working with those instructions. Thanks very much for your help : )

Avatar
justin_t_brown

Community Member, 22 Posts

1 June 2017 at 5:41am

It's been a while since this reply @martimiz, but this use-case just came up for and I was hoping a point of clarification. You posted:

if ($this->ServiceList) {
	...
	$this->Services()->add($aPageYouFound);
}

I'm wondering what $aPageYouFound refers to?

Avatar
martimiz

Forum Moderator, 1391 Posts

1 June 2017 at 9:49am

Pfff, that's allong time ago. I haven't actually done anything with the bulkloader for some time, so maybe this is totally overruled? Or doesn't even work anymore? But, if so, I think I may have meant something like this:

ServiceList contains a comma separated list of page Titles, that you would then turn into an array $titles, and then do a $allPages = Page::get()->filter(array('Title' => $titles)) and then loop $allPages and add each 'page you found' as a Service, using that phrase...

Avatar
justin_t_brown

Community Member, 22 Posts

1 June 2017 at 9:57am

Edited: 01/06/2017 9:57am

Wow, thank you! I thought it was a long shot asking that question so really appreciate your time!