用Phalcon命名空间 [英] Namespaces with Phalcon

查看:87
本文介绍了用Phalcon命名空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我所有的控制器都在名称空间MyApp\Controllers下,因此,按照文档建议,我已将其默认名称空间设置为:

All my controllers are under the namespace MyApp\Controllers so, as the documentation recommended, I've set my default namespace to it:

$dispatcher->setDefaultNamespace('MyApp\Controllers');

但是现在,我不仅需要在文件夹中组织我的控制器,还需要为其命名空间,并具有友好的URL,例如:/features/featureX//wizards/featureX/.因此,从该示例中,我得到了MyApp\Controllers\Features\FeaturesXMyApp\Controllers\Wizards\FeaturesX.

But now I need to not only organize my controllers in folders but also namespace them and have friendly URLs like: /features/featureX/ and /wizards/featureX/. So from that example I got MyApp\Controllers\Features\FeaturesX and MyApp\Controllers\Wizards\FeaturesX.

我认为不应将它们视为模块,对吗?它们只是一些自定义路由,但是从路由文档中,我不知道如何:

I believe that they shouldn't be considered modules right? They're just some custom routes, but from routing documentation I can't tell how to:

  • 声明仅定义名称空间的路由(例如$router->add("/:namespace", ["namespace" => 1]);)
  • 使上述路由策略仅用于某些控制器.例如,LoginController应该保留在MyApp\Controllers命名空间中.
  • Declare a route that only defines the namespace (e.g $router->add("/:namespace", ["namespace" => 1]);)
  • Make the above routing strategy be used for only some controllers. For example, LoginController, should remain in the MyApp\Controllers namespace.

也许我可以通过为每个路由器或调度程序使用一个路由器或调度程序来实现.任何经验丰富的Phalcon开发人员都可以在这里给我一个亮点吗?!

Maybe I can achieve this by using one router or dispatcher for each one. Any experienced Phalcon developer could please give me a light here?!

推荐答案

好吧,在使用Phalcon一段时间后,我可以说,有时候当您决定使用与项目中发现的方法不同时,它并不那么灵活文档.使用命名空间就是其中一种情况.

Well, after a some time using Phalcon I can say that sometimes it is not so flexible when you decide to use a different approach from those we found in the project documentation. The use of namespaces is one of these cases.

该框架不能很好地处理多个名称空间级别,但是它仍然设计合理且可扩展.您可以覆盖几乎所有内容,并通过进行一些自定义,可以实现所需的任何行为.

Multiple namespace levels aren't handled very well by the framework, however it still well designed and extensible. You can override pretty much anything and, with a some customization, you can achieve any behavior you want.

以下是我所做的一切,以将所有内容整理在文件夹/命名空间中,并且仍然使用整个框架.

The following is what I've done to get all my stuff organized in folders/namespaces and still make use of the whole framework.

其中一些信息可能对您有用,因此这里是迄今为止我传奇之旅的报告...

Some of these information may be useful in your context, so here is a report of my legendary journey so far...

好的,因此,如果您决定将PHP源代码保持在文件夹和命名空间中,请准备好调整几乎所有主要功能,并在实现中更明确地做到(更多)(例如,使用完整的类路径).

OK, so if you decide to keep your PHP source code organized within folders and namespaces, get ready to tweak almost all the major functionalities and also to be much more explicit in your implementations (i.e use full class paths everywhere).

基本上,您将放弃框架必须提供的一些最酷的自动化功能,因为它们是基于约定的,而这些约定似乎在定义时就没有命名空间.

Basically you're going to throw away some of the coolest automation that the framework has to offer because they're are convention based and these conventions seems to be defined without namespaces in mind.

但是,尽管还有很多额外的工作要做,但我还是决定保留这个设计决定.毕竟,出于某种原因,我们选择了MVC框架,对吗?我们要使事情井井有条.特别是在大型项目中,将源代码稀释到几个命名空间/文件中以提高可维护性非常重要.

But, despite all this extra work ahead, I've decided to keep this design decision; After all, we'd chose a MVC framework for a reason, right?! We want to keep things organized. Specially in huge projects where is very important to have the source diluted in several namespaces/files to improve maintainability.

首先,您应该了解我选择的目录结构,以了解下面我在说什么.相信我,我花了数小时的时间来调整此结构,并阅读其他MVC框架推荐的结构,毕竟我个人的建议很简单:选择问题较少的对象!通常,这意味着解耦/碎片化程度更高.

First off, you should be aware of the directory structure I've picked to understand what I'm talking about down below. Believe me, I've spent some hours days tweaking this structure and reading about structures recommended by other MVC frameworks and after all my personal recommendation is very simple: pick the less problematic one! Generally this means the more decoupled/fragmented one.

这是我目前正在使用的结构,已经为我服务了近两年了,并且适合我需要使用的任何类型的代码:

This is the structure I'm currently using which served me well for almost two years now and fits whatever kind of code I need to throw at it:

对目录/命名空间结构的清楚理解消除了在实现新内容时的大量猜测工作,并有助于您无意间编写解耦的代码.如果您一开始就浪费"一些时间来关心这一点,那么将来对您的重构就不会那么痛苦了.

