mtymek / expressive-config-manager

Lightweight library for merging and caching application config
30 stars 4 forks source link

Config provider refactor #1

Closed snapshotpl closed 8 years ago

snapshotpl commented 8 years ago

Thanks @mtymek for idea of this piece of code! Today I think about same solution similar to zend-modulemanager.

I think a little about you code and I see that's work, but it isn't enough flexible. I believe that my solution go to right way to make it very customizable and still lightweight. Example of usage:

$catchableProvider = new FileJsonCatchableConfigProvider(function(){
    $classNameConfigProvider = new ClassNameConfigProvider([
        ApplicationConfig::class,
        BlogConfig::class,
        SomeOtherConfig::class,
    ]);
    $configFileProvider = new ConfigFileProvider(Glob::glob('config/autoload/{{,*.}global,{,*.}local}.php', Glob::GLOB_BRACE));

    return new ChainConfigProvider([
        $classNameConfigProvider,
        $configFileProvider,
    ]);
});

$catchableProvider->getConfig();

Now it's very easy to change catch to simple array file or any other storage. You can easily add config-loading-strategy that fit your needs.

What are you think?

ping @weierophinney

mtymek commented 8 years ago

Honestly, I think it is too complex to use. I'd like to build something simple, at lest from the start. See #2 - I made it even simpler by removing ConfigProvider interface. While chaining and decorating providers looks flexible and powerful, I doubt if it will be practical in real-life scenario.

I'll try to come up with something more flexible than my initial solution, yet simpler.

snapshotpl commented 8 years ago

That's right, however we can close this "complex" logic into one simple object easy to use. Everybody wins

mtymek commented 8 years ago

See my new approach #3 - allows more flexibility, while keeping things simple and lightweight. I will update README file tomorrow.

snapshotpl commented 8 years ago

I don't get it, but no problem. It's independent so I can develop it on my own. Thanks anyway.

mtymek commented 8 years ago

To take your example: you wanted to load config from 3 classes and globbed configuration files. In my latest approach you would do it like this:

$configManager = new ConfigManager(
  [
      new GlobFileProvider('config/autoload/{{,*.}global,{,*.}local}.php'),
      ApplicationConfig::class,
      BlogConfig::class,
      SomeOtherConfig::class,
  ]
);

Same effect, with much simpler code to write.

Right now my class can accept 2 types of arguments:

Instead of returning arrays directly, config provider can return a generator. Generator is basically a way to return multiple configurations to be merged - see how I used it in GlobFileProvider:


namespace Zend\Expressive\ConfigManager;
use Zend\Stdlib\Glob;
class GlobFileProvider
{
    /** @var string */
    private $pattern;
    /**
     * @param string $pattern
     */
    public function __construct($pattern)
    {
        $this->pattern = $pattern;
    }
    public function __invoke()
    {
        foreach (Glob::glob($this->pattern, Glob::GLOB_BRACE) as $file) {
            yield include $file;
        }
    }
}

When using this approach, we gain one more thing: if there is a cache hit, no other IO operations are done. In my first approach (and in your version too) there was always a call Glob::glob(), even if cache exists.