custom routing for content pages in zf2 - zend-framework2

Hello to all zend coders. I am newbie to zend, doing code for manage pages through DB.
I want to use URL for these pages like this:
www.domainname.com/about-us
www.domainname.com/contact-us
...
Table name is 'cms_page' & attributes are:
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`page_key` varchar(255) NOT NULL,
`content` longtext NOT NULL,
`added_on` datetime NOT NULL,
I have done R&D for this and here are code:
// in module.config.php
'navigation' => array(
'default' => array(
'account' => array(
'label' => 'Account',
'route' => 'node',
'params' => array(
'id' => '2',
),
'pages' => array(
'home' => array(
'label' => 'Dashboard',
'route' => 'node',
'params' => array(
'id' => '1',
'link' => '/test'
),
),
'login' => array(
'label' => 'Sign In',
'route' => 'node',
'params' => array(
'id' => '5',
'link' => '/about-us'
),
),
'logout' => array(
'label' => 'Sign Out',
'route' => 'node',
'params' => array(
'id' => '3',
),
),
),
),
),
),
'router' => array(
'routes' => array(
'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'index',
),
),
),
'node' => array(
'type' => 'Application\Router\Alias',
'options' => array(
'route' => '/node[/:id]',
'constraints' => array(
'id' => '[0-9]+'
),
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
'id' => '0'
),
),
'may_terminate' => true,
),
),
),
// In Module.php
public function onBootstrap(MvcEvent $e)
{
$app = $e->getApplication();
$sm = $app->getServiceManager();
$sm->get('translator');
$sm->get('viewhelpermanager')->setFactory('controllerName', function($sm) use ($e) {
$viewHelper = new View\Helper\ControllerName($e->getRouteMatch());
return $viewHelper;
});
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$sm->setFactory('Navigation', 'Zend\Navigation\Service\DefaultNavigationFactory', true);
$alias = $sm->get('Application\Router\Alias');
$nav = $sm->get('Navigation');
$alias->setNavigation($nav);
}
public function getServiceConfig()
{
return array(
'factories' => array(
'Application\Router\Alias' => function($sm) {
$alias = new \Application\Router\Alias('/node[/:id]');
return $alias;
},
)
);
}
// Application\src\Application\Router
namespace Application\Router;
use Traversable;
use Zend\Mvc\Router\Exception;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\RequestInterface as Request;
use Zend\Mvc\Router\Http;
use Zend\Mvc\Router\Http\Segment as Segment;
class Alias extends Segment
{
private static $_navigation = null;
public function match(Request $request, $pathOffset = null)
{
$uri = $request->getUri();
$path = $uri->getPath();
$items = self::$_navigation->findAllBy('route', 'node');
$params = null;
if($items != null){
$t = sizeof($items);
for ($i=0; $i getParams();
if (isset($params['link']) && $params['link']==$path){
echo $uri->setPath('/'.$item->getRoute().'/'.$params['id']);
$request->setUri($uri);
break;
}
}
}
return parent::match($request, $pathOffset);
}
public function setNavigation($navigation){
self::$_navigation = $navigation;
}
protected function buildPath(array $parts, array $mergedParams, $isOptional, $hasChild, array $options)
{
if(isset($mergedParams['link'])){
return $mergedParams['link'];
}
return parent::buildPath($parts, $mergedParams, $isOptional, $hasChild, $options = array());
}
}
When I run this url www.domainname.com/about-us on browser getting 404 error.
Please help me where am I wrong and what code need to add or edit?

You can use the a Zend_Controller_Router_Route as an alternative. Here is a quick tutorial on how to do so:
http://www.codexperience.co.za/post/hiding-url-parameters-names-using-zend-routers

Related

Logout does not work

