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.

DataObjectManager Module

Discuss the DataObjectManager module, and the related ImageGallery module.

Moderators: martimiz, UncleCheese, Sean, biapar, Willr, Ingo, swaiba, simon_w

Alphabetical list of objects stored with DOM


Go to End
Reply

17 Posts   2569 Views

Avatar
LesC

29 October 2009 at 6:54am Community Member, 70 Posts

I'm trying to create an alphabetical listing of items that have been stored as DataObjects using the DOM, so that I get something like: http://www.hans.org/directory/

I need to have it separated in two columns (A to M, and N to Z), so was thinking of having 2 functions that each return a range of entries, and then perform some function in the view to control what gets displayed.

However, as SS doesn't like PHP in the view templates, does anyone know how to do this in the controller? Would I need to store each character as it's own array with the returned array? Or is there a more straightforward way of doing it?

If I was writing this in (fugly) PHP the first function would run something like:

$qry = "SELECT title, LEFT(title, 1) AS first_char FROM resourceobjects
WHERE UPPER(LEFT(title, 1)) BETWEEN 'A' AND 'M' ORDER BY title";

$result = mysql_query($qry);
$current_char = '';
while ($row = mysql_fetch_assoc($result)) {
if ($row['first_char'] != $current_char) {
$current_char = $row['first_char'];
echo '<h2>' . strtoupper($current_char) . '</h2>';
}
echo '<p>' . $row['title'] . '</p>';
}

Any help much appreciated :)

Avatar
UncleCheese

29 October 2009 at 7:26am 4085 Posts

Yikes. Don't work so hard.

private function getColumn($dir)
{
return $this->MyObjects("SomeField $dir 'n'", "SomeField ASC");
}

public function LeftColumn()
{
return $this->getColumn("<");
}

public function RightColumn()
{
return $this->getColumn(">");
}

Avatar
LesC

29 October 2009 at 7:33am (Last edited: 29 October 2009 7:54am), Community Member, 70 Posts

Haha, yeah I have a tendency to over engineer :) Thanks for the uber quick response as always!

How would I then cycle through the generated arrays displaying the first character as a heading, then that characters entries in a list?

I'm getting confused over what has to be done in the controlller, and what's possible in the view!

EDIT: What does the MyObjects method do? I'm getting an error when I run this code - should I replace that line with a call to the DB?

Avatar
LesC

29 October 2009 at 8:03am Community Member, 70 Posts

Actually ignore the bit about the MyObjects - it's been a long day :)

I borrowed code from this post: http://silverstripe.org/archive/show/7069#post7069

And came up with:

private function MyObjects($thisfilter, $orderby) {
$objects = DataObject::get("DirectoryCategory", $thisfilter, $orderby, "", "");
if($objects) {
$output = '<ul>';
foreach($objects as $object) {
$output .= "<li>$object->DirectoryCategory</li>\n";
}
$output .= '</ul>';
}
return $output;
}

Which is a great starter for 10...

Avatar
UncleCheese

29 October 2009 at 8:29am 4085 Posts

MyObjects() is an example placeholder. You should be using the name of the relation in your class. So if you're listing the component People, then you should use $this->People();

That function is a really ugly example of mixing HTML and PHP. You can do something a lot better than that.

Do you need to display the letter even if there are no listings under it?

Avatar
LesC

29 October 2009 at 10:02am Community Member, 70 Posts

Ahh, righto - I see how that connects the objects now, and yes it's pretty ugly code - I was going for quick and dirty, so that I could then generate the letter as heading next :)

And no, if the letter doesn't have an entry it doesn't need to display.

Avatar
LesC

2 November 2009 at 10:18pm Community Member, 70 Posts

So I've got the list now returning two columns nicely (thanks UC!), but still can't work out how to make it create a list like this:

A
Aadvark
Anteater

B
Badger
Bear

C
Cat

etc

Does anyone know how to do this with the returned array, or do I need to go back to mixing my PHP and HTML like the oldschool way?

Avatar
UncleCheese

3 November 2009 at 2:58am 4085 Posts

No, there's never any reason to do that. It's a terrible, deprecated practice that's about has about as much validity as font tags.

You could do this..

private static $alpha = array ('a','b','c','d','e'....);

public function Letters()
{
$set = new DataObjectSet();
$letters = self::$alpha;
$filter = "SomeField > '$letter'";
$filter .= ($next = next($letters)) ? " AND SomeField < '$next'" : "";
foreach($letters as $letter) {
$set =>push(new ArrayData(array(
'Letter' => $letter,
'Listings' => $this->SomeObjects($filter, "SomeField ASC")
)));
}
return $set
}

<% control Letters %>
<h3>$Letter</h3>
<% if Listings %>
<ul>
<% control Listings %>
<li>$SomeField, $AnotherField, etc..</li>
<% end_control %>
</ul>
<% else %>
There are no listings for the letter $Letter.
<% end_if %>

You may have to tweak it a bit, but you get the idea...

Go to Top