-
Notifications
You must be signed in to change notification settings - Fork 2
Tutorial.Navigation and Custom Navigation.zh_cn
- 导航实现机制
在Pi Engine里,导航的相关数据都保存在数据库里,这种数据保存的方式也为用户自定义导航提供了可能。在安装的数据表里,可以看到有core_navigation和core_navigation_node两个表,它们分别用来保存导航的基本信息和导航具体内容。如果用户修改了导航的内容,core_navigation_node表里的data字段也被相应地修改。
图6-1 数据表中的导航数据
模块的导航定义在config目录下的navigation.php文件中,因此模块的导航将在模块安装的时候被写入数据库,通过配置实现的导航主要有三种方式:
- 配置固定导航
- 配置由代码定义的导航
- 配置后台自定义的导航
其中固定导航在模块安装完后就不能修改了,如果要修改,需要更改navigation.php里的配置,然后重新安装模块;由代码定义的导航可以安装完后通过更改代码实现导航更改;后台自定义导航也可在安装完后自定义导航,但自定义需要在后台完成。
在主题和区块一章我们介绍了页面主题模板的概念,而导航的定义也是在主题模板里完成。在theme/{theme name}/template目录下,会看到有layout-front.phtml和layout-admin.phtml两个文件,它们分别定义了前后台的页面模板。在模板里我们可以看到如下代码:
图6-2 实现导航的代码
在主题模板的代码里,调用了Pi Engine的helper - nav(),这个helper会从数据库里读取出对应的系统前台或后台的导航数据,并读取出模板的导航合并到总的导航里。最后实例化Zend\Navigation\Navigation类来处理这些数据。
Zend\Navigation\Navigation类是Zend封装好的用于操作导航的类,它可以为导航定义样式,同时也可以输出面包屑。
若导航存在,则引用CSS样式menu.css,并为导航设置样式。
在这一章里,我们将介绍模块导航的定义,主要包括三个方面:
- 固定导航
- 代码控制导航自定义
- 后台控制导航自定义
- 固定导航
导航的定义也需要添加配置,在模块安装的时候,导航数据就会被写进数据库。对于固定导航只需要添加配置即可,这里同样以member模块为例,我们为member模块的前后台分别添加导航。
在config目录下创建navigation.php并添加如下代码:
路径:usr/module/member/config/navigation.php
Code 6.2.1
<?php
return array(
'front' => array(
'pagea' => array(
'label' => __('Registration'),
'route' => 'default',
'controller' => 'register',
'action' => 'index',
),
'pageb' => array(
'label' => __('Having Sub-pages'),
'pages' => array(
'pageba' => array(
'label' => __('Login'),
'route' => 'default',
'controller' => 'login',
'action' => 'login',
),
'pagebb' => array(
'label' => __('Edit'),
'route' => 'default',
'controller' => 'profile',
'action' => 'edit',
'params' => array(
'id' => 1,
),
),
),
),
'pagec' => array(
'label' => __('EEFOCUS'),
'uri' => 'http://www.eefocus.com',
),
),
'admin' => array(
'pagea' => array(
'label' => __('List Member'),
'route' => 'admin',
'controller' => 'account',
'action' => 'list',
),
'hidden' => array(
'label' => __('Hidden'),
'visible' => 0,
),
),
);
在navigation.php配置里,我们为member模块的前台定义三个导航项,同时对第二个导航项创建了两个子导航项,而为member后台也创建也两个导航项。在代码里,以front和admin字段来区分前后台导航;每个导航项的信息都保存在一个数组里,如pagea, pageb, pagec等,对于导航项,如果有子项,则以pages字段定义,在pages数组里同样以一个数组定义一个导航项,如代码中pageb导航项下有两个子项:pageba和pagebb。前台导航最多可定义三级导航,而后台目前只支持一级。保存导航信息的数组里的字段定义如下:
- label: 为导航项上显示的名称;
- route: 为这个导航项要用到的路由名称,前台默认路由为default,后台为admin;
- controller: 这个导航要请求的controller类;
- action: 导航要请求的action方法;
- params: 组装路由时要带的参数,对于pagebb,就是指请求时带id值为1的参数;
- uri: 若请求不是Pi系统的页面,那么只能直接使用url了,写在这个字段里,也就是pagec将会链接到www.eefocus.com页面;
- visible: 定义该导航项是否可见,0为不可见,即hidden导航项将不会在导航上显示。
这样,前后台的固定导航就创建完成了,若需要修改导航,在更新完navigation.php后就必须得重新安装模块。当然现在我们还得告诉系统,模块需要添加navigation配置:
路径:usr/module/member/config/module.php
Code 6.2.2
<?php
return array(
...
'maintenance' => array(
'resource' => array(
...
'block' => 'block.php',
'navigation' => 'navigation.php',
),
),
);
重新安装模块后,在前后台将会看到如图6-3所示的导航效果:
(a)
(b)
图6-3 member模块前后台固定导航效果
- 代码控制导航自定义
代码控制导航自定义就是指在navigation.php配置里,为相应的导航项添加回调函数的字段,之后在模块里就可以添加相应的类来操作导航,采用这种方式操作导航,在导航安装完后,每次更改导航的时候,不需要去修改navigation.php配置,并重新安装模块,更方便操作。
现在我们在导航配置里新加一个测试导航项,用于代码控制,如下修改navigation.php:
路径:usr/module/member/config/navigation.php
Code 6.3.1
<?php
return array(
'front' => array(
...
'pagec' => array(
'label' => __('EEFOCUS'),
'uri' => 'http://www.eefocus.com',
),
'test' => array(
'label' => __('Custom Nav by Code'),
'callback' => array('navigation', 'changeFrontNav'),
//'callback' => 'Module\Member\Navigation::changeFrontNav',
),
),
...
);
上述代码里,添加了一个导航项test,并用callback字段表明这个导航项为代码控制的。callback的值就是指要调用哪个类的哪个方法来自定义导航,代码中提供的两方式在member模块里效果一致,也就是Navigation类的changeFrontNav()方法。完成之后需要重新安装member模块,在前台就可以看到导航项,但导航没任何链接。
- 自定义添加子项
接下来我们需要创建Navigation类来自定义这个导航项,在src目录下创建Navigation.php并添加如下代码:
路径:usr/module/member/src/Navigation.php
Code 6.3.2
<?php
namespace Module\Member;
class Navigation
{
public static function changeFrontNav($module)
{
$nav = array(
'pages' => array(
'testa' => array(
'label' => __('Test 1'),
'uri' => 'http://www.test1.com',
),
'testb' => array(
'label' => __('Test 2'),
'uri' => 'http://www.test2.com',
),
),
);
return $nav;
}
}
在Navigation类里,我们定义了一个公有静态方法changeFrontNav(),这个方法也是navigation配置里指定的回调函数,方法的参数固定为$module,也就是当前模块名。在方法里我们定义了一个$nav数组,并在数组里定义了pages字段来为test导航项添加两个子导航项,最后将$nav数组返回。也可以这样理解,$nav里定义的字段会合并到navigation配置的test数组里,因此test数组的最终形式和pageb类似:
'test' => array(
'label' => __('Custom Nav by Code'),
'pages' => array(
'testa' => array(
'label' => __('Test 1'),
'uri' => 'http://www.test1.com',
),
'testb' => array(
'label' => __('Test 2'),
'uri' => 'http://www.test2.com',
),
),
),
因为目前系统为导航设置了缓存,因此要查看效果需要去后台清除缓存,进入前台强刷页面后可看到自定义的效果如图所示:
图6-4 自定义导航子项
- 将自定义项替换上一级导航项中
我们还可以将自定义的子导航项替换其父级导航,方法就是使用parent字段,将上述$nav数组修改为如下代码:
路径:usr/module/member/src/Navigation.php
Code 6.3.3
<?php
...
$nav = array(
'parent' => array(
'testa' => array(
'label' => __('Test 1'),
'uri' => 'http://www.test1.com',
),
'testb' => array(
'label' => __('Test 2'),
'uri' => 'http://www.test2.com',
),
),
);
....
这种方式相当于把test导航项替换成testa和testb导航项,也就是现在testa, testb和pagea, pageb等平级了,导航的效果如图所示:
图6-5 自定义项替换其父导航项
- 子项插到父导航项前后
另外还可以使用position字段让子项插到父导航项的前面或后面,其代码如下:
路径:usr/module/member/src/Navigation.php
Code 6.3.4
<?php
...
$nav = array(
'parent' => array(
'position' => 'before',
'pages' => array(
'testa' => array(
'label' => __('Test 1'),
'uri' => 'http://www.test1.com',
),
'testb' => array(
'label' => __('Test 2'),
'uri' => 'http://www.test2.com',
),
),
),
);
...
这种方式的效果如图所示:
图6-6 将子项插到父导航项前
- 后台控制导航自定义
Pi Engine还支持通过后台配置来自定义导航,通过方式的导航配置,用户可以在后台对导航项进行更改和定制,同时可以选择安装哪一个导航,对于没有代码开发经验的网站管理员,这种方式能很方便地帮助他们完成想要的效果。
后台导航的自定义可以直接在后台添加,也可以在navigation.php配置里完成,这里重点介绍配置navigation的方法。打开config/navigation.php并将代码作如下修改:
路径:usr/module/member/config/navigation.php
Code 6.4.1
<?php
return array(
'meta' => array(
'member' => array(
'title' => __('Custom member navigation for training'),
'section' => 'front',
),
),
'item' => array(
'admin' => array(
'pagea' => array(
'label' => __('List Member'),
'route' => 'admin',
'controller' => 'account',
'action' => 'list',
),
),
// Custom navigation
'member' => array(
'pagea' => array(
'label' => __('Registration'),
'route' => 'default',
'controller' => 'register',
'action' => 'index',
),
'pageb' => array(
'label' => __('Having Sub-pages'),
'pages' => array(
'pageba' => array(
'label' => __('Login'),
'route' => 'default',
'controller' => 'login',
'action' => 'login',
),
'pagebb' => array(
'label' => __('Edit'),
'route' => 'default',
'controller' => 'profile',
'action' => 'edit',
'params' => array(
'id' => 1,
),
),
),
),
'pagec' => array(
'label' => __('EEFOCUS'),
'uri' => 'http://www.eefocus.com',
),
),
),
);
在navigation配置里,用meta字段标识这是自定义导航,并在meta数组里定义了导航的基本信息,其中member为导航名,也就是唯一名称,这个名字的定义需要注意,不要和系统里所有模块的自定义导航重名。
而导航的内容都放在item数组里,对于固定导航仍然以admin或front来标识,数组里内容的定义和前面介绍的一致;对于自定义导航,就要以导航的唯一名称来标识,这里也就是member字符串,member数组里的导航定义也和前面介绍的一致。
这种自定义出来的导航,各导航就是横向排列,而不像固定导航里那样,一个模块只在导航里占一格。定义完成后,还需要到后台安装导航才能显示,如图所示。
图6-7 后台导航安装界面
安装完后到前台就可以看到自定义的导航了,如果没有显示,可到后台清空下缓存后再强刷页面。
图6-8 前台自定义导航
当然,自定义的导航也可以在后台作修改,方法就是先点击Clone克隆一份,再编辑导航。