Hi Stephan

In a few of my projects I created a Sitemap class that parsed a config file (e.g. Zend_Config) where each member has a title, a controller and an action.

E.g. (in .ini format)

[all]
sitemap.home.title = Home
sitemap.home.controller = home
sitemap.home.action = index

sitemap.news.title = News
sitemap.news.controller = news
sitemap.news.action = index

sitemap.protected.title = Protected Section
sitemap.protected.controller = protected
sitemap.protected.action = index

sitemap.contact.title = Contact
sitemap.contact.controller = contact
sitemap.contact.action = index


The 'Sitemap' class takes both the Zend_Config instance and the Acl instance and iterates through the sitemap, testing each controller/ action against the Acl. This happens in the constructor. If a controller is allowed, it's added to the internal $_sitemap array as an object. So when it comes time to outputting it to my view, you simply iterate through the sitemap instance and there's no extra logic to be parsed.

An example is:-

class Sitemap implements Iterator, Countable
{
    // A simplified sitemap, having only 1 level deep of navigation.
// An exercise for the roll-your-own developer is to make a version that allows nesting/children
    protected $_data = array();
    protected $_ptr = 0;

public function __construct(Zend_Config $config, Zend_Acl, $acl, $role = null)
    {
        foreach ($config as $key => $value) {
// We'll assume that non-existent resources are allowed for this exercise
            if (!$acl->has($value->controller) ||
$acl->isAllowed($role, $value->controller, $value- >action))) {
                    $this->_data[$key] = array('title' => $value,
'url' => array ('controller' => $value->controller, 'action' => $value->action));
            }
        }
    }

    /**
     * Magic method for retrieving properties.
     *
     * @param string $key
     * @return mixed
     */
    public function __get($key)
    {
        if (array_key_exists($key, $this->_data)) {
            return $this->_data[$key];
        }
        return null;
    }

    /**
     * Magic method for setting properties.
     *
     * @param string $name
     * @param mixed $value
     * @return void
     */
    public function __set($key, $value)
    {
        $this->_data[$key] = $value;
    }

    /**
     * Support isset() overloading on PHP 5.1
     *
     * @param string $name
     * @return boolean
     */
    protected function __isset($name)
    {
        return isset($this->_data[$name]);
    }

    /**
     * Defined by Countable interface
     *
     * @return int
     */
    public function count()
    {
        return count($this->_data);
    }

    /**
     * Defined by Iterator interface
     *
     * @return mixed
     */
    public function current()
    {
        return current($this->_data);
    }

    /**
     * Defined by Iterator interface
     *
     * @return mixed
     */
    public function key()
    {
        return key($this->_data);
    }

    /**
     * Defined by Iterator interface
     *
     */
    public function next()
    {
        if (next($this->_data) === false) {
            $this->_ptr = false;
        } else {
            $this->_ptr = true;
        }
    }

    /**
     * Defined by Iterator interface
     *
     */
    public function rewind()
    {
        reset($this->_data);
        $this->_ptr = true;
    }

    /**
     * Defined by Iterator interface
     *
     * @return boolean
     */
    public function valid()
    {
        return $this->_ptr;
    }
}


IN your bootstrap you instantiate it:-

$acl = new Zend_Acl();
$acl->addResource(new Zend_Acl_Resource('protected'));
$acl->deny(null, 'protected'); // Created a protected area for the purpose of demonstration

$sitemapConfig = new Zend_Config(new Zend_Config_Ini('/path/to/ config.ini')); $sitemap = new Sitemap($sitemapConfig, $acl); // A 3rd arg $role can be added here if desired (see above)

$view->sitemap = $sitemap;

...and in your view, it's as simple as:-

<?php

<ul class="menu">
    <?php foreach ($this->sitemap as $id => $section): ?>
<li><a href="<?php echo $this->url($section->url, null, true); ? >"><?php echo $this->escape($section->title) ?></a></li>
    <?php endforeach; ?>
</ul>

I can't say if it's best practice, but it works for me and the views end up being a lot cleaner for other designers/developers to read.

Cheers

this is something that interests me a lot as well. Unfortunately, this
topic is not covered in Simons article. Are there best practises for
making views visible/invisible depending on particular user roles?

--

Simon Mundy | Director | PEPTOLAB

""" " "" """""" "" "" """"""" " "" """"" " """"" "  """""" "" "
202/258 Flinders Lane | Melbourne | Victoria | Australia | 3000
Voice +61 (0) 3 9654 4324 | Mobile 0438 046 061 | Fax +61 (0) 3 9654 4124
http://www.peptolab.com


Reply via email to