ZF2 tree routing - php

How to configure ZF2 tree pages routing?
I have multilevel pages. For example:
contacts
contacts/office
contacts/office/office1
products
products/category1
products/category1/product1
and more.
I use one controller for page and this config for routing:
'page' => array(
'type' => 'Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Application\PageController'
)
),
'priority' => -1000,
'may_terminate' => false,
'child_routes' => array(
'name' => array(
'type' => 'Segment',
'options' => array(
'route' => ':sn1[/:sn2[/:sn3[/:sn4[/:sn5[/:sn6]]]]]',
'constraints' => array(
'sn1' => '[a-zA-Z][a-zA-Z0-9]*',
'sn2' => '[a-zA-Z][a-zA-Z0-9]*',
'sn3' => '[a-zA-Z][a-zA-Z0-9]*',
'sn4' => '[a-zA-Z][a-zA-Z0-9]*',
'sn5' => '[a-zA-Z][a-zA-Z0-9]*',
'sn6' => '[a-zA-Z][a-zA-Z0-9]*'
),
'defaults' => array(
'controller' => 'Application\PageController',
'action' => 'page'
)
)
)
)
)
Page action:
$params = array('sn1', 'sn2', 'sn3', 'sn4', 'sn5', 'sn6');
$names = array();
foreach ($params as $param) {
if($this->params($param, NULL) === NULL) {
break;
} else {
$names[] = $this->params($param, NULL);
}
}
var_dump($names);
$path = implode('/', $names);
var_dump($path);
Result for http://example.com/contacts/office/office1:
array (size=3)
0 => string 'contacts' (length=8)
1 => string 'office' (length=6)
2 => string 'office1' (length=7)
string 'contacts/office/office1' (length=23)
Are there any better way to implement?

Related

Replace key in array, with keeping order intact

I would like to replace keys in arrays, because I will move them on two indexes up.
Problem that I am facing is that those are containing same names which will not be ok, if i want to move them up.
This is how array looks like.
$list = array(
'ind' => array(
'messagetype' => 'Alert',
'visibility' => 'Public',
'info' => array(
0 => array(
'urgency' => 'Urgent',
'params' => array(
0 => array(
'Name' => 'display',
'value' => '3; top',
),
1 => array(
'Name' => 'level',
'value' => '1; blue',
),
),
'area' => array(
'ard' => 'Bob',
'code' => array(
0 => array(
'Name' => 'Badge',
'value' => 'GSSD154',
),
),
),
),
1 => array(
'messagetype' => 'Information',
'visibility' => 'Private',
'info' => array(
0 => array(
'urgency' => 'Minor',
'params' => array(
0 => array(
'Name' => 'display',
'value' => '1; left',
),
1 => array(
'Name' => 'level',
'value' => '1; red',
),
),
'area' => array(
'ard' => 'Bob',
'code' => array(
0 => array(
'Name' => 'Badge',
'value' => 'GBECS23',
),
),
),
),
),
),
),
),
);
and this is how I would like the output to be with changing keys in Name0, Name1, which are inside params.
$list = array(
'ind' => array(
'messagetype' => 'Alert',
'visibility' => 'Public',
'info' => array(
0 => array(
'urgency' => 'Urgent',
'params' => array(
0 => array(
'Name0' => 'display',
'value0' => '3; top',
),
1 => array(
'Name1' => 'level',
'value1' => '1; blue',
),
),
'area' => array(
'ard' => 'Bob',
'code' => array(
0 => array(
'Name' => 'Badge',
'value' => 'GSSD154',
),
),
),
),
1 => array(
'messagetype' => 'Information',
'visibility' => 'Private',
'info' => array(
0 => array(
'urgency' => 'Minor',
'params' => array(
0 => array(
'Name0' => 'display',
'value0' => '1; left',
),
1 => array(
'Name1' => 'level',
'value1' => '1; red',
),
),
'area' => array(
'ard' => 'Bob',
'code' => array(
0 => array(
'Name' => 'Badge',
'value' => 'GBECS23',
),
),
),
),
),
),
),
),
);
I have tried with a lots of examples over this website, but could not find one to achieve this.
Code that I used from
How to replace key in multidimensional array and maintain order
function replaceKey($subject, $newKey, $oldKey) {
// if the value is not an array, then you have reached the deepest
// point of the branch, so return the value
if (!is_array($subject)) {
return $subject;
}
$newArray = array(); // empty array to hold copy of subject
foreach ($subject as $key => $value) {
// replace the key with the new key only if it is the old key
$key = ($key === $oldKey) ? $newKey : $key;
// add the value with the recursive call
$newArray[$key] = replaceKey($value, $newKey, $oldKey);
}
return $newArray;
}
$s = replaceKey($list, 'Name0', 'Name');
print "<PRE>";
print_r($s);
at the moment I get this output:
[0] => Array
(
[Name0] => display
[value] => 1; left
)
[1] => Array
(
[Name0] => level
[value] => 1; red
)
any help would be appreciated. regards
A very strange question, but why not?
The following function returns nothing (a procedure) and changes the array in-place using references but feel free to rewrite it as a "real" function (without references and with a return statement somewhere).
The idea consists to search for arrays, with numeric keys and at least 2 items, in which each item has the Name and value keys. In other words, this approach doesn't care about paths where the targets are supposed to be:
function replaceKeys(&$arr) {
foreach ($arr as &$v) {
if ( !is_array($v) )
continue;
$keys = array_keys($v);
if ( count($keys) < 2 ||
$keys !== array_flip($keys) ||
array_keys(array_merge(...$v)) !== ['Name', 'value'] ) {
replaceKeys($v);
continue;
}
foreach ($v as $k => &$item) {
$item = array_combine(["Name$k", "value$k"], $item);
}
}
}
replaceKeys($list);
print_r($list);
demo

