# Adding navigation container and pages dynamically

**URL:** <https://discourse.laminas.dev/t/adding-navigation-container-and-pages-dynamically/398>\
**Category:** Components & MVC\
**Tags:** zend-mvc, zend-navigation\
**Created:** [December 13, 2017, 10:54am UTC](https://discourse.laminas.dev/t/adding-navigation-container-and-pages-dynamically/398 "2017-12-13T10:54:09Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [December 13, 2017, 10:54am UTC](https://discourse.laminas.dev/t/adding-navigation-container-and-pages-dynamically/398/1 "2017-12-13T10:54:09Z")

</div>

hello everyone, just out of curiosity is it possible to have a model that creates navigation container and pages from options that are available from querying the database? I already use Zend-Navigation but it is needed to be provided configuration array in the application module.config.php.

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [December 13, 2017, 11:25am UTC](https://discourse.laminas.dev/t/adding-navigation-container-and-pages-dynamically/398/2 "2017-12-13T11:25:08Z")

</div>

> [@erfan](#):
>
> …but it is needed to be provided configuration array in the application module.config.php.

Sorry this is wrong, because this is only one way. There are more options to create a navigation.

Create your own factory for the navigation and combine the navigation configuration from the config and the database (repository, service etc). Register the new factory for the navigation, see at the [quick start](https://docs.zendframework.com/zend-navigation/quick-start/).

(Note to myself: adding an example to the documentation)

---

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [February 23, 2018, 11:57am UTC](https://discourse.laminas.dev/t/adding-navigation-container-and-pages-dynamically/398/3 "2018-02-23T11:57:03Z")

</div>

> [@froschdesign](#):
>
> Create your own factory for the navigation and combine the navigation configuration from the config and the database (repository, service etc). Register the new factory for the navigation

What I got from your advice is as follows:  
I already have a database and tables. My desired menu items are defined in `menu` table and I used an `entity` class (Menu.php):  
**Menu.php**

```
namespace Application\Model;
class Menu
{
    private $id;
    private $title;
    private $is_head;
    private $link;
    private $order;
    public function __construct($id,$title,$is_head,$link,$order)
    {
        $this->id = $id;
        $this->title = $title;
        $this->is_head = $is_head;
        $this->link = $link;
        $this->order = $order;
    }
    public function getId()
    {
        return $this->id;
    }
    public function getTitle()
    {
        return $this->title;
    }
    public function getIsHead()
    {
        return $this->is_head;
    }
    public function getLink()
    {
        return $this->link;
    }
    public function getOrder()
    {
        return $this->order;
    }
}

```

and a `repository` (MenuRepository.php):  
**MenuRepository.php**

```
namespace Application\Model;
use Zend\Db\Sql\Sql;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\ResultSet\HydratingResultSet;
use Zend\Hydrator\HydratorInterface;
use RuntimeException;
use Zend\Db\Adapter\Driver\ResultInterface;

class MenuRepository implements MenuRepositoryInterface
{
    private $db;
    private $menu;
    private $hydrator;
    public function __construct(adapterInterface $db,
                                HydratorInterface $hydrator,
                                Menu $menu)
    {
        $this->db = $db;
        $this->menu = $menu;
        $this->hydrator = $hydrator;
    }
    public function getMenuItems()
    {
        $sql = new Sql($this->db);
        $select = $sql->select('menu');
        $select->order('ord');
        $statement = $sql->prepareStatementForSqlObject($select);
        $result = $statement->execute();
        if (! $result instanceof ResultInterface || ! $result->isQueryResult()) {
            throw new RuntimeException(sprintf(
                'Failed retrieving blog post with identifier "%s"; unknown database error.',
                $result
            ));
        }
        $resultSet = new HydratingResultSet($this->hydrator, $this->menu);
        $resultSet->initialize($result);
        return $resultSet;

    }
}

```

to store and retrieve them. So far so good. but the problem I encountered after this step was how to use them as a Navigation items.  
At this point I don’t know to use my IndexController to call the methods OR use Bootstrap($e) within the Application\Module.php???  
I am open to any suggestion.  
thanks.

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [February 23, 2018, 1:48pm UTC](https://discourse.laminas.dev/t/adding-navigation-container-and-pages-dynamically/398/4 "2018-02-23T13:48:31Z")

</div>

> [@erfan](#):
>
> …after all studying and searching…

**You forgot the factory.** The class `MenuCreator` is not needed. (See my comment above!)

Here some (pseudo) code:

```php
namespace Application\Navigation;

use Application\Model\MenuRepositoryInterface;
use Interop\Container\ContainerInterface;
use Zend\Navigation\Service\AbstractNavigationFactory;

class MyNavigationFactory extends AbstractNavigationFactory
{
    protected function getName() : string
    {
        return 'my-navigation';
    }

    protected function getPages(ContainerInterface $container) : array
    {
        if (null === $this->pages) {
            /** @var MenuRepositoryInterface $menuRepository */
            $menuRepository = $container->get(MenuRepositoryInterface::class);

            $menuItems = $menuRepository->getMenuItems();
            $pages = [];
            foreach ($menuItems as $item) {
                $pages[] = [
                    'label' => $item->getTitle(),
                    'route' => $item->getLink(),
                ];
            }

            $this->pages = $this->preparePages($container, $pages);
        }

        return $this->pages;
    }
}

```

Register your navigation in config:

```php
'service_manager' => [
    'factories' => [
        'my-navigation' => Application\Navigation\MyNavigationFactory::class,
    ]
]

```

Use your navigation in the layout-script:

```php
<?= $this->navigation('my-navigation')->menu() ?>

```

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [February 23, 2018, 2:09pm UTC](https://discourse.laminas.dev/t/adding-navigation-container-and-pages-dynamically/398/5 "2018-02-23T14:09:36Z")

</div>

@erfan  
Please delete all the code for the `MenuCreator` class from your comment before someone copies something. This is wrong and will not work. Thanks!

---

<div class="post-metadata">

**Author:** ![erfan](https://avatars.discourse-cdn.com/v4/letter/e/c4cdca/32.png) [@erfan](https://discourse.laminas.dev/u/erfan)\
**Post date:** [February 23, 2018, 2:36pm UTC](https://discourse.laminas.dev/t/adding-navigation-container-and-pages-dynamically/398/6 "2018-02-23T14:36:35Z")

</div>

> [@froschdesign](#):
>
> You forgot the factory

thanks for your helping I am pretty sure this will work out!!! but I didn’t get what you meant from **factory**. there were lots of coding in the reference that made me confused and had no clue where to begin.
