I'd like to create navigation menus from SQL data in ZF3 applications; and in the interest of DRY, I want to try to use common functions to query the data. Based on @Crisp's answer to a similar question, if we want to create a dynamic menu from the module illustrated in the Blog tutorial and use functions from ZendDbSqlRepository
, it seems that the navigation factory should look like this:
namespace Blog\Factory;
use Zend\Navigation\Service\AbstractNavigationFactory;
use Zend\ServiceManager\ServiceLocatorInterface;
use Blog\Model\ZendDbSqlRepository;
class BlogNavigationFactory extends AbstractNavigationFactory
{
/**
* @param ServiceLocatorInterface $serviceLocator
* @return array
* @throws \Zend\Navigation\Exception\InvalidArgumentException
*/
protected function getPages(ServiceLocatorInterface $serviceLocator)
{
if (null === $this->pages) {
$application = $serviceLocator->get('Application');
$routeMatch = $application->getMvcEvent()->getRouteMatch();
$router = $application->getMvcEvent()->getRouter();
// get your pages from wherever...
$postRepository = new ZendDbSqlRepository();
$pages = $postRepository->findAllPosts();
$this->pages = $this->injectComponents($pages, $routeMatch, $router);
}
return $this->pages;
}
public function getName()
{
// this isn't used if fetching from db, it's just here to keep the abstract factory happy
return 'cms';
}
}
the factory would be added to the service manager like this:
// In module/Blog/config/module.config.php:
return [
'service_manager' => [
'aliases' => [ /* ... */ ],
'factories' => [
Model\PostRepository::class => InvokableFactory::class,
Model\ZendDbSqlRepository::class => Factory\ZendDbSqlRepositoryFactory::class,
Model\PostCommand::class => InvokableFactory::class,
Model\ZendDbSqlCommand::class => Factory\ZendDbSqlCommandFactory::class,
'BlogNavigation' => 'Blog\Factory\BlogNavigationFactory',
],
],
'controllers' => [ /* ... */ ],
'router' => [ /* ... */ ],
'view_manager' => [ /* ... */ ],
];
and used in navigation view helpers like this:
<?php echo $this->navigation()->menu('BlogNavigation'); ?>
This doesn't work because the Blog tutorial passes the data through factories and interfaces that the navigation factory would need to reference somehow.
How do I write my navigation factory to use the findAllPosts
function from ZendDbSqlRepository
?
The
getPages()
method receives theServiceManager
instance (which implements theServiceLocatorInterface
), you can get your repository using it like so