通过PHP中的字符串引用和调用方法是一个坏主意吗?

时间:2009-07-01 17:05:38

标签: php iterator data-mapping

我总是担心通过字符串引用它们来调用方法。

基本上在我当前的场景中,我使用静态数据映射器方法来创建和返回数据模型对象的数组(例如,SomeDataMapper :: getAll(1234))。模型遵循Active Record设计模式。在某些情况下,可能会返回数百条记录,而且我不想一次将所有内容都放入内存中。所以,我使用迭代器来翻阅记录,如下所示

$Iterator = new DataMapperIterator('SomeDataMapper', 'getAll', array(1234));

while ($Iterator->hasNext()) {
  $data = $Iterator->next();
}

这是一个很好的方法吗?以字符串形式传递mapper类的名称和方法是一个坏主意吗?我担心这个想法不能移植到其他语言。对于像Ruby和Python这样的语言,这通常是正确的吗?如果是这样,有人可以推荐一个好的选择吗?

仅供参考,对于未来人们的推荐,我称之为这样的方法:

$method = new ReflectionMethod($className, $methodName);
$returnValue = $method->invokeArgs(null, $parameters);

3 个答案:

答案 0 :(得分:3)

这实际上是工厂模式的一个版本 - 使用字符串创建对象实例。

但是,我质疑使用迭代器来控制数据分页的设计思想 - 这不是迭代器的真正目的。除非我们只是名字混淆,但我可能更愿意看到这样的事情。

$pager = new DataMapperPager( 'SomeDataMapper', 'someMethod', array(1234) );
$pager->setPageNum( 1 );
$pager->setPageSize( 10 );
$rows = $pager->getResults();

foreach ( $rows as $row )
{
   // whatever
}

当然,DataMapperPager :: getResults()可以返回迭代器或任何你想要的东西。

答案 1 :(得分:1)

这是一种可以接受的方式。 Python和Ruby都支持它,因此应该是可移植的。 Python可以像PHP一样轻松地完成它,但Ruby还有更多功能。至少在Python中,当您引用的特定类尚未在文件中导入或显示时(例如,在您尝试引用它的同一文件中找到该类时),它非常有用。

从Ruby中的字符串中获取类对象:http://infovore.org/archives/2006/08/02/getting-a-class-object-in-ruby-from-a-string-containing-that-classes-name/

答案 2 :(得分:1)

PHP并不真正支持以任何其他方式传递函数。 PHP中的所有动态方法调用函数都采用他们称之为“回调”的函数 - 有关该文档的文档,请参阅http://us.php.net/manual/en/language.pseudo-types.php#language.types.callback。正如您将看到的,它们只是字符串或不同使用模式的字符串数组,所以您离它们不远。

然而,有一些设计模式可以解决这个问题。例如,您可以定义所有映射器类必须实现的DataMapper接口。然后,您可以将映射器实例传递给迭代器,而不是将类和方法作为字符串传递,因为它需要接口,它可以直接调用接口方法。

伪代码:

interface DataMapper
{
   public function mapData($data);
}

class DataMapperIterator ...
{
  public function __construct(DataMapper $mapper, ...)
  {
   ...
  }
  ...
  public function next()
  {
    ... now we can call the method explicitly because of interface ...
    $this->mapper->mapData($data);
  }
}

class DataMapperImplemenation implements DataMapper
{
  ...
  public function mapData($data)
  {
    ...
  }
 ...
}

使用传入的字符串按名称调用方法并不可怕,可能只有性能损失,因为生成的字节码无法优化 - 总会有符号查找 - 但我怀疑你会注意到这一点得多。