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

How to populate a <select> from a DataObjectSet without the duplicates


Go to End


5 Posts   2268 Views

Avatar
lise

Community Member, 47 Posts

13 March 2010 at 10:19am

This is a very simplified/childish version of my data structure and code so I can better explain the problem.

Let's assume a a Dataobject

class Customers extends DataObject {
static $db = array(
'Name' => 'Text',
'Country' => 'Text'
);

In a template reports.ss , I would like to have a dropdown field (<select>) populated with all the "Country" existing
in the "Customers" dataObject. The trick is that I would like to ignore/delete the duplicates and ,if possible, to have
the list sorted.

My idea was to create a function (get_unique_country() )which returns a ObjectDataSet which I can use in a control block :

<% control get_unique_country %>
<option value=$Country>$country</option>
<% end_control %>

The problem is that I can't find a way to create a DataObject with no duplicate . However I found in the book (page 205-206) a
way to create an array containing unique values of countries :

I would have a function

function get_unique_country(){
$myentries = DataObject::get('Customers');
if(!$myentries) return array();
$countryList = array_unique($myentries->column('country'));
sort($countryList);
return $countryList;
}

The problem is that it returns an array not a DataObject . How can I use an array into a <% control %> block?

What is the best SS-way to achieve what I want?

Any hints would be very appreciated.
Thanks!

Lise

Avatar
Willr

Forum Moderator, 5523 Posts

13 March 2010 at 2:12pm

You can use the sort parameter on the dataobject get all and the removeDuplicates() functions which you can call on a DataObjectSet.

Sadly to use the removeDuplicates() function like removeDuplicates('Country') you have to be using branches/2.4 and a relatively recent checkout of that too. Before you could only removeDuplicates() on ID. But if your running 2.4 then its a piece of cake

function getUniqueCountries() {

$countries = DataObject::get('Country', '', 'Country ASC');
if(!$countries) return false;

$countries->removeDuplicates('Country');

return $countries;
}

However if your running 2.3 a number of ways you could get round that. Having a quick look - there is a function GroupedBy() which you can group a set by any column so perhaps try this if your on 2.3

function getUniqueCountries() {

$countries = DataObject::get('Country', '', 'Country ASC');
if(!$countries) return false;

$countryArray = $countries->groupBy('Country');

return new ArrayData($countryArray);
}

Avatar
lise

Community Member, 47 Posts

13 March 2010 at 5:02pm

Thank you very much Willr.
I didn't know about the "GroupedBy" function. This is exactly what I needed.

However I want to mention for those who read this thread that the code you sent didn't exactly work :
Instead of using 'groupBy' , I had to use 'GroupedBy' which returns an DataObjectSet so it is even easier.
You mentioned correctly "GroupedBy" in your response but used "groupBy" in your example. Actually I don't quite understand why
"groupBy" doesn't work ...

Also thank you very much for the info about 2.4. I will keep it in mind. It looks pretty cool.
Below is the code which works for me on 2.3 .

Thanks - Lise
-------------------------------------------------------------------------------------------------
function getUniqueCountries() {

$countries = DataObject::get('Country', '', 'Country ASC');
if(!$countries) return false;

$countrySet = $countries->GroupedBy('Country');

return $countrySet;
}
--------------------------------------------------------------------------------------------------------

Avatar
Sean

Forum Moderator, 922 Posts

13 March 2010 at 8:31pm

Edited: 13/03/2010 8:33pm

I believe the following code may be more efficient, as you don't have to do any post-processing of the result in PHP. It's all done in the database using "SELECT DISTINCT".

If you need more columns to be selected, just add them in the select clause. At the moment, I have only selected the bare minimum, which is the ClassName enumeration column, and the Country column.


function getUniqueCountries() {
	$result = DB::query('SELECT DISTINCT ClassName, Country FROM Country ORDER BY Country ASC');
	return singleton('Country')->buildDataObjectSet($result);
}

Sean

Avatar
lise

Community Member, 47 Posts

14 March 2010 at 1:31pm

Thank you Sean. This works also very well for me.

And for those who (like me) are not too familiar with raw sql, I suggest to look at the tutorial:
http://doc.silverstripe.org/doku.php?id=SQLquery