Skip to main content

My new way of using PHP Traits & Interfaces

A popular feature in Rails called "mixins" came to PHP a while back under the name "traits".  Traits let library developers give you a lot of functionality with little to no effort by injecting code into your classes that runs as if originally authored in them.
Just toss a line of code into the class you want to augment and you're off to the races.

The one snag I found when using traits however is that they don't participate in any kind of type system.  If desperate enough, you can use reflection to pull out whether a class has one applied or not, but that's only half the battle and a lot of work each time.

This puts me in a slight bind when I'm interacting with classes using a trait I've made as I have no way to type check or hint them in.

But then it dawned on me...

interface MyInterface {
     public function thisMethodIsImportant();
}

trait MyInterfaceImpl {
     public function thisMethodIsImportant() {
          return "Thanks for not forgetting about me!";
     }
}

It's pretty obvious what I'm doing here.  I'm basically writing an interface to add to a class and then creating a trait that fulfils that interface.

This leaves us with "why?"

I think most of the time when someone is going to use your interface, they're going to wish that they didn't have to actually implement the methods it sets out.  Which teaches us a little about how traits came to be: they're purely convenience.
Interfaces are a good idea, no question about it.  It makes code easier to read and follow when you see classes that use them.  Burdening consumers of your library with writing menial code however is not as useful and to a lesser extent so is forcing an implementation with traits.

Using this approach lets someone interested in your library take exactly as much as they need and leave the rest behind.  If all they want is to stay in sync with my library and use the defaults, my trait and implementation will always be in sync, they don't have to worry.  If however for some reason they need to abide by my library's contract but swap out how it's done?  They're fully empowered to do so!

I don't suspect I'm the first person to think of this, however I did come up with it on my own and it seems like a very considerate way to get the best of both worlds.  Enjoy!

Comments

Popular posts from this blog

Laravel Project Architecture: The Missing Guide

At my job, we've been doing a lot of learning and development using Taylor Otwell 's Laravel 4 PHP framework.  As we've become more familiar with it, we've had to come up with better ways to structure our projects outside of what the documentation indicates and the default distribution that is provided. If you've been working with Laravel 4 for any amount of time or come with experience from another framework and are just getting started, you've probably noticed that there are a lot of different ways to cut up your projects. Choice is nice, but sometimes it can be paralysing or misleading. Concrete Advice This post is done in such a way that you can just skim the headings, but if you want a detailed explanation in each section, feel free to read in where necessary. While I can't say the entirety of my advice is in practice throughout the community, I can say that we are starting to use it, and to very good effect at my job.  Especially consider...

Building .NET Core Nuget Packages

My last blog post was on building and publishing npm packages, specifically for typescript projects. In my opinion, packages are an important fundamental unit in software development. They sit at the confluence of technical competence and collaboration, and represent something the software community should be proud of. Most of the time, you're going to be creating software packages once you're comfortable with some essential pillars: Coding Project structure Software architecture Building Delivery Community Licensing After I got my npm package up and running, my next task was to do the same thing with my C# libraries. Similar to protoculture, I have made a library called praxis .  This is done by leveraging the services and tooling known in the .NET ecosystem as nuget. In this case, praxis abstracts many of the concepts and functionality I require when producing server projects. It builds on top of ASP.NET Core, so in that sense you can almost think of it as ...

Laravel is Good, Facades Aren't

I've been working on some Laravel 4 based packages lately which inevitably results in me also looking at other packages. I've noticed sometimes that people use facades at times that give me pause. The most troubling being from inside their model classes. A quick google turned up this video which assures people "there's still an instance behind everything, we're fine" .  Everything mentioned in the video is true except that there is a very glaring omission. Scope What usually goes out the door at the start of a long series of mishaps in software design is scope . When the desire to obtain a solution is stronger than the desire to consider the implications of a firm approach, mistakes are sure to follow.  Sacrifices like this are made due to the assumption of a high cost to developing carefully. What really is happening however is a false dilemma , being responded to with a convenience decision . It's very easy to write model code like ...