另一种方法是元编程的一种非常基本的形式。这个想法是你比手动调用你的方法更高,让代码为你做这件事。
(假设方法定义都是 的一部分Post
)
public function getX($model = null) {
if ($model) return $model->getX();
else return self::DEFAULT_X;
}
// usage
$postModel->getX($pictureModel);
这里发生的情况是,在模型中的这个单个实例中,getX
您Post
传入另一个类的名称,并在该实例上执行“getX”方法(如果它存在并且是可调用的)。
您可以通过其他方式扩展它。例如,当方法无论如何都可以做到时,也许您不想传递实例:
public function getX($model_name = null) {
if ($model_name && $class_exists($model_name) && is_callable(array($model_name, 'getX')) {
$model = new $model_name;
return $model->getX();
} else {
return self::DEFAULT_X;
}
}
// usage
$postModel->getX('Picture');
在这种情况下,您将模型作为字符串传入,然后该方法将完成其余的工作。虽然这可以更快地获得您想要的东西,但您可能会发现您不想一直使用新实例(或者您不能),因此需要对这种“方便”进行权衡方法。
但是,这仍然不能完全解决您的问题,因为您仍然必须一遍又一遍地为每个吸气剂重复此操作。相反,您可以尝试这样的事情:
public function __call($method, $args) {
$class = $args[0];
if (class_exists($class) && is_callable(array($class, $method))) {
$model = new $class;
return $model->$method();
}
}
// usage
$postModel->getX('Picture');
$postModel->getY('Quote');
$postModel->getZ('Picture');
如果您调用模型上不存在的函数,则将Post
调用该魔术方法,并且它将启动您作为参数提供的模型名称的新实例,并getWhatever
在其上调用该方法(如果存在) .
重要的是要注意,您不能在 中定义这些 getterPost
,除非您想覆盖其他类中的方法。
但是,始终存在创建新实例的问题,为了解决这个问题,您可以使用一些依赖注入。这意味着您让Post
该类包含它希望将来使用的其他类实例的列表,因此您可以随意添加和删除它们。
这就是我认为的实际解决方案,其他示例有望展示我是如何到达这里的(当然,将编辑以澄清事情)。
public $models = array();
public function addModel($instance) {
$this->models[get_class($instance)] = $instance;
}
public function __call($method, $args) {
$class = $args[0];
if (array_key_exists($class, $this->models)) {
$model = $this->models[$class];
if (is_callable(array($model, $method)) {
return $model->$method();
}
}
}
// usage
$this->addModel($pictureModel);
$this->addModel($quoteModel);
$this->getX('Picture');
$this->getY('Quote');
在这里,您将现有的模型实例传递给Post
类,然后将它们存储在一个数组中,并以类的名称为键。然后,当您使用上一个示例中描述的类时,它不会创建新实例,而是使用它已经存储的实例。这样做的好处是您可以对您的实例做一些您希望在Post
模型中反映出来的事情。
这意味着您可以添加任意数量的需要插入的新模型,而您Post
唯一需要做的就是注入它们addModel
,并在这些模型上实现 getter。
它们都要求你告诉班级在某个时候要调用什么模型。既然您有一系列依赖模型,为什么不添加一种获取所有内容的方法呢?
public function __call($method, $args) {
$class = $args[0];
if (array_key_exists($class, $this->models)) {
$model = $this->models[$class];
if (is_callable(array($model, $method)) {
return $model->$method();
}
} elseif ($class === 'all') {
// return an array containing the results of each method call on each model
return array_map(function($model) use ($method) {
if (is_callable(array($model, $method) return $model->$method();
}, $this->models);
}
}
// usage
$postModel->getX('all');
使用它,您将获得一个数组,其中包含getX
您添加的每个模型上每个方法的返回值addModel
。您可以创建非常强大的函数和类来完成所有这些工作,而无需重复繁琐的逻辑。
我不得不提一下,这些例子是未经测试的,但至少我希望你能做什么的概念已经清楚了。
注意:
同样的事情也可以应用于__GET
和__SET
方法,用于访问属性。还值得一提的是,库已经使用这些魔术方法可能存在轻微风险,在这种情况下,您需要使代码更加智能。