Welcome Guest, Not a member yet? Register   Sign In
Forum breadcrumb class - where to start?
#1

[eluser]TheFuzzy0ne[/eluser]
I'm trying to create a breadcrumb class/helper for my forum, and I'm not quite sure where to start. Creating a breadcrumb for any given forum seems simple enough, but it seems to quickly become complex when I try to factor in including threads, and posts, and search results and so on.

I've seen a lot of breadcrumb classes, but they all seem to rely on directory or URL structure. I'd appreciate it if anyone could make a suggestion about how I could make this work. A suggestion for method names would probably give me everything I need.

I'm also not sure if the model should pass back the HTML, or if the model should just pass back an array for me to use with a helper function that generates the HTML (which makes more sense to me).

Perhaps the breadcrumb class needs to be integrated into my site a bit more, so rather than calling several functions, the breadcrumb is built as the code progresses?

All comments and suggestions welcome.
#2

[eluser]jedd[/eluser]
On my forum module (a work still in progress, and heavily modeled on the CI Forum approach) I do much as they do for forum breadcrumbs :

Code:
Forum Home  >  CodeIgniter Development Forums  >  Code and Application Development  >  Thread

You don't mean breadcrumb in the sense of taking you from where you came, so much as tracking where you are in the hierarchy, do you? If the former, then probably a compound addition to flashdata -- an array of perhaps 3 or 4 items that you just do some FIFO magic with - would probably work reasonably well, especially if you were preparing your breadcrumb string or view snippet in your MY_Controller (or similar).

You seem to hint that basing on URL structure won't work .. is that because you've got a flat structure, or the work involved in converting '111457' to 'Forum breadcrumb class - where to start?' kind of lookups? That's what I'm doing, btw, and works pretty well. I have to pass forum / thread / message id's around, so just pass forum-name and thread-subjects at the same time.

