包含基于子类的父类

时间:2015-09-29 23:31:07

标签: php oop laravel design-patterns lumen

我有一个扩展基类控制器类的子控制器类。在子代码中,我定义了一个静态命名空间字符串,该字符串指向我在基类中调用函数时要使用的模型类。现在,我必须使用call_user_func来调用正确的模型类上的函数。代码看起来像这样:

儿童班

class RolesController extends Controller
{
    const RESOURCE_NAME = 'roles';
    const MODEL = 'Role';
}

父类

class Controller extends BaseController
{

    private $model;

    public function __construct()
    {
        $this->model = 'App\\Models\\' . static::MODEL;
    }

    public function getAll(Request $request)
    {
        $objects = call_user_func([$this->model, 'getAll'], [
            Model::GET_OPTION_FORMAT => true
        ]);

        return Response::success([
            static::RESOURCE_NAME => $objects
        ]);
    }
}

我不禁认为这种设计模式不正确。有没有更好的方法来完成我想要做的事情而不必依赖call_user_func?我找不到类似的问题,因为我正在努力找到描述这个问题的词。如果有人能指出我正确的方向,将不胜感激。

1 个答案:

答案 0 :(得分:2)

长答案

这使得繁琐的是模型类上的静态方法。更清洁的方法可能如下所示:

class RolesController extends Controller
{
    const RESOURCE_NAME = 'roles';
    const MODEL = App\Models\Role::class;
}


class Controller extends BaseController
{

    private $model;

    public function __construct()
    {
        $modelClass = static::MODEL;
        $this->model = new $modelClass;
    }

    public function getAll(Request $request)
    {
        $objects = $this->model->getAll([
            Model::GET_OPTION_FORMAT => true
        ]);

        return Response::success([
            static::RESOURCE_NAME => $objects
        ]);
    }
}

我将"模型类保持为常数"方法,但它明确地引用了这个类。

但是现在我们正在使用实际的对象,我建议更进一步,在没有类常量间接的情况下实例化它:

class RolesController extends Controller
{
    const RESOURCE_NAME = 'roles';

    public function __construct()
    {
        parent::__construct();
        $this->model = new App\Models\Role();
    }
}


class Controller extends BaseController
{

    protected $model;

    public function __construct()
    {
    }

    public function getAll(Request $request)
    {
        $objects = $this->model->getAll([
            Model::GET_OPTION_FORMAT => true
        ]);

        return Response::success([
            static::RESOURCE_NAME => $objects
        ]);
    }
}

请注意,您不需要将静态方法getAll更改为非静态方法。使用$object->method调用静态方法即使在严格模式下也能正常工作(不是相反)。

简短回答

你也可以使用变量作为类名(不是属性,正如你所尝试的那样,解析器无法理解这一点):

$class = $this->model;
$objects = $class::getAll([
    Model::GET_OPTION_FORMAT => true
]);

但这只能解决你的直接编码问题,而不能解决结构问题。