11

I am coming from C# and I am struggling to work out the PHP way of making my code extensible.

Lets say for instance I have a function that calculates my recommended daily allowance of food intake. It looks at vitamins, calories, minerals etc...

I want to have lots of different food objects that I use in my application and different functions that look at different aspects of food so I implement a IFoodNutrition interface and make my food classes that I want to be compatible with my function implement it. I then declare that my function takes it as an arg

function GetRda(IFoodNutrition $food){}

In C# I would specify all of the properties that I need to use in the interface so I know any class that implements this will be compatible with this function.

What is making my head hurt is that PHP only allows method signatures in interfaces.

My problems is obviously the paradigm shift. I am not sure what the equivalent pattern is in PHP. I have read the documentation and I can't see the like for like alternative unless you inherit from an abstract class but then you can only inherit from one class so that doesn't work the same way.

As PHP isn't typesafe I don't have to create the interface. Someone can just send any object to the method and if it has the properties needed in the right format it will work. This just doesn't seem right to me though as I am so used to laying out how things should be interacted with in interfaces.

I feel like there should at least be some extra step in the middle where the object is validated and some obvious structure that a developer can look at and then implement their own class intuitively and see errors before runtime.

Is there a specific pattern in PHP like this?

1

3 Answers 3

6

PHP only allows method signatures in interfaces.

This is true. However, nothing is stopping you from making traditional getters and setters for properties as part of the interface. Doing so abstracts underlying implementation details.

Someone can just send any object to the method and if it has the properties needed in the right format it will work.

This is not true. You have type-hinted the argument with IFoodNutrition $food. PHP will throw a fatal error if this function receives an object that does not implement the IFoodNutrition interface.

Sign up to request clarification or add additional context in comments.

6 Comments

Raising an error on invalid type does not make the language type safe. 7 will go a long way towards that goal, but still will not be type safe. For that you need a WHOLE lot more predictability around conversions, etc.
@ircmaxell, you got me on semantics regarding type-safe. In regards to the question though, Someone can just send any object to the method and if it has the properties needed in the right format it will work. is still not true.
Sure, which is why I didn't downvote or write my own answer. What you're saying is on-point, just the semantic details are slightly off, hence why I tried helping by explaining the pedantic point in the comment. :-D
The interface will be empty as it can't define properties so the fact that a class implements it will not make it compatible with the method so serves no practical purpose other than to stop things getting passed in by accident I guess. I will have to validate input inside method and leave instructions for developers in the phpdoc.
The interface serves as a contract which all implementing objects are bound. Your method could reliably call any method defined in the interface. Have your code call getters instead of accessing properties directly. Voila.
|
0

My PHP knowledge is still limited, but I'll try a couple of answers about how I would tackle this problem.

1. quick and dirty (not recommended, imho, big no-no)

accept everything on the input, fail with an exception if the input is not valid.

    function getRda ($food) {

        if (!($food instanceof IInterface)) {
           throw new \Exception('function argument should be instance of IInterface');

        }

    //... do your magic
    }

2. suggest getters and setters through the interface

In the interface, suggest the presence of a property (e.g. getMinerals for $minerals)

3. use a trait

Although it's not going to help you much with establishing a contract between object interactions, it will help you keep you code DRY

e.g.

trait Food 
{
   protected $minerals;
   public function getMinerals ()
     {
        return $this->minerals;
     }
}

then, in every class you want multiple inheritence (the equivalent of, let's say, extending two abstract classes), use the trait above.

4 Comments

Can you use properties in traits?
Sorry what is wrong with doing function getRda(IInterface $food)
+ for the mention of traits. However, at this time you can not type-hint traits. So you would lose that functionality.
@BradleyWeston nothing. all good. but one should keep its options open, as there should be other ways to tackle a need. with a replacement or complementary solution.
0

You can't define properties in an interface in php.

It makes sense, because the function of the interface is to specify an API, not the implementation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.