Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

keevitaja's avatar

Interface and Trait naming

I know that there is no right or wrong way doing this. So i just would like to know, how you do it.

Should interface always have name like SomeServiceInterface or just SomeService if there is no class with that name. Same question for the trait.

0 likes
28 replies
xingfucoder's avatar

Hi @keevitaja, i usually use the I prefix for interfaces as .Net convention you can see here:

interface IUserRepository {
    //here is your interface code
}

When you use the importing use Namespace\to\your\Interface if you don't specify any prefix or suffix how do you know if it is a class or interface or something similar.

For traits I use trait suffix.

1 like
JeffreyWay's avatar

You're free to do whatever you want, but, in the PHP community, practically nobody uses the I prefix convention. Most common is to append "Interface" to the name, however, when I can, I much prefer to keep it off.

The interface is UserRepository. The EloquentUserRepository is the implementation.

12 likes
RayRutjes's avatar

You can just call them the name of your actual implementation. This is really nice when you start extracting interfaces from actual implementations, as you don't need to refactor all your code.

You have an actual SomeService class, you rename it SomeSpecificService and make it implement the SomeService interface.

keevitaja's avatar

Most complicated thing in coding is finding the names which make sense!

7 likes
RayRutjes's avatar

@keevitaja very often when I can't find a good name, I realize that my Class misses some kind of abstraction and has too much responsibility or sometimes it is just an empty class extending another one.

5 likes
thepsion5's avatar

I use to append Interface to my interfaces, but I've found that it's not terribly intuitive, especially for typehinting. Mentally, it's easier for me to parse someFunction(UserRepository $users) than someFunction(UserRepositoryInterface $users). Not by a lot, but it adds up over time, especially when I'm dealing with a really complex applications.

2 likes
Valorin's avatar

I'm a big fan of leaving off unnecessary hints like Interface, and with the introduction of Contracts in L5, I've started putting my Interfaces in a common namespace like App\Contracts.

Something I find curious is that the discussion is around removing unnecessary hints from class names, but no one appears to have any issues with using Repository in their class names too. I find that creates needlessly long class names, when you can use Namespaces to keep everything really clean:

namespace App\Repositories;

use App\Models\User as UserModel;
use App\Contracts\Repositories\User as UserRepository;

class EloquentUser implements UserRepository {}

The raw classes have minimal names, and the aliases assigned in the use cases allow you to easily identify them when they are being used.

Ultimately, it turns a path like app/Contracts/Repositories/UserRepositoryInterface.php into app/Contracts/Repositories/User.php which is still perfectly readable, but a lot shorter and cleaner.

Side note, it really bugs me how Laravel appends things like Controller and Filter by default, but the Model classes are left in the global namespace without Model appended. It's not consistent... (I always move my Models into a App\Models namespace.)

4 likes
xingfucoder's avatar

Hi @valorin, I agree with you, only I see a problem with some names, in example of User. Sometimes I saw User as a repository injected into a Controller constructor, and if the user doesn't comment this param, when a new developer find his code, it may be confusing for him, because the User model and the Repository could be named with the same name. Only differenciated by the use import sentence, and the full namespace.

2 likes
Valorin's avatar

@codeatbusiness, yep, it can be confusing at times, however thanks to Composer and the PSRs, PHP is shifting to have everything into namespaces. This means checking the use imports at the top becomes critical to understanding a the class anyway, since you can have things coming from multiple dependencies.

That said, it's definitely should be (if it isn't already) one of those best practice things to import a class and alias it if it's likely to be ambiguous.

1 like
JeffreyWay's avatar

But you can always alias the class, so that's sort of a non-issue.

use App\Repositories\User as UserRepository;

// ... 

public function __construct(UserRepository $repo) {}
1 like
Valorin's avatar

@JeffreyWay exactly :-)

Confusion comes when you're too lazy to alias the class, so you end up with ambiguity of what does User refer to - if you don't check the use imports. Following a coding standard and best practices remove the ambiguity.

1 like
keevitaja's avatar

@codeatbusiness i doubt that anyone would write a code which injects both models and repos to controllers/services. At least i do not do that ever. If there are repos, then only repos use directly models.

xingfucoder's avatar

Yes @keevitaja, I refer when a new developer take your code and may think is working with models in place of repositories, some coders avoid documenting their code and may be confusing.

But I agree the importance of namespace alias for removing ambiguity.

Thanks for al replies.

Valorin's avatar

@keevitaja, actually, I can think of a perfectly acceptable use case: Route Model Binding.

Consider this controller:

use App\Models\User as UserModel;
use App\Repositories\User as UserRepository;

class UserController {
    function show(UserModel $user, UserRepository $repository) {
        // ...
    }
}

Simple example of exactly the sort of thing you'd expect to see with Route Model Binding and Repositories in use. You'd use the repository within the route binding to load the model, so it's injected into the controller automatically.

Kemito's avatar

I guess there is not need to alias everything. Take a moment and think about your namings. Make them readable. For example - class User will be respoinsible for single user. Which means it is a model so dont need to alias that. UserRepository can be a interface binded into IoC on implementation - for example: EloquentUserRepository. You will inject interface and its pretty readable that is UserRepository. Make naming pretty readable and you can skip aliases.

If you use interfaces then interface will be name of usage. SomeRepository, SomeService and implementation can include type of implementation EloquentUserRepository BraintreeService or so.

