5.5. 替换系统功能

前面的 Example1 例子向我们展示了如何为 bzfshop "增加功能",但有时候我们不只是要 "增加功能",我们甚至要 "替换系统已有功能",这种情况下我们需要去自己修改 bzfshop 的代码吗?

答案是不需要。bzfshop 的插件机制设计是提供无限可能性,你可以用插件实现任何功能,包括替代系统现有功能,下面就是 Example2 例子,我们打算用插件替换系统现有 /Goods/View 访问,改为我们自己的实现。Example2 的代码在这里 下载

首先你可以访问 http://…/Goods/View/goods_id-42107.html 看看商品详情页面是什么样子,然后安装 Example2 插件(安装参见:第 5.4.1 节 “安装插件”),再次尝试访问前面的链接,你会发现页面已经变化了,这就是插件 Example2 替换了系统默认的 /Goods/View 实现,采用了自己的实现。

5.5.1. 代码结构

前面的 Example1 只是一个简单的例子,我们也就简单来实现。从现在开始我们希望代码能够写的更加正规化,所以首先代码目录结构就应该正规起来,下面是 Example2 的目录结构:

图 5.4. 插件Example2目录结构

插件Example2目录结构

从上面的图可以看到,我们把代码都放在 Example 命名空间中(Controller/Example/Goods/View.php)这样不会和系统已有的 Goods/View.php 混淆。对应的 smarty 模板命名也前缀自己的命名空间 example_goods_view.tpl(防止和系统已有的 goods_view.tpl 名字冲突)。

5.5.2. 替换实现

我们采用自己的代码替换系统的实现,最关键的代码在 doShopAction() 中实现的,如下:

        /**
         * 为系统设置运行环境
         *
         * @return bool
         */
        private function doShopAction()
        {
            // 获取当前插件的根地址
            $currentPluginBasePath = dirname(__FILE__);

            // code 目录加入到 auto load 的路径中,这样系统就能自动做 class 加载
            SystemHelper::addAutoloadPath($currentPluginBasePath . '/shop/Code');

            // 增加 smarty 的搜索路径,这样才能找到我们的模板
            global $smarty;
            $smarty->addTemplateDir($currentPluginBasePath . '/shop/Tpl/');

            // 设置路由,我们这里替换系统的 /Goods/View 路由,让它指向插件的实现代码
            SystemHelper::addRouteMap(
                '/Goods/View',
                'Controller\Example\Goods\View'
            );

            return true;
        }

注意这里最关键的一段代码 SystemHelper::addRouteMap(…) ,我们在这里把路由 /Goods/View 映射到了我们自己的代码 Controller\Example\Goods\View 。于是当用户访问 http://…/Goods/View/goods_id-42097.html 的时候,bzfshop 会调用我们的代码实现,这样我们就成功的替换了系统原有的 商品详情页面。

[提示]

采用插件实现替换系统已有功能,而不是直接去修改 bzfshop 原有的代码。这样你可以很顺畅的跟随 bzfshop 一步一步升级,而不是把代码改得面目全非,然后再也无法升级只能自己苦逼的做维护了。