Phalcon学习笔记(7)多模块

很多网站程序其实都需要有很多模块,比如客户访问的前台和管理员的后台就是大不相同的两个模块。诚然,用一个模块的Controller/Action也能实现类似功能,但是毕竟还是多模块用起来好。从Phalcon的启动顺序来看

https://docs.phalconphp.com/en/latest/reference/applications.html#manual-bootstrapping

其模块功能较弱。


实际上笔者亲身使用下来,感觉多模块做得不太好,不过既然有需要,还是要介绍一下的。


首先,为了开发的需要,文件和目录的结构有必要调整,这是官方文档中的一个案例

multiple/
  apps/
    frontend/
       controllers/
       models/
       views/
       Module.php
    backend/
       controllers/
       models/
       views/
       Module.php
  public/
    css/
    img/
    js/
首先入口文件仍然只有一个index.php,然后不同的模块放置在不同的目录,每个模块目录下有其对应的控制器、模型、视图目录,不过最重要的是每个模块目录下有一个Module.php文件。其实因为加载器的存在,除了Module.php必须以外,其他的目录其实都是可以随意放置的,只要在加载器中注册就好。


首先在入口的index.php文件中必须要有2个特殊的部分,一个是特殊的router路由器,这样才能识别模块。其实非常简单,就是把URL中对应模块的部分让路由器识别出来就ok了

$di->set('router', function () {
    $router = new \Phalcon\Mvc\Router();
    $router->notFound(array(
        'module' => 'entrance',
        'controller' => 'index',
        'action' => 'index',
    ));
    $router->add('/:module', array(
        'module' => 1,
        'controller' => 'index',
        'action' => 'index',
    ));
    $router->add('/:module/:controller', array(
        'module' => 1,
        'controller' => 2,
        'action' => 'index',
    ));
    $router->add('/:module/:controller/:action', array(
        'module' => 1,
        'controller' => 2,
        'action' => 3,
    ));
    $router->add('/:module/:controller/:action/:params', array(
        'module' => 1,
        'controller' => 2,
        'action' => 3,
        'params' => 4,
    ));
    $router->setDefaultModule('entrance');
    $router->setDefaultController('index');
    $router->setDefaultAction('index');
    return $router;
});
再一个就是要在Application启动类中注册模块

$application->registerModules(array(
        'entrance' => array(
            'className' => 'Multiple\Entrance\Module',
            'path' => ROOT_PATH . '/apps/entrance/Module.php',
        ),
        'backend' => array(
            'className' => 'Multiple\Backend\Module',
            'path' => ROOT_PATH . '/apps/backend/Module.php',
        ),
    ));


另外笔者推荐在设置DI和Application类之前设置一下加载器,主要是要注册不同的模块所对应的命名空间以及各个不同的Module所共同需要的类库。

$loader = new \Phalcon\Loader();
$loader->registerDirs(
    array(
        ROOT_PATH . '/apps/library/',
    )
)->registerNamespaces(
    array(
        'Multiple\Backend' => ROOT_PATH . '/apps/backend/',
        'Multiple\Backend\Controllers' => ROOT_PATH . '/apps/backend/controllers/',
        'Multiple\Backend\Controllers\Model' => ROOT_PATH . '/apps/backend/models/',
        'Multiple\Entrance' => ROOT_PATH . '/apps/entrance/',
        'Multiple\Entrance\Controllers' => ROOT_PATH . '/apps/entrance/controllers/',
        'Multiple\Entrance\Models' => ROOT_PATH . '/apps/entrance/models/',
    )
)->register();

这样Application类就可以找到各个不同的Module所对应的Module.php文件,在官方文档中这样说:当 Phalcon\Mvc\Application Module注册后,每个匹配的route都必须返回一个有效的module。注册的module都有一个相关的类,用于设置module本身提供的功能。每个module类都必须实现 registerAutoloaders() 和 registerServices() 这两个方法,Phalcon\Mvc\Application 将调用它们执行要执行的module


也就是说,我们必须要在Module.php文件中要声明这个类,然后实现registerAutoloaders() 和 registerServices() 这两个方法。类的声明很简单

class Module extends \Phalcon\DI\Injectable implements \Phalcon\Mvc\ModuleDefinitionInterface {}

如果特殊需求也不需要指定
extends \Phalcon\DI\Injectable
然后是registerAutoloaders()方法

public function registerAutoloaders(\Phalcon\DiInterface $dependencyInjector = NULL) {

        $loader = new \Phalcon\Loader();
        $loader->registerNamespaces(array(
            'Multiple\Entrance\Controllers' => __DIR__ . '/controllers/',
            'Multiple\Entrance\Models' => __DIR__ . '/models/',
        ))->registerDirs(array(
            __DIR__ . '/controllers/',
            __DIR__ . '/models/',
        ))->register();
    }
