Coder Social home page Coder Social logo

sandrokeil / interop-config Goto Github PK

View Code? Open in Web Editor NEW
58.0 9.0 8.0 442 KB

Provides interfaces and a concrete implementation to create instances depending on configuration via factory classes with mandatory options check and ensures an uniform config structure.

Home Page: https://sandro-keil.de/blog/2015/09/08/php-interoperable-service-configuration/

License: Other

PHP 100.00%
php config interop service factory options configuration structure php7

interop-config's Introduction

Interoperability Configuration

You want to configure your factories?

You want to reduce your factory boilerplate code?

You want to check automatically for mandatory options or merge default options?

You want to have a valid config structure?

You want to generate your configuration files from factory classes?

This library comes to the rescue!

Build Status Scrutinizer Quality Score Coverage Status Latest Stable Version Total Downloads License

interop-config provides interfaces and a concrete implementation to create instances depending on configuration via factory classes and ensures a valid config structure. It can also be used to auto discover factories and to create configuration files.

  • Well tested. Besides unit test and continuous integration/inspection this solution is also ready for production use.
  • Framework agnostic This PHP library does not depends on any framework but you can use it with your favourite framework.
  • Every change is tracked. Want to know whats new? Take a look at CHANGELOG.md
  • Listen to your ideas. Have a great idea? Bring your tested pull request or open a new issue. See CONTRIBUTING.md

You should have coding conventions and you should have config conventions. If not, you should think about that. interop-config is universally applicable! See further documentation for more details.

Installation

The suggested installation method is via composer. For composer documentation, please refer to getcomposer.org.

Run composer require sandrokeil/interop-config to install interop-config. Version 1.x is for PHP < 7.1 and Version 2.x is for PHP >= 7.1.

Documentation

For the latest online documentation visit http://sandrokeil.github.io/interop-config/. Refer the Quick Start section for a detailed explanation.

Documentation is in the doc tree, and can be compiled using bookdown or Docker

$ docker run -it --rm -v $(pwd):/app sandrokeil/bookdown doc/bookdown.json
$ docker run -it --rm -p 8080:8080 -v $(pwd):/app php:7.1-cli php -S 0.0.0.0:8080 -t /app/doc/html

or run bookdown

$ ./vendor/bin/bookdown doc/bookdown.json
$ php -S 0.0.0.0:8080 -t doc/html/

Then browse to http://localhost:8080/

Projects

This is a list of projects who are using interop-config interfaces (incomplete).

Benchmarks

The benchmarks uses PHPBench and can be started by the following command:

$ ./vendor/bin/phpbench run -v --report=table

or with Docker

$ docker run --rm -it --volume $(pwd):/app prooph/php:7.1-cli-opcache php ./vendor/bin/phpbench run --report=table

You can use the group and filter argument to get only results for a specific group/filter.

These groups are available: perf, config, configId, mandatory, mandatoryRev and default

These filters are available: can, options and fallback

interop-config's People

Contributors

codeliner avatar dantleech avatar peter279k avatar sandrokeil avatar tobiju avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

interop-config's Issues

Create console tools to generate/display config based on factories

The factories provides all the stuff to generate config definitions from it. It would be really useful to have such a console tool.

  • Create a new configuration file with specific factory config
  • Update a configuration file with specific factory config
  • Dump a configuration file with specific factory config (copy & paste)
  • Ask for default values
  • Use previous value if nothing is entered (allows to update only specific options)
  • Display configuration for service / factory
  • Add unit tests
  • Add console commands to docs

[proposal] Naming proposal for option keys

Currently the AbstractConfigurableFactory requires getModule, getScope, getName.
I would like to suggest renaming this methods to:

  • getModule -> getVendorName
  • getScope -> getComponentName
  • getName -> getScope

Reasons

  • more explicit names
  • IMO the scope should be the third element, because you want to create for example a scoped command bus and have the following config structure:
    $config['vendor']['command_bus']['cli']

What do you think?

How to import shared settings from same vendor but different package?