1 like
keevitaja's avatar

@Valorin i have never used Route Model Binding in my projects. I guess mostly because it breaks the "allways code to abstraction" principle and renders repositories pattern with interface binding useless.

What good does a binded repository give me if i still use concrete eloquent models in my controller?

Valorin's avatar

@keevitaja, I'll admit that I don't code to abstraction when it comes to my models and repositories, however you should be able to inject whatever model you like with the route model binding. I haven't tested it, but given you can override the resolution of the model, I'd assume that you can inject your repository interface, and return whatever you like to be passed into the controller.

That said, it's probably only saving a single line of code from each controller action, while adding in extra bootstrap in the routes (which has the side affect of preventing route caching) and extra use imports. So it's possibly not worth it.

satz's avatar

Coming from a .NET background , am prefer to use 'I' as prefix for Interface.

keevitaja's avatar

I need help with naming...

All Repositories extend BaseRepository which injects a model. If there is a PostRepository then it will inject Post model.

    public function __construct(Container $app)
    {
        $segments = explode('\\', get_called_class());
        $modelClass = 'Blog\\' . str_replace('Repository', '', array_pop($segments));

        $this->model = $app->make($modelClass);
    }

That is all working well, but i want to extract this code to a dedicated class. How should i call this class and where should it be placed?

Services\RepositoryToModelService ???

What should be the method name?

xingfucoder's avatar

Maybe RepositoryModelExtractor?

I think it would be a Application Service and you could make an specific ServiceProvider for it.

keevitaja's avatar

Sometimes it pays off to think. This is what i came up with and as a bonus i can already find several usages to it in my project!

use Illuminate\Container\Container;
use ReflectionClass;

abstract class InstanceConverter {

    /**
     * Target class namespace
     *
     * @var string
     */
    static protected $namespace;

    /**
     * Replacement pattern
     *
     * @var string
     */
    static protected $pattern;

    /**
     * Replacement
     *
     * @var string
     */
    static protected $replacement;

    /**
     * @var Application Container
     */
    private $app;

    public function __construct(Container $app)
    {
        $this->app = $app;
    }

    /**
     * Convert model instance
     *
     * @param object $instance
     *
     * @return object
     */
    public function convert($instance)
    {
        $targetClass = $this->getTargetClass($this->getShortName($instance));

        return $this->app->make($targetClass);
    }

    /**
     * Get short name of the instance
     *
     * @param object $instance
     *
     * @return string
     */
    private function getShortName($instance)
    {
        return (new ReflectionClass($instance))->getShortName();
    }

    /**
     * Convert short name to full class name
     *
     * @param string $shortName
     *
     * @return string
     */
    private function getTargetClass($shortName)
    {
        $targetName = preg_replace(static::$pattern, static::$replacement, $shortName);

        return static::$namespace . '\\' . $targetName;
    }
} 
use Blog\Services\InstanceConverter;

class RepositoryToModelConverter extends InstanceConverter {

    static protected $namespace = 'Blog';
    static protected $pattern = '/Repository$/';
    static protected $replacement = '';
}
abstract class BaseRepository {

    /**
     * @var object
     */
    protected $model;

    public function __construct(RepositoryToModelConverter $converter)
    {
        $this->model = $converter->convert($this);
    }
}

To append with preg_replace use preg_replace('/$/', '\0Handler', $class) and to prepend preg_replace('/^/', '\0Do', $class).

dberry's avatar

If you are just going to alias the class:

use App\Repositories\User as UserRepository;

Why not just go ahead and add the suffix to begin with? If the time to type is an issue, it seems like adding the alias would take more time as it's not going to be autocompleted by any ide. If you are aliasing it, then you still end up with the "verbose-ness" in your methods.

Personally I have been suffixing (Interface, Trait, etc), prefixing Abstract... but I am changing that, because take this for example:

use App\Contracts\User;


public function myMethod(User $user) {}

My method doesn't care if it is an interface, class, etc... All it cares about is that it provides the required functionality. It doesn't matter what it's named, where it comes from, just what it does.

So I am now leaning more towards intuitive class names, proper directory structure and good namespacing.

keevitaja's avatar

@dberry you do not understand the purpose of this service.

It takes repository instance in abstract BaseRepository and initiates model instance so it could be used by other repositories like PostRepository. So i would have $this->model which is Post model instance.

dberry's avatar

@keevitaja, sorry I wasn't talking about that service, just the original question of naming and my thoughts on aliasing & suffixing...

keevitaja's avatar

Yeah, I tried not to suffix repositories, but i didn't like it as it was too confusing.

Also i still need the correct namespace and i can use this with other similar cases, like in commanding pattern, as well... need to add the initiation in relative namespace method along with the absolute one.

Edit:

And i am starting to think interface should have Interface suffix unless it is in a dedicated namespace like L5 Contracts.

trondhuso's avatar

Came over this post while trying to search for where to put interfaces in Laravel. According to the follow url interfaces must be suffixed with interface and traits suffixed with trait https://www.php-fig.org/bylaws/psr-naming-conventions/

I prefer to use this naming as it makes sense to say what the class/interface/trait is. It also helps when you look at filenames as well. When you look at code and you see it says UserModel you know it is a model for user. If it is userInterface, you know it is an interface for User.

Now... where to put the Interface or even traits. Search continues.

Please or to participate in this conversation.