How to get value of element in the same array when initialize

I Think it's a strange question :
i dont need answer with loop or push to array i'm just wondering about the idea
I'm trying ti initialize an array ,, but i need to read the previous element like this,
return $recourd_list = array(
'clients'=> array(
'route' => 'clients.index',
'title' => 'fullname',
'list' => Clients::orderBy('id', 'desc')->take(5)->get(),
'count' => Clients::count(),
'class' => 'bgm-lightgreen',
'diff' => 5 - $recourd_list['clients']['count'],
),
'sliders'=> array(
'route' => 'sliders',
'title' => 'title',
'list' => Sliders::orderBy('id', 'desc')->take(5)->get(),
'count' => Sliders::count(),
'class' => 'bgm-rightBlue Oil-color',
'diff' => 5 - $recourd_list['sliders']['count'],
),
'sponsors'=> array(
'route' => 'sponsors.index',
'title' => 'title',
'list' => Sponsors::orderBy('id', 'desc')->take(5)->get(),
'count' => Sponsors::count(),
'class' => 'bgm-nave dark-green',
'diff' => 5 - $recourd_list['sponsors']['count'],
),
'packages'=> array(
'route' => 'packages',
'title' => 'title',
'list' => Packages::orderBy('id', 'desc')->take(5)->get(),
'count' => Packages::count(),
'class' => 'bgm-bluegray',
'diff' => 5 - $recourd_list['packages']['count'],
),
'event_schedule'=> array(
'route' => 'event_schedule.index',
'title' => 'title',
'list' => EventSchedule::orderBy('id', 'desc')->take(5)->get(),
'count' => EventSchedule::count(),
'class' => 'bgm-orange',
'diff' => 5 - $recourd_list['event_schedule']['count'],
),
);
I need to read the count element in diff element .. is that way to do that when initialize array
Thanks All
No, this isn't possible as the array technically won't be defined at that point.
One way to achieve this would be to use something like array_map.
http://php.net/manual/en/function.array-map.php
$recourd_list = array(
'clients'=> array(
'route' => 'clients.index',
'title' => 'fullname',
'list' => Clients::orderBy('id', 'desc')->take(5)->get(),
'count' => Clients::count(),
'class' => 'bgm-lightgreen',
),
'sliders'=> array(
'route' => 'sliders',
'title' => 'title',
'list' => Sliders::orderBy('id', 'desc')->take(5)->get(),
'count' => Sliders::count(),
'class' => 'bgm-rightBlue Oil-color',
),
'sponsors'=> array(
'route' => 'sponsors.index',
'title' => 'title',
'list' => Sponsors::orderBy('id', 'desc')->take(5)->get(),
'count' => Sponsors::count(),
'class' => 'bgm-nave dark-green',
),
'packages'=> array(
'route' => 'packages',
'title' => 'title',
'list' => Packages::orderBy('id', 'desc')->take(5)->get(),
'count' => Packages::count(),
'class' => 'bgm-bluegray',
),
'event_schedule'=> array(
'route' => 'event_schedule.index',
'title' => 'title',
'list' => EventSchedule::orderBy('id', 'desc')->take(5)->get(),
'count' => EventSchedule::count(),
'class' => 'bgm-orange',
),
);
then
return array_map(function ($item) {
$item['diff'] = $item['count'] - 5;
return $item;
}, $recourd_list);
Alternatively, you could use map with Collections
https://laravel.com/docs/5.3/collections#method-map
return collect($recourd_list)->map(function ($item) {
$item['diff'] = $item['count'] - 5;
return $item;
})->toArray();
Hope this helps!
short answer:
no.
But since you are, at init time, defining the Count, why not do this:
'diff' => 5 - Clients::count(),
so with the entire example:
return $recourd_list = array(
'clients' => array(
'route' => 'clients.index',
'title' => 'fullname',
'list' => Clients::orderBy('id', 'desc')->take(5)->get(),
'count' => Clients::count(),
'class' => 'bgm-lightgreen',
'diff' => 5 - Clients::count(),
),
'sliders' => array(
'route' => 'sliders',
'title' => 'title',
'list' => Sliders::orderBy('id', 'desc')->take(5)->get(),
'count' => Sliders::count(),
'class' => 'bgm-rightBlue Oil-color',
'diff' => 5 - Sliders::count(),
),
'sponsors' => array(
'route' => 'sponsors.index',
'title' => 'title',
'list' => Sponsors::orderBy('id', 'desc')->take(5)->get(),
'count' => Sponsors::count(),
'class' => 'bgm-nave dark-green',
'diff' => 5 - Sponsors::count(),
),
'packages' => array(
'route' => 'packages',
'title' => 'title',
'list' => Packages::orderBy('id', 'desc')->take(5)->get(),
'count' => Packages::count(),
'class' => 'bgm-bluegray',
'diff' => 5 - Packages::count(),
),
'event_schedule' => array(
'route' => 'event_schedule.index',
'title' => 'title',
'list' => EventSchedule::orderBy('id', 'desc')->take(5)->get(),
'count' => EventSchedule::count(),
'class' => 'bgm-orange',
'diff' => 5 - EventSchedule::count(),
),
);

