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.

DataObjectManager Module /

Discuss the DataObjectManager module, and the related ImageGallery module.

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

Alphabetical list of objects stored with DOM


Go to End


17 Posts   4592 Views

Avatar
LesC

Community Member, 70 Posts

29 October 2009 at 6:54am

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

Forum Moderator, 4102 Posts

29 October 2009 at 7:26am

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

Community Member, 70 Posts

29 October 2009 at 7:33am

Edited: 29/10/2009 7:54am

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

Community Member, 70 Posts

29 October 2009 at 8:03am

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

Forum Moderator, 4102 Posts

29 October 2009 at 8:29am

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

Community Member, 70 Posts

29 October 2009 at 10:02am

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

Community Member, 70 Posts

2 November 2009 at 10:18pm

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

Forum Moderator, 4102 Posts

3 November 2009 at 2:58am

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