2

I have a custom class that extends Pimple\Container. The idea was to wrap the, to my eyes, ugly methods for accessing defined services (see below):

offsetGet($key)       -> get($key)
offsetSet($key, $val) -> set($key, $val)
offsetExists($key)    -> has($key)

This idea worked fine for what i wanted to be able to do. i then went on to create an Application class that I chose INHERITANCE over AGGREGATION not for any particular reason than seeming to be logic.

The issue now is when I have a ServiceProvider that accepts an application instance instead of the Pimple\Container since I created my very own ServiceProviderInterface that defines this contract.

i realize now that assuming that Application was and still is a type of Container and have it use a different type of contract from the parent class wasn't a great idea. However, conceptually in my mind an application instance is some kind of a container because in it I have some key => value pair data stored.

I was thinking that Interface Segration principle would save my day but I am not sure.

  1. Could I have violated the Liskorv Substitution Principle here with my assumption with regards to the Application extends Pimple\Container relationship?

  2. Is there any way I can use my own Interface to register my service providers with stumbling on the error that whatever service I pass doesn't conform to the pimple\ServiceProvider contract?

In simply terms is it possible to extend Pimple's container and ignore the library's service provider and use your which defines the same contract but with different parameter?

scruffycoder86
  • 527
  • 1
  • 5
  • 24

1 Answers1

1

First of all,

The idea was to wrap the, to my eyes, ugly methods for accessing defined services

The ugly methods are from the ArrayAcess interface, which allows you to access properties in an array-like form:

$container = new Pimple();
$container['session_storage'] = function ($c) {
    return new SessionStorage('SESSION_ID');
};

$container['session'] = function ($c) {
    return new Session($c['session_storage']);
};

i then went on to create an Application class that I chose INHERITANCE over AGGREGATION not for any particular reason than seeming to be logic

This is just wrong. You should always choose Aggregation over Inheritance when it is possible.

Inheritance is a static tightly-coupled relationship and it is limited to only one in PHP. You can't change inheritance during runtime.

Composition, in the other hand, is a dynamic and could be losely coupled if implemented respecting the SOLID principles. You can perfectly switch relationships during runtime when using composition.

The issue now is when I have a ServiceProvider that accepts an application instance instead of the Pimple\Container since I created my very own ServiceProviderInterface that defines this contract.

This makes no sense! Why would you Service Provider depend on your application? Shouldn't it be the other way around? The provider is a self-contained module. Your application has several dependencies.

About your questions,

  1. The best way of knowing if you violated the LSP is to ask yourself:
    Can I substituite a Container object for an Application object without any loss in functionality?

  2. Nop. Interfaces are contracts and contracts should be honored.

Henrique Barcelos
  • 7,670
  • 1
  • 41
  • 66
  • Thanks for your detailed explanation on this issue. I have just spent some time studying the SOLID principles and the sad the sad thing is that when we are being introduced to Object Oriented Programming at school we are taught to program the bad way and then when in advance level you get to be taught Design Patterns and Principles which may help you become a better programmer. i will reconsider my design and maybe drop pimple but retaining the idea's behind it to build my own container. I will come back with a solution on to this. Thanks again. – scruffycoder86 Jul 21 '16 at 07:47