I made login/registration module. I also changed indexAction in LoginController to loginAction but still Logout doesn't work. I try my best but I don't know what the problem is.
My code is given below:
LoginController.php
namespace Users\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Authentication\AuthenticationService;
use Zend\Authentication\Adapter\DbTable as DbTableAuthAdapter;
use Users\Form\LoginForm;
use Users\Form\LoginFilter;
use Users\Model\User;
use Users\Model\UserTable;
class LoginController extends AbstractActionController
{
protected $storage;
protected $authservice;
public function getAuthService()
{
if (! $this->authservice) {
$this->authservice = $this->getServiceLocator()->get('AuthService');
}
return $this->authservice;
}
public function indexAction()
{
$this->layout("layout/layout_users");
if ($this->getAuthService()->hasIdentity())
{
return $this->redirect()->toRoute('admin',
array('action'=>'index'));
}
$form = $this->getServiceLocator()->get('LoginForm');
$viewModel = new ViewModel(array('form' => $form));
return $viewModel;
}
public function processAction()
{
if (!$this->request->isPost()) {
return $this->redirect()->toRoute(NULL , array(
'controller' => 'login',
'action' => 'index'
));
}
$post = $this->request->getPost();
$form = new LoginForm();
$inputFilter = new LoginFilter();
$form->setInputFilter($inputFilter);
$form->setData($post);
if (!$form->isValid()) {
$model = new ViewModel(array(
'error' => true,
'form' => $form,
));
$model->setTemplate('users/login/index');
return $model;
} else {
//check authentication...
$this->getAuthService()->getAdapter()
->setIdentity($this->request->getPost('email'))
->setCredential($this->request->getPost('password'));
$result = $this->getAuthService()->authenticate();
if ($result->isValid()) {
$this->getAuthService()->getStorage()->write($this->request->getPost('email'));
return $this->redirect()->toRoute('admin' , array( ));
} else {
$model = new ViewModel(array(
'error' => true,
'form' => $form,
));
$model->setTemplate('users/login/index');
return $model;
}
}
}
public function logoutAction()
{
if ($this->getAuthService()->hasIdentity()) {
$this->getAuthService()->clearIdentity();
}
return $this->redirect()->toRoute('users/login',
array('action'=>'index'));
}
}
module.config.php for Users module
<?php
return array(
'controllers' => array(
'invokables' => array(
'Users\Controller\Register' => 'Users\Controller\RegisterController',
'Users\Controller\Login' => 'Users\Controller\LoginController',
),
),
'router' => array(
'routes' => array(
'users' => array(
'type' => 'Literal',
'options' => array(
'route' => '/users',
'defaults' => array(
'controller' => 'Users\Controller\Login',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'login' => array(
'type' => 'Segment',
'may_terminate' => true,
'options' => array(
'route' => '/login[/:action]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Users\Controller\Login',
'action' => 'index',
),
),
),
'register' => array(
'type' => 'Segment',
'may_terminate' => true,
'options' => array(
'route' => '/register[/:action]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Users\Controller\Register',
'action' => 'index',
),
),
),
),
),
),
),
'view_manager' => array(
'template_map' => array(
'layout/layout_users' => __DIR__ . '/../view/layout/layout.phtml',
),
'template_path_stack' => array(
'users' => __DIR__ . '/../view',
),
),
);
module.config.php for Admin module:
<?php
namespace Admin;
return array(
'router' => array(
'routes' => array(
'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Admin\Controller\Index',
'action' => 'index',
),
),
),
'profile' => array(
'type' => 'Segment',
'may_terminate' => true,
'options' => array(
'route' => '/profile[/:action]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Admin\Controller\Profile',
'action' => 'index',
),
),
),
'logout' => array(
'type' => 'Segment',
'may_terminate' => true,
'options' => array(
'route' => '/users/login',
'defaults' => array(
'controller' => 'Users\Controller\Login',
'action' => 'logout',
),
),
),
'admin' => array(
'type' => 'Literal',
'options' => array(
'route' => '/admin',
'defaults' => array(
'__NAMESPACE__' => 'Admin\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
),
),
'service_manager' => array(
'abstract_factories' => array(
'Zend\Cache\Service\StorageCacheAbstractServiceFactory',
'Zend\Log\LoggerAbstractServiceFactory',
),
'factories' => array(
'translator' => 'Zend\Mvc\Service\TranslatorServiceFactory',
'navigation' => 'Zend\Navigation\Service\DefaultNavigationFactory',
),
),
'translator' => array(
'locale' => 'en_US',
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
),
),
'controllers' => array(
'invokables' => array(
// 'Admin\Controller\Index' => Controller\IndexController::class
'Admin\Controller\Index' => 'Admin\Controller\IndexController',
'Admin\Controller\Profile' => 'Admin\Controller\ProfileController',
'Admin\Controller\Provinces' => 'Admin\Controller\ProvincesController',
'Admin\Controller\Districts' => 'Admin\Controller\DistrictsController',
'Admin\Controller\Cities' => 'Admin\Controller\CitiesController',
'Admin\Controller\Stations' => 'Admin\Controller\StationsController',
'Admin\Controller\Services' => 'Admin\Controller\ServicesController',
'Admin\Controller\Vehicles' => 'Admin\Controller\VehiclesController',
),
),
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/layout_admin' => __DIR__ . '/../view/layout/layout.phtml',
'admin/index/index' => __DIR__ . '/../view/admin/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
// Placeholder for console routes
'console' => array(
'router' => array(
'routes' => array(
),
),
),
'navigation' => array(
'default' => array(
array(
'label' => 'Home',
'route' => 'home',
),
array(
'label' => 'Profile',
'route' => 'profile',
),
array(
'label' => 'Logout',
'route' => 'logout',
),
),
),
);
Directory for view in User module is:
view/users/login/index.phtml
You have mistakes in a route and a controller.
In controller
public function logoutAction()
{
if ($this->getAuthService()->hasIdentity()) {
$this->getAuthService()->clearIdentity();
}
return $this->redirect()->toRoute('users/login', //Change to 'home'
array('action'=>'index'));
}
In module.config
'logout' => array(
'type' => 'Segment',
'may_terminate' => true,
'options' => array(
'route' => '/users/login', //Change to '/users/logout'
'defaults' => array(
'controller' => 'Users\Controller\Login',
'action' => 'logout',
),
),
),

