【问题标题】:How to get the name of a given function in php?如何在php中获取给定函数的名称?
【发布时间】:2013-12-19 02:11:35
【问题描述】:

tl;dr:我需要获取给定函数的名称,但不是我所在的当前函数。

例如,类似于下面代码中的“getFunctionName()”:

$listFieldNames = array(
    getFunctionName($country->getName()) => 'Name',
    getFunctionName($country->getAcronym()) => 'Acronym'
);

您可能想知道我为什么要这样做。好吧,当我考虑如何在我的应用程序中处理用户输入时,我想到了这个。在阅读了大量关于使用或不使用异常来验证用户输入的讨论之后,我最终选择使用通知类之类的东西(我使用的是 Zend Framework 1.12):

class Application_Model_Notification
{
    protected $message;
    protected $fieldName;
    protected $code;

    public function __construct($message, $fieldName = NULL, $code = NULL)
    {
        return $this->setMessage($message)
            ->setFieldName($fieldName)
            ->setCode($code);
    }

    // getters and setters;
}

当我验证用户发送的数据时,对于每个输入错误的字段,我都会将通知推送到数组中。每个通知都使用 $fieldName 属性来识别哪个字段包含有问题的信息。

这样,我可以向用户显示输入错误的字段,并将消息放置在匹配字段附近。因为模型中的属性可以有与 UI 表单名称不同的名称(特别是当 web 设计者和 web 开发者不是同一个人时),我需要建立一个匹配它们的列表。这就是问题所在:我想避免使用纯字符串构建该列表。原因是我可以更改模型中属性的名称,而在列表中更改它也会很痛苦。否则,如果我使用它的 getter 的名称,我可以使用 IDE 的重构命令轻松更改它。我只是不知道如何得到它!这不是通过使用魔法常量,因为它们只适用于当前的函数/方法,而我的情况是关于任何给定的方法......

我不知道我正在做的是否是一个好的做法,所以我把我打算做的事情写在下面:

在国家/地区控制器中

public function insertAction()
{
    $country = new Application_Model_Country();
    $country->setName($this->getParam('Name'))
        ->setAcronym($this->getParam('Acronym'));

    $bloCountry = new Application_Model_Business_Country();
    try {
        // The aforementioned list
        $listFieldNames = array(
            getFunctionName($country->getName()) => 'Name',
            getFunctionName($country->getAcronym()) => 'Acronym'
        );

        $bloCountry->insert($country, $listFieldNames);
        if ($bloCountry->countNotifications() > 0) {
            $this->view->notifications = $bloCountry->getNotifications();
        } else {
            $this->view->success = 'Country saved succesfuly.';
        }
    } catch (Exception $e) {
        $this->view->error = $e->getMessage();
    }
}

在模型内的 Country 业务对象中

protected $_country;
protected $_notifications;

// Constructor, getters, setters and other methods
// (...)

protected function validate($country, $listFieldNames)
{
    if (trim($country->getName()) == '') {
        $_notifications[] = new Application_Model_Notification(
            'The country name must be specified',
            $listFieldNames[getFunctionName($country->getName())]
        );
    } else {
        $_country->setName(trim($country->getName()));
    }
}

public function insert($country, $listFieldNames)
{
    $this->validate($country, $listFieldNames);
    if (countNotifications() > 0) {
        return 0;
    } else {
        $daoCountry = new Application_Model_DbTables_Country();
        return $daoCountry->save($this->_country);
    }
}

提前致谢!

【问题讨论】:

  • 我一遍又一遍地阅读你的问题,但我无法弄清楚你想要什么。 getFunctionName() 应该返回什么?
  • 抱歉,我的问题没有很清楚,@Barmar,getFunctionName() 应该返回一个带有给定函数名称的字符串。你可能会想到魔术常量,但它们对我不起作用,因为它们用于返回当前函数的名称,而我需要获取我想要的函数的名称。
  • 所以您希望getFunctionName($country->getName()) 返回类似Country::getName 的内容?但是getFunctionName的参数只是一个字符串(一个国家的名字),它怎么知道它来自什么函数呢?
  • 这正是问题所在。我只需要动态获取任何给定函数的名称,但我该怎么做呢?我知道我是否写下函数,我只是在调用它。所以我期待有某种方法可以得到这个名字,它可以是任何格式,你刚才说的那个“Country::getName”非常适合......
  • 如果可以在参数中写入'$country->getName()',为什么不能在数组赋值中直接写入'Country::getName'?

标签: php design-patterns user-defined-functions


【解决方案1】:

因此,对于来自网络的每个自定义字段,您都需要一个在其上调用的验证函数。您可以在模型级别执行此操作。你将不得不自己定义那些;你将不得不做一些工作。

定义接口提供了每个模型都不能破坏的契约。这意味着您可以期望实现它的每个类/模型都定义了这些功能。

interface FieldValidationInterface
{
    public function isValid();
    public function getNotifications();
}

class Country implements FieldValidationInterface
{
    /**
     * Check to see if the model is valid 
     * by checking every field
     */
    public function isValid()
    {
        $valid = true;

        // go through each private member
        if (!$this->name) {
            $this->notifications['name'] = 
                'The country name must be specified';
            $valid = false;
        }

        return $valid;
    }

    public function getNotifications()
    {
        return $this->notifications;
    }
}

// The logic for insertAction()
if (!$coutry->isValid()) {
    foreach ($country->getNotifications() as $field => $msg) {
        // do something to report to the web: 
        // which field was bad ($field), and why ($msg)
    }
}

【讨论】:

  • 谢谢,@Andrea。将验证权放在模型中允许我直接使用受保护的属性,这样我就可以避免使用属性 getter 名称来识别它们的所有工作。但是我仍然关心设计模式......我不应该让我的实体贫血并将验证放在模型中的另一个类中,以便将验证逻辑与实体本身分开吗?这就是我一直在尝试做的事情,但我最终遇到了我首先提出的问题:需要使用函数名称......
  • 您可以将验证类设为一个单独的类,并将其传递给 Country 类的构造函数。如果您有兴趣了解具有单一职责的小类的设计模式,您可能对依赖注入感兴趣:fabien.potencier.org/article/11/what-is-dependency-injection
  • 看来这样可以保证分离,但我需要看看这篇文章。谢谢,如果有帮助,我会尽快发布。
猜你喜欢
  • 2011-01-10
  • 1970-01-01
  • 2011-10-26
  • 2010-11-03
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
相关资源
最近更新 更多