在 Parent 中包含 Class 基于 Child Class
Include Class in Parent Based on Child Class
我有一个扩展基本控制器 class 的 child 控制器 class。在 child 中,我定义了一个静态命名空间字符串,它指向模型 class 我想在调用基础 class 中的函数时使用。现在,我必须使用 call_user_func
在正确的模型 class 上调用函数。代码看起来像这样:
Child Class
class RolesController extends Controller
{
const RESOURCE_NAME = 'roles';
const MODEL = 'Role';
}
Parent Class
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
?我找不到类似的问题,因为我正在努力寻找描述这个问题的词。如果有人能指出我正确的方向,将不胜感激。
长答案
模型 classes 上的静态方法使这变得麻烦。更简洁的方法可能如下所示:
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
]);
}
}
我保留了 "model class as constant" 方法,但明确引用了 class。
但现在我们正在使用实际对象,我建议更进一步并在不使用 class 常量的间接寻址的情况下实例化它:
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 名称(不是 属性,如您所试,解析器无法理解):
$class = $this->model;
$objects = $class::getAll([
Model::GET_OPTION_FORMAT => true
]);
但这只能解决您眼前的编码问题,不能解决结构问题。
我有一个扩展基本控制器 class 的 child 控制器 class。在 child 中,我定义了一个静态命名空间字符串,它指向模型 class 我想在调用基础 class 中的函数时使用。现在,我必须使用 call_user_func
在正确的模型 class 上调用函数。代码看起来像这样:
Child Class
class RolesController extends Controller
{
const RESOURCE_NAME = 'roles';
const MODEL = 'Role';
}
Parent Class
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
?我找不到类似的问题,因为我正在努力寻找描述这个问题的词。如果有人能指出我正确的方向,将不胜感激。
长答案
模型 classes 上的静态方法使这变得麻烦。更简洁的方法可能如下所示:
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
]);
}
}
我保留了 "model class as constant" 方法,但明确引用了 class。
但现在我们正在使用实际对象,我建议更进一步并在不使用 class 常量的间接寻址的情况下实例化它:
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 名称(不是 属性,如您所试,解析器无法理解):
$class = $this->model;
$objects = $class::getAll([
Model::GET_OPTION_FORMAT => true
]);
但这只能解决您眼前的编码问题,不能解决结构问题。