编写自己的PHP框架,需要一些方法的意见/建议

时间:2011-01-28 05:24:22

标签: php object frameworks containers instance

在开始之前,这个框架并不意味着与Zend,Symfony,Cake或任何其他框架竞争。它主要是一个个人项目,所以我可以测试一些PHP 5.3好东西,体验新技术,让我有机会在我的想法下尝试。我也试图使这个框架尽可能轻量级,并减少不必要的getter和setter的数量。现在解决手头的问题。

完成了大部分框架,主要是运行所需的所有核心类。问题出现在应用程序的切入点上。我希望整个应用程序通过一个分支出来的单个核心对象运行。核心对象将通过类进行扩展,以管理环境,配置,注册表,自动加载,路由等等。您可以在下面看到这个“核心”对象,它恰当地称为应用程序。

https://github.com/titon/titon/blob/42c88e36c29e3d8c697306fe68be18b3a8fd2e70/titon/source/Infrastructure.php

$app = new \titon\source\core\Application();

我们的想法是,从应用程序的任何位置,您都可以通过此$ app变量访问核心对象。例如:

(我无法发布超过1个链接,所以请转到Github上的以下目录./app/config/Setup.php和/app/modules/core/Bootstrap.php)

$app->environment->current();
$app->loader->includePath(array(__DIR__));
$app->registry->factory('titon\source\system\Controller');

但是现在我们遇到了全局变量的问题,我不想使用它。我也想尝试避免单身人士。

public function foobar() {
    global $app; // Eww
}

但我也不想使用静态类,因为我试图采用更多的OOP方法。我能想到的唯一解决方案是使用静态类属性来保存Application实例并在任何地方访问它,但我不喜欢这样。或者我可以一遍又一遍地将物体传递给它的孩子,但又一次,不是粉丝。

Core::$app->router->detect(); // Meh
$this->setApplication($this); // Mehher

我很好奇Zend和Symfony是如何解决这个问题的。但在查看了他们的源代码后,我无法向后设计并确定正确的入口点。此外,似乎Zend会全面创建全局变量(Zend_Config等),但我更愿意拥有一个管理对象。 Symfony 2.0,我迷路了。至于Cake,Solar,Fuel,似乎他们正在为这类物体使用静态类。

现在我的主要问题是,您如何解决这个问题?我想保留一个对象来实例化并随处可访问,但这似乎不是一件容易处理的事情。如果需要,我愿意重写很多框架。

3 个答案:

答案 0 :(得分:1)

  

我们的想法是,从应用程序的任何位置,您都可以通过此$ app变量访问核心对象。例如:

...

  

但是现在我们遇到了全局变量的问题,我不想使用它。我也想尝试避免单身人士。

这似乎与我相矛盾。

你知道为什么你不想要任何全局变量?是因为你在某处看到全局变量是一件坏事吗?

相反,您是否知道为什么您想要一个可在应用程序中的任何位置使用的中心对象?

跟进

如果不清楚,那些就是修辞问题。从架构的角度来看,全局变量(任何形状)都是昂贵的。有人说邪恶。我认为这有点遗漏 - 你需要在任何应用程序中使用一些全局变量(至少一个)。为了进一步混淆水域,“全球化”真的是一个相对的东西;将变量视为具有不同的范围更为有意义,其中全局位于连续体的一个极端,而局部的临时变量位于另一个极端。如果你有一个包含所有其他对象的对象,那么我会将每个变量视为有效的全局变量,即使它们在技术意义上可能不是这样。想一想。

至于银弹,你可以看一下依赖注入。这是一种避免全局变量起作用的方法,但是以复杂的形式存在一些成本。

答案 1 :(得分:0)

PHP未解决的问题之一:如果不使用像runkit这样的扩展,就无法定义超全局。

我通常使用伪注册表解决这个问题,即我定义一个class R,其中包含我想要全局定义为public static $var的所有变量。我知道,这可能不是vanilla-OOP方法,但它很好用。我想,R::$var最短。其他所有内容,如依赖注入($this->var)或单例(R::getVar()),都会更长。

答案 2 :(得分:0)

避免全局变量的最佳解决方案是依赖注入。您可能需要创建一些容器。查看Symfony组件库。

您也可以尝试使用注册表模式。