How would the following work out?

Basically you have DefaultORMFactory and SecondORMFactory, both responsible for a different doctrine database connection (['doctrine']['connection']['orm_default'] and ['doctrine']['connection']['orm_second']). They share the same settings from ['doctrine']['orm'].

I understand from the docs how to get the orm connection settings. How would I import ['doctrine']['orm']?

<?php

return [
    'doctrine' => [
        'orm'        => [
            'auto_generate_proxy_classes' => false,
            'proxy_dir'                   => 'data/cache/EntityProxy',
            'proxy_namespace'             => 'EntityProxy',
            'underscore_naming_strategy'  => true,
        ],
        'connection' => [
            'orm_default' => [
                'driver'   => 'pdo_mysql',
                'host'     => '127.0.0.1',
                'port'     => '3306',
                'dbname'   => 'database1',
                'user'     => 'user1',
                'password' => 'one',
                'charset'  => 'UTF8',
            ],
            'orm_second' => [
                'driver'   => 'pdo_mysql',
                'host'     => '127.0.0.1',
                'port'     => '3306',
                'dbname'   => 'database2',
                'user'     => 'user2',
                'password' => 'two',
                'charset'  => 'UTF8',
            ],
        ],
        'cache'      => [
            'redis' => [
                'host' => '127.0.0.1',
                'port' => '6379',
            ],
        ],
    ],
];

Introducing HasDefaultOptions Interface

The configuration described in #8 Introducing HasOptionalOptions Interface has default options.

So why not have an interface which returns the options with default values?

namespace Interop\Config;

interface HasDefaultOptions
{
    /**
     * Returns a list of default options with their values
     *
     * @return string[] List of default options with their values
     */
    public function defaultOptions();
}

Implementation for the configuration looks like

public function defaultOptions()
{
    return [
        'metadata_cache' => 'array',
        'query_cache' => 'array',
        'result_cache' => 'array',
        'hydration_cache' => 'array',
    ];
}

This does not replace the HasOptionalOptions interface, because optional means null (not provided). I think the interface HasOptionalOptions and HasDefaultOptions can be combined.

For this feature the ConfigurationTrait must be updated with an extra interface check. What do you think?

All errors at once

This idea is from #38

Possibility to collect all errors if one error occured e.g. mandatory options or maybe even whole config structure.

Introducing HasOptionalOptions Interface

For auto discovery I think it's useful to have information about available options. Actually we have only a function mandatoryOptions which tells us what options must be provided. Optional options are missing.

Note that the ConfigurationTrait must not be changed.

Let's look at this example from DoctrineORMModule. All the options under the key orm_crawler are optional, but it's not visible in the factory.

'doctrine' => array(
        'configuration' => array(
            'orm_crawler' => array(
                'metadata_cache'    => 'array',
                'query_cache'       => 'array',
                'result_cache'      => 'array',
                'hydration_cache'   => 'array',
            ),
        ),
    ),
);

The HasOptionalOptions interface follows the same semantic like HasMandatoryOptions interface.

namespace Interop\Config;

interface HasOptionalOptions
{
    /**
     * Returns a list of optional options
     *
     * @return string[] List with optional options
     */
    public function optionalOptions();
}

What do you think?

Check order of default and mandatory options

Hello Sandro,

I've recently used this package on version 1.0 (because PHP 5.6 platform). Really cool and usefull, except in one condition.
I'll try to explain

When you use both mandatory and default conditions
If you provide default values and partially the mandatory options, you'll have an error raised, that is in my opinion un-necessary.

use Interop\Config\ConfigurationTrait;
use Interop\Config\RequiresConfig;
use Interop\Config\ProvidesDefaultOptions;

class SmartyRendererFactory implements RequiresConfig, ProvidesDefaultOptions
{
    // ... more code ...

    public function dimensions()
    {
        return ['view'];
    }