Validating Zend\Form\Element\Collection

I have a form which has 'rows' added dynamically using Zend\Form\Element\Collection. This works fine, but I am struggling to add the validation for these rows.
So far my code looks something like the following. I presume I need to pass something to InputFilter\InputFilter::add() but I can't figure out what:
<?php
class EditForm extends \Zend\Form\Form
{
public function __construct()
{
parent::__construct('edit');
$this->setUpFormElements();
$this->setupInputFilters();
}
protected function setUpFormElements()
{
$fieldset = new \Zend\Form\Fieldset;
$nameElement = new \Zend\Form\Element\Text('name');
$fieldset->add($nameElement);
$descriptionElement = new \Zend\Form\Element\Text('description');
$fieldset->add($description);
$this->add(
array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'rows',
'options' => array(
'label' => 'Edit Rows',
'should_create_template' => true,
'allow_add' => true,
'target_element' => $fieldset,
)
)
);
return $this;
}
public function setupInputFilters()
{
$filter = new \Zend\InputFilter\InputFilter();
$filter->add(
array(
'name' => 'rows',
'required' => true,
'validators' => array(
// Not sure what to do here!
)
)
);
return $this;
}
}
I think you need to add the input filter to the getInputFilterSpecification method of the fieldset you are adding dynamically
class Row extends Fieldset implements InputFilterProviderInterface
{
$this->add(array(
'name' => 'yourFieldset',
'options' => array(
'label' => 'One of your fieldset elements'
),
'attributes' => array(
'required' => 'required'
)
));
$this->add(array(
'name' => 'fields',
'options' => array(
'label' => 'Another fieldset element'
),
'attributes' => array(
'required' => 'required'
)
));
public function getInputFilterSpecification()
{
return array(
'yourFieldset' => array(
'required' => true,
),
'fields' => array(
'required' => true,
'validators' => array(
array(
'name' => 'Float'
)
)
)
);
}
then in your form you need to set the validation group
class EditForm extends Form
{
public function __construct()
{
$this->add(
array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'rows',
'options' => array(
'label' => 'Edit Rows',
'should_create_template' => true,
'allow_add' => true,
'target_element' => $fieldset,
)
)
);
$this->setValidationGroup(array(
'csrf',
'row' => array(
'yourFieldset',
'fields',
)
));
}
}

ZendFramework 2: No database adapter present

