开发者

Why common PHP frameworks use a central Core?

Is it just comfy or there are other purposes on having a main central core?

Why they do

    $core->A->do();
    $core->B->do();

instead of

    $A->do();
    $B->do();

And leave it all to the classes to handle 开发者_如何学Gotheir needs? Also there'll not be a big object once we load different classes inside it.

To get in the real problem: I'm currently using the Dependency Injection pattern to give the classes some things they need, but I'm also asking myself if wouldn't be better if that all the classes can have access the resources (configs, for example) without calling the core each time they need them.

Sort of this

MyClass

    $myclass->get_configs();    // get my configs
    $myclass->do_stuff($this->my_configs);    // use them

instead of this

MyCore

    $myclass_configs = $this->config->get('configs_for_myclass');    // get configs
    $this->myclass = new MyClass($myclass_configs);    // call the function and give it the configs

Wouldn't this avoid the need of a big core and, also, decentralize everything? Or its just freakin' heavy mind-masturbation?

Edit: corrected a typo.


I am the owner and mantainer of the Alloy HMVC Framework, and I chose to have a core "Kernel" object as you describe for a few main reasons:

It's Useful as a Factory

Having a central core object that you use to get and load other objects eliminates the need for other people to know the dependencies of other objects they might need to use in your framework. For example, a typical user just knows they want to use the Router, but they don't want to have to build it themselves each time they want to use it.

Users would rather write:

$router = $kernel->router();

Than something like:

$router = new SomeFramework\Http\Router(new SomeFramework\Http\Request());

Or:

$router = SomeFramework\Http\Router::getInstance();

Instance Management

A central core object can also ensure that objects don't get instantiated multiple times when it's not necessary. It's usually not necessary for objects like Request, Response, Router, Session, etc. to have multiple instances.

So a call to retrieve a Request instance like this:

$request = $kernel->request();

Will automatically create and instantiate a new Request object on the first call, and then use a simple class-level cache to store the instance for use on subsequent calls to reduce overhead.

Simplifies Dependency Handling

A central core or kernel object can also be useful to simplify dependency handling within the framework itself (usage as a Service Locator). Instead of having to know object inter-dependencies up front, you just pass the core object and know that anything needed can be retrieved directly from it. This is especially useful in frameworks, because you never know what users will want to do within their controllers. You just provide them a central core object, and they can pull anything they need from it. It's worth saying that this Service Locator style approach does come with the known caveat of creating dependencies on the Service Locator itself by all the objects that use it. The drawback is a tradeoff you may or may not want to live with, but it vastly simplifies user-level code, so it's one I chose to make.

Provides a Central Extension Point

One of the nice things about having a central object exist and be passed around everywhere (and available within any Controller) is that it provides a natural common extension point. Alloy lets users add their own methods on the Kernel object that are proxied through the __call magic function:

$kernel->addMethod('bark', function() { echo 'Woof!'; });

Which allows you to use it anywhere within the application that the Kernel is available:

$kernel->bark(); // echos 'Woof!'

This provides a nice way for things like plugins to provide custom functionality or create their own factory methods on the kernel for helper object creation, etc. without having to create a whole new plugin architecture to support it.

Regarding Class Configuration

Regarding your question on why you wouldn't want to do this:

$myclass->get_configs();    // get my configs
$myclass->do_stuff($this->my_configs);    // use them

Instead of this:

$myclass_configs = $this->config->get('configs_for_myclass');    // get configs
$this->myclass = new MyClass($myclass_configs);    // call the function and give it the config

Is because of two main reasons:

(1) Repetitious functionality across all classes for "get_config". To keep the code DRY, you would end up having to make all your classes derive from a common base class, which would most likely constitute inheritance abuse and deepen your class hierarchy.

(2) When you make multiple method calls on the object, it would be tedious and ugly to pass in the configs every time, i.e.:

$myclass->do_stuff($this->my_configs);
$myclass->do_other_stuff($this->my_configs);
$myclass->do_more_stuff($this->my_configs);

It is much nicer to instantiate the object with configuration once:

$myclass = new MyClass($myclass_configs);
$myclass->do_stuff();
$myclass->do_other_stuff();
$myclass->do_more_stuff();

And since that configuration has to come from somewhere and you don't necessarily want your users having to type it all out or hardcode it somewhere else, you just have them pull it out of the common core object because it's already loaded the common configuration file that is used across the whole application.


They might be doing it to reduce the number of things in the global namespace, so instead of having hundreds of class names you can't use, there's only one.


I think part of the reason is because if you do $core->A as opposed to $A, then $core->A can be lazy loaded only when you request it.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