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

boldstar's avatar

How To Properly Implement A Vendor Interface

So I am trying to implement a vendor file. I have been looking for something that would give me an idea of what is happening, but perhaps from lack of experience I am unable to make sense.

So this is the vendor file I am looking to implement Hostname.php

namespace Hyn\Tenancy\Contracts;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
 * @property int $id
 * @property string $fqdn
 * @property string $redirect_to
 * @property bool $force_https
 * @property Carbon $under_maintenance_since
 * @property Carbon $created_at
 * @property Carbon $updated_at
 * @property Carbon $deleted_at
 * @property int $website_id
 * @property Website $website
 */
interface Hostname
{
    public function website(): BelongsTo;
}

Now according to there Instructions I can extend there model to a custom model however I am running into an issue with the public function website() method because I beliece I need to concretely instantiate the vendor file but I am unsure how should go about doing this.

  1. Do I need to register a service provider?
  2. What should I do in my custom model file?

This is the current structor of my custom model file


namespace App\Models\System;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Hyn\Tenancy\Contracts\Hostname as Contract;
use Laravel\Cashier\Billable;

class Hostname extends Authenticatable implements Contract
{
    use Billable;

    protected $fillable = [
        'id', 'stripe_id'
    ];

    public function __construct(Hostname $hostname) {
        $this->hostname = $hostname;
    }

}

This is the alarm that I am currently getting

Class App\Models\System\Hostname contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Hyn\Tenancy\Contracts\Hostname::website)
0 likes
3 replies
arukomp's avatar

Because you declared that the Hostname class must implement the Hostname contract/interface, it needs to have this public function website(): BelongsTo method, but it doesn't. Implement the method on your Hostname class (not the interface) and you'll be good to go.

boldstar's avatar

@arukomp , thanks for the response! However I run into a couple problems.

1st: When I add the method public function website(): BelongsTo I get the following alarm

Non abstract method must contain body

So I change the method to public function website(): BelongsTo {;} which as you expect then throws an alarm saying

Return value of App\Models\System\Hostname::website() must be an instance of Illuminate\Database\Eloquent\Relations\BelongsTo

Which makes sense because I am not telling it to return anything. Typically when I write a belongsTo method it would look like this

public function website() {
   return $this->belongsTo('Hyn\Tenancy\Contracts\Website');
}

But when I try to do it that way I get this alarm

Declaration of App\Models\System\Hostname::website() must be compatible with Hyn\Tenancy\Contracts\Hostname::website():

2nd: The argument being passed to public function __construct(Hostname $hostname) is not receiving any arguments however I only get this alarm occasionally.. Here is the alarm

Too few arguments to function App\Models\System\Hostname::__construct(), 0 passed in

The file structure looks like this when I get the Too few arguments alarm

namespace App\Models\System;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Hyn\Tenancy\Contracts\Hostname as Contract;
use Laravel\Cashier\Billable;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Hostname extends Authenticatable implements Contract
{
    use Billable;

    protected $fillable = [
        'id', 'stripe_id'
    ];

    
    private $hostname;

    public function __construct(Hostname $hostname) {
        $this->hostname = $hostname;
    }

    public function website(): BelongsTo {;}

}
boldstar's avatar
boldstar
OP
Best Answer
Level 2

So instead of extending the interface I switch to extending the model. My final code looks like this now

<?php

namespace App\Models\System;

use Illuminate\Database\Eloquent\Model;
use Hyn\Tenancy\Models\Hostname as Contract;
use Laravel\Cashier\Billable;

class Hostname extends Contract
{
    use Billable;

}

Please or to participate in this conversation.