A clear understanding of your directory/namespace structure removes a considerable amount guesswork while implementing new stuff and helps you to write decoupled code unwittingly. If you "waste" some time caring about this in the beginning this means less painful refactors for you in the future.

您是否注意到source/文件夹,它的内容或多或少地组织为 PSR标准有要求吗? 原因是 Phalcon的类加载器为PSR-0符合

Did you noticed the source/ folder and it's contents organized more or less as the PSR Standards demands?! The reason for this is that the Phalcon's Class Loader is PSR-0 compliant;

所以基本上我只需要将source/文件夹注册到加载器中即可.

So basically I just need to register only the source/ folder into the loader:

$phLoader = new PhLoader();
// Considering the public folder as your current __DIR__
$phLoader->registerDirs(['../source/']);
$phLoader->register();

...瞧!您只需引用该类(在需要时使用完整路径),PHP和Phalcon内部实现都可以找到它.例如,要在我的DI容器中注册我的组件之一:

...and voila! You simply refer to the class (using the full path when needed) and both PHP and Phalcon internal implementations will find it. For example, to register one of my components in my DI container:

// At the first time the service 'foo' is needed
// Phalcon will read the file at 'source/MyApp/Components/Foo.php'
// and then call Foo's constructor
$di->set('foo', 'MyApp\Components\Foo'); 


路由器和控制器

如果所有控制器都在同一个名称空间/文件夹中,则只需执行以下操作:


Router and Controllers

If all your controllers are on the same namespace/folder you can simply do this:

$router->setDefaultNamespace('MyApp\Controllers');

很好!

但是如果您在MyApp\Controllers\Foo\BarController下有一个控制器怎么办?!

But what if you have a controller under MyApp\Controllers\Foo\BarController?!

就像默认的加载程序行为一样,路由器也没有尝试将Foo部分解释为另一个命名空间级别.

Just like the default loader behavior, there's no effort from the router to try to interpret the Foo portion as another namespace level.

ATTOW没有使路由器在更深的"名称空间中找到控制器的解决方法.到目前为止,我的解决方案是关闭默认路由行为并为每个命名空间分支手动添加四种常见模式.

ATTOW there's no workaround to make the router to find controllers in "deeper" namespaces. My solution so far is to turn off the default routing behavior and add manually the four common patterns for each namespace branch.

四种常见模式"指的是这些路线:

By "four common patterns" I mean these routes:

:namespace/index/index 仅定义名称空间时

:namespace/:controller/index/ 仅定义名称空间和控制器名称时

:namespace/:controller/:action/ 定义名称空间,控制器和操作名称时

:namespace/:controller/:action/:params 定义所有内容并包含参数时

要为所有名称空间启用这些路由,我已将:namespace regex占位符替换为与所有可能的名称空间匹配的另一个regex,并实现了将路径转换为正确名称空间的转换器"(即"/foo/bar/baz-> ['namespace' => 'MyApp\Controllers\Foo', 'controller' => 'bar', 'action' => 'baz']).

To enable these routes for all namespaces I've replaced the :namespace regex placeholder with another regex that matches all possible namespaces and implemented a "converter" that translates the route to the correct namespace (i.e "/foo/bar/baz" --> ['namespace' => 'MyApp\Controllers\Foo', 'controller' => 'bar', 'action' => 'baz']).

仅为了说明我在说什么,这是我前一段时间编写的使用此技术的自定义路由器: https://gist.github.com/snolflake/9797835

Just to illustrate what I'm talking about here's a custom router that I've write some time ago and uses this technique: https://gist.github.com/snolflake/9797835

您必须遵循文档中所说的内容.这意味着,只要您在 PHQL 上引用模型(或关系定义),您需要始终使用完整的类路径.

You must follow what the docs say. That means, any time you refer to a model on PHQL (or relationship definitions) you need to always use the full class path.

按视图,我的意思是基本上是模板文件.当然,它们不在名称空间下,但是由于您的控制器在其中,因此自动视图选择无法正常工作.因此,应该手动选择您的视图:

By views I mean basically the template files. Of course they aren't under namespaces, but since your controllers are, the automatic view picking doesn't work properly. So your views should be picked manually:

namespace MyApp\Controllers\Foo;

class BarController
{
    public function bazAction()
    {
        // The path is relative to the views dir you've set before
        $this->view->pick('configurations/subscriptions/index.volt')
        ...

很高兴您可以使用事件 beforeExecuteRoute 以根据您自己的约定自动选择视图.

Gladly you can make use of the event beforeExecuteRoute to automatically pick the view based on your own conventions.

Phalcon似乎将目标更多地放在了简单/琐碎的项目中,但这是完全合理的,即使使用所有这些样板代码来使您的应用程序更加精美,框架的其余部分本身也值得以后再做.

It seems that Phalcon is aiming more in simple/trivial project, but that's perfectly reasonable and even with all these boilerplate code to get your application more fancy the rest of the framework itself make it all worth the job later on.

同时,我只希望下一个版本包含更多名称空间友好的功能.

Meanwhile I just hope that next versions include more namespace-friendly features.

这篇关于用Phalcon命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