Reputation: 3081
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
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
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