I have this class:
<?php
class RegisterFilter extends InputFilter
{
public function __construct()
{
$this->add(array(
'name' => 'email1',
'required' => true,
'validators' => array(
array(
'name' => 'EmailAddress',
'options' => array(
'domain' => true,
),
),
array(
'name' => 'Identical',
'options' => array(
'token' => 'email2',
),
),
array(
'name' => 'Db\NoRecordExists',
'options' => array(
'table' => 'user',
'field' => 'email',
'messages' => array(
'recordFound' => "Email already exist ... ! <br>",
),
),
),
),
));
}
}
?>
I get this error: No database adapter present. Any ideas why this happens?
It would be good if you'd read the documentation about Zend\Validator\Db\Record*. The given error message means exactly what it said. You don't provide a DB-Adapter inside the Validator.
From the DOCs:
$validator = new Zend\Validator\Db\RecordExists(
array(
'table' => 'users',
'field' => 'emailaddress',
'adapter' => $dbAdapter
)
);
If you want to find out how to get the DB-Adapter into your Form, i have written a Blog Article about said topic.

How To Create Custom Form Elements That Extend Doctrine Entity Select Elements

I am trying to create a custom element where I can pre-set an entity namespace say -- Application\Entity\User and easily add that element to any form. I have an issue with injecting the doctrine em in form elements -- I found this post about the form_elements key in configuration but it doesnt work -- so I figured maybe just setup the element and pass it the objectmanager from the form.
I want to do something like this.
$this->add(
array(
'name' => 'user_id',
'type' => 'Application\Form\Element\UserSelect',
'options' => array(
'label' => 'User',
'object_manager' => $this->getObjectManager(),
),
),
);
Or even better just this
$this->add(
array(
'name' => 'user_id',
'type' => 'Application\Form\Element\UserSelect',
'label' => 'User',
),
);
module.config.php
'service_manager' => array(
'aliases' => array(
'doctrine_service' => 'doctrine.entitymanager.orm_default',
),
'initializers' => array(
function ($instance, $sm) {
if ($instance instanceof DoctrineModule\Persistence\ObjectManagerAwareInterface) {
$instance->setObjectManager(
$sm->get('doctrine_service')
);
}
if ($instance instanceof Application\Form\AbstractForm) {
$instance->init();
}
},
),
),
AbstractForm.php
namespace Application\Form;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use Zend\Form\Form as ZendForm;
abstract class AbstractForm extends ZendForm implements ObjectManagerAwareInterface
{
protected $objectManager;
public function setObjectManager(ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
}
public function getObjectManager()
{
return $this->objectManager;
}
}
TestForm.php
namespace Users\Form;
use Application\Form\AbstractForm;
class Login extends AbstractForm
{
public function init()
{
$this->add(
array(
'name' => 'user_id',
'type' => 'DoctrineORMModule\Form\Element\DoctrineEntity',
'options' => array(
'label' => 'User',
'object_manager' => $this->getObjectManager(),
'target_class' => 'Application\Entity\User',
'property' => 'name',
'find_method' => array(
'name' => 'findBy',
'params' => array(
'criteria' => array('is_deleted' => 0),
'orderBy' => array('name' => 'ASC'),
),
),
),
),
);
}
}
Add your initializer and invokables to the getFormElementConfig method of your Module.php:
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
...
public function getFormElementConfig()
{
return array(
'invokables' => array(
'MyForm' => 'Application\Form\MyForm',
),
'initializers' => array(
'ObjectManagerInitializer' => function ($element, $formElements) {
if ($element instanceof ObjectManagerAwareInterface) {
$services = $formElements->getServiceLocator();
$entityManager = $services->get('Doctrine\ORM\EntityManager');
$element->setObjectManager($entityManager);
}
},
),
);
}
Then use the FormElementManager to get te form:
$forms = $this->getServiceLocator()->get('FormElementManager');
$myForm = $forms->get('MyForm');
Finally add your element inside the init method - not the constructor because he will never be aware of the objectManager:
public function init()
{
$this->add(
array(
'name' => 'user_id',
'type' => 'DoctrineORMModule\Form\Element\DoctrineEntity',
'options' => array(
'label' => 'User',
'object_manager' => $this->getObjectManager(),
'target_class' => 'Application\Entity\User',
'property' => 'name',
'find_method' => array(
'name' => 'findBy',
'params' => array(
'criteria' => array('is_deleted' => 0),
'orderBy' => array('name' => 'ASC'),
),
),
),
),
);
}
See a discussion on this setup here.