I generate my breadcrumbs in my Forum controller - which handles all public messaging - so no repetition as such (my Mail system is pretty much the 'whispered threads' that xwero pointed me at a while ago - and consequently I've replicated lumps of code from the Forum controller until I work out what I can abstract down again). I digress.
#3

[eluser]TheFuzzy0ne[/eluser]
Hi, Jedd!

Yes, the structure is flat, I've been playing with about 100 different ways to do what I want, but they all seem quite messy. I think I have it sussed, however. I'm just stuck on what to name my model method, and how it should work. It uses the MPTtree library, and this is what I have so far (it really needs changing I feel, as does the method name):

Code:
function get_breadcrumb_array($forum_id=0)
    {
        if ($forum_id)
        {
            if ($parent_row = $this->get_forum_row($forum_id))
            {
                $rows = array();
                foreach ($this->mptt->get_parents($parent_row['lft'], $parent_row['rgt']) as $row)
                {
                    $rows[] = array('id' => $row['id'], 'title' => $row['title']);
                }
                $rows[] = array('id' => $parent_row['id'], 'title' => $parent_row['title']);
                
                unset($rows[0]);
                $rows = array_reverse($rows);
                
                return $rows;
            }
        }
        return array();
    }
    
    function get_forum_row($id=0)
    {
        if ($id)
        {
            $res = $this->db->get_where('forums', array('id' => $id));
            if ($res->num_rows())
            {
                return $res->row_array();
            }
        }
        return FALSE;
    }

Your thoughts are welcome as always.

Here's the breadcrumb class I've developed so far. It probably needs some of the rough edges files down a bit, but it works, and is fairly straight forward.

Code:
<?php

class Breadcrumb {
    
    var $_segments = array();
    var $separator = ' > ';
    var $breadcrumb_prefix = '';
    var $breadcrumb_suffix = '';
    var $separator_prefix = '';
    var $separator_suffix = '';
    
    function initialize($config=array())
    {
        foreach ($config as $key=>$value)
        {
            if (method_exists($this, $key))
            {
                $this->$key = $value;
            }
        }
    }
    
    /**
     * Set's the separator for the breadcrumb
     *
     * @return void
     * @param string $separator
     */
    function set_separator($separator="")
    {
        $this->separator = $separator;
    }
    
    /**
     * Allows you to set the prefix and suffix for the separator.
     *
     * @return void
     * @param string $prefix
     * @param string $suffix
     */
    function set_separator_delimiters($prefix='', $suffix='')
    {
        $this->_separator_prefix = $prefix;
        $this->_separator_suffix = $suffix;
    }
    
    /**
     * Allows you to set the prefix and suffix for the breadcrumbs.
     *
     * @return void
     * @param array $prefix
     * @param array $suffix
     */
    function set_breadcrumb_delimiters($prefix='', $suffix='')
    {
        $this->_breadcrumb_prefix = $prefix;
        $this->_breadcrumb_suffix = $suffix;
    }
    
    /**
     * Returns an HTML string containing the generated breadcrumbs
     *
     * @return string
     * @param array $config[optional] This is just for convenience
     */
    function get($config=array())
    {
        if (is_array($config) && count($config) > 0)
        {
            $this->initialize($config);
        }
        
        $output = array();
        $count = 0;
        foreach ($this->_segments as $bc)
        {
            $count++;
            $str = $bc['text'];
            if ($bc['url'] != '' && $count != count($this->_segments))
            {
                $str = '<a href="'
                . $bc['url']
                . '" title="' . $bc['title'] .'">'
                . $str
                . '</a>';
            }
            
            $str = $this->breadcrumb_prefix . $str . $this->breadcrumb_suffix;
            
            $output[] = $str;
        }
        
        return implode(
            $this->separator_prefix    . $this->separator . $this->separator_suffix,
            $output
        );
        
    }
    
    /**
     * Adds the specified array to the already existing segments.
     *
     * array(
     *         'text' => 'breadcrumb text',
     *         'url' => 'breadcrumb URL',
     *         'title' => 'anchor title' // Optional
     *     );
     *
     * You can also specify a string (usually for the last breadcrumb),
     * which will not be turned into a link, or an array of arrays
     * in the above format.
     *
     * @return bool Just in case you want to do some extra checking.
     * @param mixed $data
     */
    function add($data=array())
    {
        if (is_array($data) && count($data) > 0)
        {
            if (isset($data['text']))
            {
                $this->_segments[] = array(
                    'text' => $data['text'],
                    'url' => (isset($data['url'])) ? $data['url'] : '',
                    'title' => (isset($data['title'])) ? $data['title'] : ''
                );
            }
            else if (isset($data[0]) && is_array($data[0]))
            {
                foreach ($data as $arr)
                {
                    $this->add($arr);
                }
            }
            
            return TRUE;
        }
        else if (is_string($data) && $data != '')
        {
            $this->add(array(
                    'text' => $data,
                    'url' => '',
                    'title' => ''
                ));
            return TRUE;
        }
        
        return FALSE;
    }
}

Thanks again for your comments.
#4

[eluser]jedd[/eluser]
Well, the MPT stuff is going straight over my head, but I'm curious how many levels are you anticipating with your forum - and what actual levels would they reflect. Can you give me an example of the contents of some of these breadcrumbs that you'd be displaying?

My approach is far simpler, because I settled on a finite (3 !) levels, and one of those has precious little meta data (message must be part of a thread, and consequently message pretty much just has an ID and CONTENT - so nothing to show in a breadcrumb, and indeed messages are never shown independently of their parent thread anyway). So in that sense, there's really only two levels that can change, and a static level above that.

What do you do, on the presentation side, if your MPT hierarchy gets quite deep?
#5

[eluser]TheFuzzy0ne[/eluser]
MPTT goes way over my head too, which is why I use someone else's library. Bar a single inconsistency, the library is fantastic. The API is fairly straight forward, and quite well documented. I highly recommend it.

I'm not sure how many levels there's likely to be, but I didn't want to limit it as such. I wouldn't imagine it would go over three, but hey, why not? As for examples, I can't give you any, as the client apparently doesn't even know yet...

As for presentation - the breadcrumbs will be in a div, which will allow it to expand vertically if it's too wide.

I've been thinking about my dilemma, and I think my main problem is that I am expecting my model methods to do too much, and as a result it's losing its simplicity. I try to get the data I need in one fowl swoop, when I should really have the controller do a bit more work, or perhaps export the processing to a library or something. That way, I shouldn't end up with tons of quite similar model methods, but rather fewer generic methods.

I don't mean to be cheeky, but I'd be really interested to see what you've come up with so far with your forums module.
#6

[eluser]TheFuzzy0ne[/eluser]
OK, I'm still at a loss here. I can easily get the breadcrumb for the current forum, but I can't visualise how to do the same thing but from a forum thread (if that makes sense). I'm not sure if I should be doing this all with a single call to the model, or if I'm expecting too much as usual, and it should be done with two calls the the model - one for getting the forum breadcrumb, and one for getting the thread title.

I can't believe something so trivial is stressing me out so much...
#7

[eluser]ericsodt[/eluser]
[quote author="TheFuzzy0ne" date="1239646240"]OK, I'm still at a loss here. I can easily get the breadcrumb for the current forum, but I can't visualise how to do the same thing but from a forum thread (if that makes sense). I'm not sure if I should be doing this all with a single call to the model, or if I'm expecting too much as usual, and it should be done with two calls the the model - one for getting the forum breadcrumb, and one for getting the thread title.

I can't believe something so trivial is stressing me out so much...[/quote]

Please try my breadcrumb class... should help you out
#8

[eluser]TheFuzzy0ne[/eluser]
Hi. Nice library, thanks for sharing. As you can see, mine works on a very similar principle. I'd managed to get things working with my own simpler class. But hopefully I can still switch to yours though. It seems much cleaner than mine.




Theme © iAndrew 2016 - Forum software by © MyBB