У меня есть приложение Laravel, использующее шаблон репозитория. У меня также есть абстрактный класс под названием EloquentRepository
который содержит основные методы. Все мои репозитории имеют update()
метод, в котором я просто обновляю модель, используя ID и массив:
abstract class EloquentRepository {
public function update($id, array $array) {
$this->model->whereId($id)->update($array);
}
}
Теперь у меня также есть Server
репозиторий:
interface ServerRepository {
public function update($id, array $options);
}
class EloquentServerRepository extends EloquentRepository implements ServerRepository {
protected $model;
public function __construct(Server $model)
{
$this->model = $model;
}
}
Так что теперь мне не нужно добавлять update()
метод к моему EloquentServerRepository
ни каких-либо других хранилищ, которые должны сделать это (довольно много).
Тем не менее, есть один репозиторий, у которого есть функция обновления, но я бы хотел, чтобы он делал что-то «нестандартное». Допустим, это хранилище пользователя:
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);
}
}
Так что теперь у меня есть мой репозиторий пользователей, требующий статус при каждом обновлении.
Однако я получаю ошибку:
Declaration of EloquentUserRepository::update() should be compatible with EloquentRepository::update($id, array $array)
,
Почему, конечно, мой интерфейс определяет, какое объявление должно быть?
Вы можете передать эту ошибку, сделав $ status необязательным, указав значение по умолчанию, например:
public function update($id, array $options, $status = null)
Если это не обязательно (со значением по умолчанию), вы говорите, что этот метод должен иметь третий параметр, который нарушает контракт, установленный ServerRepository
Это потому, что вы расширяете EloquentUserRepository
где у вас есть update
метод как это:
public function update($id, array $array) {
$this->model->whereId($id)->update($array);
}
В этом случае вы также реализуете UserRepository
интерфейс, но в соответствии с базовым классом update
метод ваш update
Метод имеет другую подпись, как указано ниже:
public function update($id, array $options, $status);
Итак, ошибка растет, потому что у вас разные сигнатуры методов. Хотя вы можете сделать подпись обоих методов одинаковой, возможно, с помощью необязательного параметра, подобного этому:
// 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);
}
Но я бы предложил использовать только один интерфейс или абстрактный класс и переопределить метод в вашем EloquentUserRepository
для другого варианта использования. Который будет выглядеть так:
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);
}
}
Или поменять EloquentRepository
немного, например:
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);
}
}