create dynamic multidimensional array using PHP

I want to create dynamic multidimensional array using PHP
I need to generate array like this ...
$fetchMenu = array('page-1' => array(
'name' => 'first_page',
'label' => 'First page 2',
'route' => 'product_index',
'pages' => array(
array(
'name' => 'xxx',
'label' => 'xxx',
'route' => 'product_index',
), array(
'id' => 'permissions',
'label' => 'Permissions',
'title' => 'Permissions',
'route' => 'product_add',
'menu_tree_path' => 'default|system|roles_and_permission|permissions',
'display_in_menu' => true,
)
),
),
'page-2' => array(
'name' => 'second_page',
'label' => 'Second page 2',
'route' => 'product_index',
'pages' => array(),
),);
How can I do it ?
something like this?
$dynMenu = array();
$bookLength = 5; //function getBookLength() ??
for($i=0;$i<$bookLength;$i++){
$pageNumber = 'page'.$i;
$page = $i; // function getPages() ??
$dynMenu[$pageNumber] = array('name' => 'foo', 'label' => 'bar');
for($j=0;$j<$page;$j++){
$dynMenu[$pageNumber][$j] = array('name' => 'foo-ish', 'label' => 'bar-ish');
}
}

I need to hide some of the parts of zf2 URL

I have a web app using zf2. And when it launches it shows the URL like follows:
http://www.example.com/auth/themes/neighborhoods for the neighborhoods
http://www.example.com/auth/comments/comments for the comments
http://www.example.com/auth/themes/themes for the themes
I need to make them like:
http://www.example.com/neighborhoods
http://www.example.com/comments
http://www.example.com/themes
I tried to play with module.config.php, but no use:
'router' => array(
'routes' => array(
'home' => array(
'type' => 'Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Auth\Controller\Index',
'action' => 'login',
),
),
),
'auth' => array(
'type' => 'Literal',
'options' => array(
'route' => '/auth',
'defaults' => array(
'__NAMESPACE__' => 'Auth\Controller',
'controller' => 'Auth\Controller\Index',
'action' => 'login',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action[/:id]]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
),
),
Any help would be appreciated!
Solution one :
'neighborhoods' => array(
'type' => 'Literal',
'options' => array(
'route' => '/neighborhoods',
'defaults' => array(
'module' => 'auth',
'controller' => 'neighborhoods',
'action' => 'neighborhoods',
),
),
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:id]',
'constraints' => array(
'id' => '[a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
'comments' => array(
'type' => 'Literal',
'options' => array(
'route' => '/comments',
'defaults' => array(
'module' => 'auth',
'controller' => 'comments',
'action' => 'comments',
),
),
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:id]',
'constraints' => array(
'id' => '[a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
'themes' => array(
'type' => 'Literal',
'options' => array(
'route' => '/themes',
'defaults' => array(
'module' => 'auth',
'controller' => 'themes',
'action' => 'themes',
),
),
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:id]',
'constraints' => array(
'id' => '[a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
Solution 2 : Custom route
http://www.zendexperts.com/2012/12/09/custom-routing-in-zend-framework-2/
in module.config.php
'routeTestCustom' => array(
'type' => 'pageRoute',
),
in Module.php
use [modulename]\Route\PageRoute;
....
public function getRouteConfig()
{
return array(
'factories' => array(
'pageRoute' => function ($routePluginManager) {
$locator = $routePluginManager->getServiceLocator();
$params = array('defaults' => array('module' => 'auth' ));
$route = PageRoute::factory($params);
$route->setServiceManager($locator);
return $route;
},
),
);
}
your custom route class in [module_name]\src[module_name]\Route\PageRoute.php
namespace [module_name]\Route;
use Zend\Mvc\Router\Http\RouteInterface;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\Stdlib\RequestInterface as Request;
use Zend\Mvc\Router\Http\RouteMatch;
class PageRoute implements RouteInterface
{
protected $defaults;
public function __construct(array $defaults = array())
{
$this->defaults = $defaults;
}
public static function factory($options = array())
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (!is_array($options)) {
throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable set of options');
}
if (!isset($options['defaults'])) {
$options['defaults'] = array();
}
return new static($options['defaults']);
}
public function match(Request $request)
{
$uri = $request->getUri();
$path = $uri->getPath();
$part = explode('/',$uri);
if(count($part) == 4 && $part[0] == 'http:' && $part[2] == "www.example.com"){
$params = $this->defaults;
$params['controller'] = $part[3];
$params['action']= $part[3];
}
return new RouteMatch($params);
}
public function assemble(array $params = array(), array $options = array()){
return $this->route;
}
public function getAssembledParams()
{
return array();
}
}
Updated

How to remove routing error in zf2?

I used authentication in zend module but when i render it gives me error like
Zend\View\Renderer\PhpRenderer::render: Unable to render template "calendar/index/login"; resolver could not resolve to a files
here is my module.config.php:
<?php
return array(
'controllers' => array(
'invokables' => array(
'Calendar\Controller\Index' => 'Calendar\Controller\IndexController',
'Calendar\Controller\User' => 'Calendar\Controller\UserController',
'Calendar\Controller\Calendar' => 'Calendar\Controller\CalendarController',
'Calendar\Controller\Event' => 'Calendar\Controller\EventController'
),
),
'router' => array(
'routes' => array(
/*###############*/
//index
'admin_index' => array(
'type'=>'segment',
'options' => array(
'route'=>'/calendar/admin[/]',
'defaults'=>array('controller'=>'Calendar\Controller\Index','action'=>'index')
)
),
//login
'admin_login' => array(
'type'=>'literal',
'options' => array(
'route'=>'/calendar/admin/login',
'defaults'=>array('controller'=>'Calendar\Controller\Index','action'=>'login')
)
),
//logout
'admin_logout' => array(
'type'=>'literal',
'options' => array(
'route'=>'/calendar/admin/logout',
'defaults'=>array('controller'=>'Calendar\Controller\Index','action'=>'logout')
)
),
//user index
'admin_user' => array(
'type'=>'segment',
'options' => array(
'route'=>'/calendar/admin/user[/]',
'defaults'=>array('controller'=>'Calendar\Controller\User','action'=>'index')
)
),
//user add
'admin_user_add' => array(
'type'=>'segment',
'options' => array(
'route'=>'/calendar/admin/user/add[/]',
'defaults'=>array('controller'=>'Calendar\Controller\User','action'=>'add')
)
),
//user edit
'admin_user_edit' => array(
'type'=>'segment',
'options' => array(
'route' =>'/calendar/admin/user/edit[/:id]',
'constraints' => array(
'action' => 'edit',
'id' => '[a-zA-Z0-9_-]+',
),
'defaults'=>array('controller'=>'Calendar\Controller\User','action'=>'edit')
)
),
//user profile
'admin_profile' => array(
'type'=>'segment',
'options' => array(
'route'=>'/calendar/admin/profile[/]',
'defaults'=>array('controller'=>'Calendar\Controller\Index','action'=>'profile')
)
),
'calendar' => array(
'type' => 'segment',
'options' => array(
'route' => '/calendar[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Calendar\Controller\Calendar',
'action' => 'index',
),
),
),
'event' => array(
'type' => 'segment',
'options' => array(
'route' => '/event[/:action][/:id][/:unixTime][/:allDay]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
'unixTime' => '[0-9]+',
'allDay' => '0|1',
),
'defaults' => array(
'controller' => 'Calendar\Controller\Event',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'calendar' => __DIR__ . '/../view',
),
),
);
and here is my controller action:
public function loginAction(){
//$this->layout('layout/login-layout.phtml');
$login_error=false;
$loginForm = new LoginForm();
if ($this->request->isPost())
{
$loginForm->setData($this->request->getPost());
if ($loginForm->isValid())
{
//die("dgdgdgdgdgdgdgdg");
$data = $loginForm->getData();
$authService = $this->getServiceLocator()
->get('doctrine.authenticationservice.odm_default');
$adapter = $authService->getAdapter();
$adapter->setIdentityValue($data['username']);
$adapter->setCredentialValue(md5($data['password']));
$authResult = $authService->authenticate();
//for disable authentication comment here////////////////////////////
if ($authResult->isValid()) {
$identity = $authResult->getIdentity();
//$authService->getStorage()->write($identity);
$this->redirect()->toRoute('admin_index');
}
else {
$identity =false;
$login_error= true;
}
//for disable authentication comment here////////////////////////////
}
}
//
return new ViewModel(array(
'loginForm' => $loginForm,
'login_error' => $login_error,
));
}
That error occurs when you forgot to make the actual for your view. You need to create that template and place it in the appropriate view directory. Then this error should go away.

Categories