Alias
Alias

Reputation: 3081

Laravel - Repository Pattern issues

I've got my Laravel application using the repository pattern. I also have an abstract class called EloquentRepository which contains basic methods. All of my repositories have an update() method, where I simply update a model using an ID and array:

abstract class EloquentRepository {

    public function update($id, array $array) {
        $this->model->whereId($id)->update($array);
    }

}

Now, I also have a Server repository:

interface ServerRepository {

   public function update($id, array $options);

}

class EloquentServerRepository extends EloquentRepository implements ServerRepository {

    protected $model;

    public function __construct(Server $model)
    {
        $this->model = $model;
    }
}

So now, I don't have to add the update() method to my EloquentServerRepository, nor any other Repositories which need to do this (quite a few).

However, there is one repository which does have an update feature, but I'd like it to do something "custom". Lets say it's the User repository:

interface UserRepository {

   public function update($id, array $options, $status);

}

class EloquentUserRepository extends EloquentRepository implements UserRepository {

    protected $model;

    public function __construct(User $model)
    {
        $this->model = $model;
    }

    public function update($id, array $options, $status)
    {
        $this->model->setStatus($status);
        $this->model->whereId($id)->update($options);
    }
}

So now, I have my User repository requiring a status with every update.

However, I get the error:

Declaration of EloquentUserRepository::update() should be compatible with EloquentRepository::update($id, array $array).

Why is this, surely my interface specifies what the declaration should be?

Upvotes: 1

Views: 1777

Answers (2)

The Alpha
The Alpha

Reputation: 146191

It's because you are extending EloquentUserRepository where you have the update method like this:

public function update($id, array $array) {
    $this->model->whereId($id)->update($array);
}

In this case you are also implementing the UserRepository interface but according to the base class' update method your update method has a different signature, which is as given below:

public function update($id, array $options, $status);

So, the error is rising because you've different method signatures. While you may can make both method's signature same probably using an optional parameter like this:

// EloquentUserRepository
public function update($id, array $array, $status = null) {
    $this->model->whereId($id)->update($array);
}

// interface UserRepository
interface UserRepository {
    public function update($id, array $options, $status = null);
}

But I would suggest to use only one interface or abstract class and override the method in your EloquentUserRepository for the different use case. Which would look like this:

abstract class EloquentRepository {
    public function update($id, array $array, $status = null) {
        $this->model->whereId($id)->update($array);
    }
}

// Only extend the EloquentRepository and override the update method
class EloquentUserRepository extends EloquentRepository {

    protected $model;

    public function __construct(User $model)
    {
        $this->model = $model;
    }

    // re-declare the method to override
    public function update($id, array $options, $status = null)
    {
        $this->model->setStatus($status);
        $this->model->whereId($id)->update($options);
    }
}

Or change EloquentRepository a little, for example:

abstract class EloquentRepository {

    public function update($id, array $array, $status = null) {

        if(!is_null($status)) {
            $this->model->setStatus($status);
        }

        $this->model->whereId($id)->update($array);
    }
}

Upvotes: 0

Weltschmerz
Weltschmerz

Reputation: 2186

You can get passed that error by making $status optional by giving it default value, for example:

public function update($id, array $options, $status = null)

Without it being optional (with default value) you're saying this method needs to have a third parameter, which violates the contract set by ServerRepository

Upvotes: 1

Related Questions