ZF2 - Multi navigation with navigation

Is it possible to have 2 differents navigation ?
For example :
//in module.config.php
'service_manager'=>array(
'factories'=>array(
'navigation1'=>'Zend\Navigation\Service\DefaultNavigationFactory',
'navigation2'=>'Zend\Navigation\Service\DefaultNavigationFactory',
),
),
'navigation'=>array(
'navigation1'=>array(
'home'=>array('type' => 'mvc','route' => 'home','active'=>false,'label' => 'Home','title' => 'Home',
'pages'=>array(
'contact'=>array('type' => 'mvc','route'=>'contact','active'=>false,'label'=>'Contact','title' =>'Contact'),
)
),
),
'navigation2'=>array(
'home'=>array('type'=>'mvc','route'=>'home','active'=>false,'label'=>'Home','title'=>'Home',
'contact'=>array('type'=>'mvc','route'=>'faq','active'=>false,'label'=>'Faq','title'=>'Faq'),
),
),
//Dans laout
<?php echo $this->navigation()->menu('navigation1')->setMinDepth(0);?>
<hr />
<?php echo $this->navigation()->menu('navigation2')->setMinDepth(0);?>
I would like 2 differents menu with differents pages but this method doesn't run.
Every one has an idea please ?
Thanks
Birzat
You need to provide a custom factory class for each navigation group. For example, see how ZfcAdmin does this:
Create a custom factory class
<?php
namespace ZfcAdmin\Navigation\Service;
use Zend\Navigation\Service\DefaultNavigationFactory;
class AdminNavigationFactory extends DefaultNavigationFactory
{
protected function getName()
{
return 'admin';
}
}
Source: https://github.com/ZF-Commons/ZfcAdmin/blob/master/src/ZfcAdmin/Navigation/Service/AdminNavigationFactory.php
Register AdminNavigationFactory
// in Module.php
public function getServiceConfig()
{
return array(
'factories' => array(
'admin_navigation' => 'ZfcAdmin\Navigation\Service\AdminNavigationFactory',
),
);
}
Source: https://github.com/ZF-Commons/ZfcAdmin/blob/master/Module.php#L90
Define Navigation trees in your module's configuration under the key you specified in the getName method of your factory. As an example, this is how ZfcUserAdmin adds itself to the ZfcAdmin menu:
'navigation' => array(
'admin' => array(
'zfcuseradmin' => array(
'label' => 'Users',
'route' => 'zfcadmin/zfcuseradmin/list',
'pages' => array(
'create' => array(
'label' => 'New User',
'route' => 'admin/create',
),
),
),
),
),
Source: https://github.com/Danielss89/ZfcUserAdmin/blob/master/config/module.config.php
/vendor/MyNamespace/library/MyNamespace/Navigation/Service/SecondaryNavigationFactory.php
namespace MyNamespace\Navigation\Service;
use Zend\Navigation\Service\DefaultNavigationFactory;
class SecondaryNavigationFactory extends DefaultNavigationFactory {
protected function getName() {
return 'secondary';
}
}
/config/autoload/global.php
return array(
'service_manager' => array(
'factories' => array(
'navigation' => 'Zend\Navigation\Service\DefaultNavigationFactory',
'secondary' => 'MyNamespace\Navigation\Service\SecondaryNavigationFactory',
),
),
'navigation' => array(
'default' => array(
array(
'label' => 'Item-1.1',
'route' => 'foo',
),
array(
'label' => 'Item-1.2',
'route' => 'bar',
),
),
'secondary' => array(
array(
'label' => 'Item-2',
'route' => 'baz',
),
),
),
);
/module/Application/view/layout/layout.phtml
<?php echo $this->navigation('navigation')->menu(); ?>
<?php echo $this->navigation('secondary')->menu(); ?>

Resources