另一种方法是元编程的一种非常基本的形式。这个想法是你比手动调用你的方法更高级,让代码为你做这件事。
(假设方法定义都是Post的一部分)
public function getX($model = null) {
if ($model) return $model->getX();
else return self::DEFAULT_X;
}
// usage
$postModel->getX($pictureModel);
这里发生的情况是,在 getX 模型中的 getX 的单个实例中,您传入另一个类的名称,并在该实例上执行 `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');
在这种情况下,您将模型作为字符串传入,然后该方法将完成其余的工作。虽然这可以更快地获得您想要的东西,但您可能会发现您不想一直使用新实例(或者您不能),因此需要对这种“方便”进行权衡方式。
但是,这仍然不能完全解决您的问题,因为您仍然必须一遍又一遍地为每个 getter 重复此操作。相反,您可以尝试以下方法:
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 模型上不存在的函数,该魔术方法将被调用,它会启动您作为参数提供的模型名称的新实例,并调用 @ 987654328@ 方法就可以了,如果它存在的话。
请务必注意,您不得在 Post 中定义这些 getter,除非您想覆盖其他类中的方法。
尽管如此,仍然存在创建新实例的问题,为了解决这个问题,您可以使用一些依赖注入。这意味着您让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');
使用它,您将获得一个数组,其中包含您使用addModel 添加的每个模型上每个getX 方法的返回值。您可以创建非常强大的函数和类来完成所有这些工作,而无需重复繁琐的逻辑。
我必须提到这些示例未经测试,但至少我希望你可以做什么的概念已经明确。
注意:
同样的事情也可以应用于__GET 和__SET 方法,它们用于访问属性。还值得一提的是,库已经在使用这些魔术方法可能存在轻微风险,在这种情况下,您需要使代码更加智能。