Laravel动态类使用

时间:2016-09-01 19:50:23

标签: php html laravel oop

我需要为这样的类调用实现一个系统:

想象一下,有一个类Calendar.php处理数据库查询(或者你喜欢的模型),默认情况下应该使用它。如果需要实现一些新的行为,我想实现一个类MaterialCalendar.php,它将扩展Calendar.php类,这样我就可以在新创建的MaterialCalendar.php中使用Calendar.php中的所有方法。如果需要,使用重写父方法。

问题是如何在代码中的任何位置,视图或控制器中实现这种行为:

if(子类存在){use child class} else {use default parent class}

上面伪代码中的这种行为应该是动态的,所以如果没有MaterialCalendar.php,默认情况下应该使用Calendar.php,如果存在MaterialCalendar.php那么应该使用它。它需要是动态的,与本例中使用的类名无关。

2 个答案:

答案 0 :(得分:1)

定义接口以保证您的代码可以与ICalendar的任何实现一起使用:

interface ICalendar {
    public function method1();
    public function method2();
}

创建实施:

class Calendar implements ICalendar {
    public function method1() {}
    public function method2() {}

}

class MaterialCalendar extends Calendar {
    public function method1() {}
    public function method2() {}
}

简单容器

class SimpleContainer {
    private static $binds = [];

    public static function bind($interface, $class) {
        self::$binds[$interface] = $class;
    }

    public static function make($interface) {
        if (array_key_exists($interface, self::$binds)) {
            return new self::$binds[$interface];
        }

        throw new \Exception("Interface is not binded");
    }
}

在bootstrap的某个地方你应该确定要绑定到接口的类,如:

SimpleContainer::bind(ICalendar::class, MaterialCalendar::class);

在需要获取日历对象的所有位置使用以下代码:

SimpleContainer::make(ICalendar::class);

答案 1 :(得分:0)

Andrej开局不错,但没有必要为此目的设计容器。 Laravel附带了一个功能强大的container,您可以将实现绑定到接口。

使用Andrej的界面和具体类,您可以创建一个service provider,将所需的类绑定到ICalendar接口:

(在提供者的注册方法中):

$this->app->bind('App\Contracts\ICalendar', 'App\Models\MaterialCalendar');

当然,在这里,您将有条件地决定将哪个类绑定到接口(请参阅函数class_exists)。

从这一点开始,您可以依赖Laravel的容器在任何需要的位置注入此依赖项。例如,在CalendarController的{​​{1}}方法中,您只需type hint 界面,Laravel将自动为您提供具体类的实例绑定它:

store

我绝对建议您阅读container以及providers上的文档。您可能感兴趣的是Contextual Binding,您可以在其中有条件地将实现绑定到接口。