    public function defaultOptions()
    {
        return [
            'template_paths' => [
                getenv('BASE_DIR') . '/ProjectNamespace/View/Default',
            ],
            'smarty' => [
                'cacheDir'   => getenv('VAR_DIR') . '/view/cache',
                'compileDir' => getenv('VAR_DIR') . '/view/templates_c',
                'pluginsDir' => null,  // optional
            ]
        ];
    }
}


$settings = [
    'settings' => [
        // View settings
        'view' => [
            'template_paths' => [
                __DIR__ . '/ProjectNamespace/View/Default',
            ],
        ],
    ],
];

$container['view'] = function ($c) {
    $factory = new SmartyRendererFactory($settings);
    return $factory($c);
};

BASE_DIR and VAR_DIR all both defined

I recommand to inverse default and mandatory options in [1] version 1.0 but also 2.1 (that is also affected)

Laurent

[1] https://github.com/sandrokeil/interop-config/blob/1.x/src/ConfigurationTrait.php#L116-#L127

PhpUnit failure when testing a basic example

Hello,

I'm playing with that package, and I'm getting the following testing failure.

Would be great if someone could point me in the right direction on why the $config is not recognised.

by running $ phpunit interop-config/testing.php I'm getting the following output:

PHPUnit 7.1.3 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 160 ms, Memory: 4.00MB

There was 1 failure:

1) InteropTest::testIfcanRetrieveOptions with data set #0 (array(array(array(array('Doctrine\DBAL\Driver\PDOMySql\Driver', array('localhost', '3306', 'root', 'root', 'testing'))))))
Failed asserting that false is true.

/Users/****/PhpstormProjects/localhost.com/interop-config/testing.php:65
/Users/****/.composer/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:529
/Users/****/.composer/vendor/phpunit/phpunit/src/TextUI/Command.php:198
/Users/****/.composer/vendor/phpunit/phpunit/src/TextUI/Command.php:151

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

And this is the testing.php file:

<?php
declare(strict_types=1);

namespace {

    require_once __DIR__ . '/../vendor/autoload.php';

    class MyDBALConnectionFactory implements \Interop\Config\RequiresConfigId, \Interop\Config\RequiresMandatoryOptions
    {
        use \Interop\Config\ConfigurationTrait;

        public function __invoke(\Psr\Container\ContainerInterface $container)
        {
            // get options for doctrine.connection.orm_default
            $options = $this->options($container->get('config'), 'orm_default');

            // mandatory options check is automatically done by RequiresMandatoryOptions

            $driverClass = $options['driverClass'];
            $params = $options['params'];

            // create your instance and set options

            return $instance;
        }

        /**
         * Is used to retrieve options from the configuration array ['doctrine' => ['connection' => []]].
         *
         * @return iterable
         */
        public function dimensions() : iterable
        {
            return ['doctrine', 'connection'];
        }

        /**
         * Returns a list of mandatory options which must be available
         *
         * @return iterable List with mandatory options
         */
        public function mandatoryOptions() : iterable
        {
            return ['params' => ['user', 'password', 'dbname']];
        }
    }

    class InteropTest extends \PHPUnit\Framework\TestCase
    {
        /**
         * @dataProvider providerConfig
         */
        public function testIfcanRetrieveOptions($config)
        {
            $stub = new MyDBALConnectionFactory();

            self::assertTrue($stub->canRetrieveOptions($config));
        }

        public function providerConfig(): array
        {
            // interop config example
            $config = [
                // vendor name
                'doctrine' => [
                    // package name
                    'connection' => [
                        // container id
                        'orm_default' => [
                            // mandatory options
                            'driverClass' => \Doctrine\DBAL\Driver\PDOMySql\Driver::class,
                            'params' => [
                                'host' => 'localhost',
                                'port' => '3306',
                                'user' => 'root',
                                'password' => 'root',
                                'dbname' => 'testing',
                            ],
                        ],
                    ],
                ],
            ];

            return [
                [$config]
            ];
        }
    }
}

MySQL is up & running, and I tried to manually connecting to MySQL Server and it worked fine, so the issue is not there.

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.