принудительное определение функции на основе реализованного интерфейса

Я использую некоторый полиморфизм базы данных, чтобы соединить отношения между таблицами через красноречивый / laravel. (ПРИМЕЧАНИЕ, приведенный ниже пример был упрощен, два объекта уже расширяют базовый класс, поэтому я не могу расширить другой, который реализовывал бы нужное мне поведение, базовый класс, который они расширяют, используется совместно с другими классами, которые не связаны с тем, что я пытаюсь сделать ниже)

class Pageable{
  public function table() {
    return $this->morphTo();
  }
}

class User {
  public function pageable() {
    return $this->morphOne('Pageable', 'table');
  }

  public function returnUrl() {
    return "http://...";
  }
}

class Company {
  public function pageable() {
    return $this->morphOne('Pageable', 'table');
  }

  public function returnUrl() {
    return "http://...";
  }  
}

Я перебираю pageable и затем могу получить либо объект User, либо Company, однако мне нужна общая функция, такая как returnUrl, которую я могу вызывать для любого из объектов, которые могут быть преобразованы в это отношение. Есть ли способ очистить это выше или, по крайней мере, создать несколько отказоустойчивых проверок, чтобы убедиться, что все необходимые методы реализованы в классе, если, например, они реализуют PeageableInterface. Например, могу ли я установить в интерфейсе требование, чтобы эта функция returnUrl была обязательной?

Как мне создать такой интерфейс?


person user391986    schedule 16.08.2013    source источник


Ответы (2)


Попробуйте использовать черты.

В своих классах просто сделайте следующее:

use TraitWithReturnUrl;

тогда...

trait TraitWithReturnUrl {
    function returnUrl() {
        // do stuff like it's on the object itself
    }
}

Бинго! :)

Также ознакомьтесь с моей библиотекой Fatty, которая также может быть полезна для подобных вещей: https://github.com/kirkbushell/fatty

В обоих случаях вам понадобится PHP 5.4+.

person Oddman    schedule 16.08.2013
comment
интересные вещи у вас здесь мистер! :) Я проверю это, когда у меня будет минутка. PS. Скажи чтоооо? :П - person Gadoma; 16.08.2013
comment
отличная ссылка, где именно я могу определить свою черту, в каком файле и в каком месте? Я посмотрю на жир, он выглядит великолепно, единственная разница между ними, что жир во время выполнения? - person user391986; 16.08.2013
comment
@Oddman Я видел твой пост на форуме L :P, но на самом деле мы не встречались ;p - person Gadoma; 17.08.2013
comment
Черты предназначены для более конкретных реализаций - как то, что вы делаете здесь, так и должен быть ваш подход. Вы правы, говоря, что Fatty больше для расширения времени выполнения - он для предоставления методов и функций, когда вам это нужно, а не когда создается экземпляр объекта. Что касается того, где вы поместите черты - это полностью зависит от вас. Просто до тех пор, пока Laravel может это видеть, все будет в порядке, что очень легко сделать с функциональностью IoC :) Гадома - ах да :) - person Oddman; 17.08.2013

Черты могут быть более удобным способом (новый в php 5.5), но вы можете напрямую использовать интерфейсы, которые, я думаю, в вашем случае могут выглядеть так:

1) Создадим интерфейс:

interface Pageable {

    public function pageable();

}

2) Реализовать интерфейс

class User extends Model implements UserInterface, RemindableInterface, Pageable {

    ... other methods ...

    public function pageable() {
        return $this->morphOne('Pageable', 'table');
    }

}

Однако, если метод pageable() является одним и тем же кодом в каждой реализации, вы можете создать абстрактный класс, который его определяет, а затем использовать его в качестве базового класса вашей модели:

use Illuminate\Database\Eloquent\Model as BaseModel;

abstract class NewModel extends BaseModel implements Pageable {

    public function pageable() {
        return $this->morphOne('Pageable', 'table');
    }

}

Тогда ваши классы:

class User extends NewModel implements UserInterface, RemindableInterface {

    // You now have the pageable() method available

}

Надеюсь, это поможет вам направить вас в правильном направлении.

person fideloper    schedule 16.08.2013
comment
спасибо фиделопер! это действительно помогает, какой-либо ввод, где именно я должен определить свои интерфейсы? - person user391986; 16.08.2013
comment
Конечно, см. мой ответ SO здесь, который идет мои мысли и соответствующую статью в блоге о настройке библиотеки приложений< /а>. - person fideloper; 17.08.2013