要注意,这个样例代码中给这个函数一个输入变量,默认值是NULL,也就是说它不是必需的。在Phalcon-1.3.x中是不需要这个变量的,在Phalcon-2.0.x中会需要,否则会出错,这似乎是一个bug,不过官方到2.0.2版本尚未解决。在这个函数中,主要就是设定一个该模块自己的加载器,在Application启动类加载完成各模块公用的文件之后,针对这个模块加载这个模块专用的文件。


然后是registerServices()方法

原则上讲,Application启动类中的依赖注入器DI不应该加载任何专属于模块的功能,而今应该加载公共的功能,比如config、session之类,而且还应该使用setShared()函数来注册。各模块专属的部分应该在各模块的Module.php中通过其专属DI来设定,而这个设定就是在registerServices()方法中完成的,所以说这个函数中的输入参数是必不可少的。

在这段样例代码中,对于数据库的部分就读取了公共DI中关于数据库的部分。

public function registerServices(\Phalcon\DiInterface $di) {
        //Registering a dispatcher
        $di->set('dispatcher', function () {
            $dispatcher = new \Phalcon\Mvc\Dispatcher();

            //Attach a event listener to the dispatcher
            $eventManager = new \Phalcon\Events\Manager();
            $eventManager->attach('dispatch:beforeDispatch', new \SecurityPlugin(__CLASS__));

            $dispatcher->setEventsManager($eventManager);
            $dispatcher->setDefaultNamespace('Multiple\Entrance\Controllers\\');
            return $dispatcher;
        });

        //Registering the view component
        $di->set('view', function () {
            $view = new \Phalcon\Mvc\View();
            $view->setBasePath(ROOT_PATH . '/apps/entrance/');
            $view->setViewsDir('./views/');
            $view->registerEngines(array(
                '.volt' => 'Phalcon\Mvc\View\Engine\Volt',
                ".phtml" => 'Phalcon\Mvc\View\Engine\Php',
            ));
            return $view;
        });
        //You can set a different connection in each module
        $config = $this->di->get('config');
        $di->set('db', function () use ($config) {
            $dbadapter = '\Phalcon\Db\Adapter\Pdo\\' . $config->database->adapter;
            return new $dbadapter(array(
                "host" => $config->database->host,
                "username" => $config->database->username,
                "password" => $config->database->password,
                "dbname" => $config->database->dbname,
                "options" => $config->database->options,
            ));
        });
    }

然后开发者就可以在各个不同的模块所注册的MVC目录里添加自己的代码了。在浏览器中访问

http://yourwebsite/module/controller/action/params

就可以访问各个模块的功能了。


要注意的是分发器不能跨模块跳转,如果想跨模块跳转,只能使用

$this->response->redirect('entrance/index/login');

而这会带来多一次的http访问,给服务器带来额外负担,具体可以由开发者权衡。


另外笔者实践检验,router有时会出错,如果开发者把url给全,而不是让router自动分配默认的Module/Controller/Action,可能会更稳妥一些。



Phalcon 中文文档 一般都是直接看英文资料,大都能看得懂。但看到Phalcon框架如此优秀,在学习后就想和大家分享,但发现国内的人几乎没有使用的,故想翻译一下,一旦翻译才发现读懂和译出一篇好文章真的不太一样。 故前一期翻译的部分章节有点生硬,等有空的时候再回头重译吧,后面的一部分也是以英文文档为基础,但并不再是逐句翻译了。 09年左右,大量的框架出现,我看过的框架不下20种,最先看到的可能就是php.MVC了,这是一个按照struts 1x编写的,只不过同时加载的类库太多了,效率不高而且不太完善。 后来稍有名的包括 cakephp, Symfony, Akelos, Prado, Kohana等,最近几年流行的就是 zf, yii, ci等,当然还有国内几个比较有名的框架,如fleaphp, thinkphp等。 在上面的一些框架中,我比较感冒的还是ci,yii,thinkphp等。ci,thinkphp够简单,速度也不错。yii是生活在国外的华人开发,功能够全而强大,速度也不错,国内的应用也不少。 一直不太喜欢zf,记得几年前就和同行朋友聊天的时候说,像ZEND公司完全可以用C语言开发出一个扩展来,这样效率会高得多,为毛非得用PHP开发呢,事实被我验证了,但开发扩展的不是ZEND公司,而是国内一个PHP大鸟,人称鸟哥。这个框架就是非常出名的YAF,因此YAF扩展是我必装的扩展之一。同时这也是我发现的第一个C语言写的扩展框架。 但YAF的缺点是,功能非常不完善,在我看来只是简单实现了MVC结构及路由,分发等功能,像一些ORM之类的功能完全没有开发,作者好像也没有开发的意思:) 后来就发现了Phalcon,一看文档就爱上了她,功能,速度等都是我想要的,我花了一周时间看文档学习她,并在一个下午的过程中,发现了文档中的三个错误并提交了这些错误:),我决定为完善它也贡献一点自己的力量。 本文档的中文地址存放在 http://phalcon.5iunix.net Github上的地址为: https://github.com/netstu/phalcondocs ,您如果发现有些地方译的有些操蛋,烦请你fork它,并完善她。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值