开发者

Writing my own PHP framework, need some opinions/suggestions on an approach

Before I begin, this framework is not meant to compete with Zend, Symfony, Cake or any other framework. It is primarily a personal project so that I may test out some PHP 5.3 goodies, experience new techniques and gives me the chance to try things under my idea. I am also trying to make this framework as lightweight as possible, and reduce the amount of unncessary getters and setters. Now for the problem at hand.

A bulk of the framework is done, primarily all the core classes required for it to run. The problem arises on the entry point of the application. I want the whole application to be run through a single core object which branches out. The core object will be extended with classes to manage environments, configuration, registry, autoloading, routing, etc, etc. You can see this "core" object below, it is aptly called Application.

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

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

The idea was that from anywhere in the application, you can access the core objects through this $app variable. Example:

(I cant post more than 1 link, so please go to the following directories on Github. /app/config/Setup.php and /app/modules/core/Bootstrap.php)

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

But now we get into the problem of global variables, which I do not want to use. I also like to try and avoid Singletons.

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

But I also do not want to use static classes, as I was trying to go for a more OOP approach. The only solutions I can think of is using a static class property to hold the Application instance and access that everywhere, but I do not like that. Or I can pass the object down to its children over and over again, but again, not a fan.

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

I was curious how Zend and Symfony approached this problem. But after looking through their source code, I could not backwards engineer and determine the correct entry point. Furthermore, it seemed Zend would created global variables all over (Zend_Config, etc), but I would prefer to have a managing object. Symfony 2.0, I just got lost. As for Cake, Solar, Fuel, it seems they are using static classes for these kind of objects.

Now my primary question is, how would you solve this? I would like to keep a single object to instantiate and be acce开发者_StackOverflow社区ssible everywhere, but it doesn't seem like an easy thing to handle. I am willing to rewrite a lot of the framework if need be.


The idea was that from anywhere in the application, you can access the core objects through this $app variable. Example:

...

But now we get into the problem of global variables, which I do not want to use. I also like to try and avoid Singletons.

That seems like a contradiction to me.

Do you know why you don't want any global variables? Is it because you read somewhere that global variables are a bad thing?

Conversely, do you know why you want a central object that is available from anywhere in your application?

Follow Up:

In case it wasn't clear, those were meant as rhetorical questions. From an architectural viewpoint, global variables (in any shape) are expensive. Some say evil. I think that's missing the point slightly - You need some amount of global variables in any application (At least one). To further muddy the waters, "global" is really a relative thing; It is much more meaningful to consider variables as having varying scopes, where global is on one extreme of the continuum and local, temporary variable at the other. If you have a single object containing all your other objects, then I would consider each of these variables as being effectively global variables, even though they may not be so in a technical sense. Think a bit about that.

As for a silver bullet, you could take a look at dependency injection. This is an approach to avoiding global variables that works, but has some cost in the form of complexity.


One of PHP's old unresolved issues: One can't define superglobals, without using a extension like runkit.

I usually solve this with a pseudo-Registry, i.e. I define a class R with all variables I want to make global defined as public static $var. I know, this is probably not the vanilla-OOP approach, but it serves well. R::$var is as short as it get, I think. Everything else, like dependency injection ($this->var) or singleton (R::getVar()), is longer.


The best solution to avoid global variables is dependency injection. You'll probably need to create some container. Look at the Symfony components library.

You may also try registry pattern.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