PHP类方法中的下划线会如何处理?


155

在查看各种PHP库时,我注意到很多人选择在某些类方法的前面加一个下划线,例如

public function _foo()

...代替...

public function foo()

我意识到这最终归结于个人喜好,但我想知道是否有人对这种习惯的来源有所了解。

我的想法是,它可能是从PHP 4继承过来的,然后才可以将类方法标记为受保护或私有,以暗示“不要从类外部调用此方法”。但是,我也想到它可能起源于我不熟悉的某个地方(一种语言),或者背后隐藏着很好的理由,我将从了解中受益。

任何想法,见解和/或意见将不胜感激。


9
2014年更新:这是正式过时的语法:github.com/php-fig/fig-standards/blob/master/accepted/…– Sliq 2014
4

Answers:


155

它来自于面向对象的PHP(PHP 4)的糟糕年代。OO的实现非常糟糕,并且不包含私有方法之类的东西。为了弥补这一点,PHP开发人员在方法的开头加了下划线,这些方法原本是私有的。在一些较旧的课程中,您会看到/**private*/ __foo() {它增加一些重量。

我从来没有听说过开发人员在所有方法前都加下划线,因此我无法开始解释造成这种情况的原因。


12
我将下划线放在类私有的控制器中的方法之前,并且未在路由中使用。因为我使用自己的框架,所以在我对路由内的控制器名称强制使用不加下划线的策略时,这增加了安全性。但是,每个控制器很少超过1-2个方法。
罗伯特·K

6
按照惯例,对于perl,以下划线开头的方法是私有的。但这只是一个约定。实际上,这些方法仍然可以从类外部访问。
卢克M

如果扩展类决定将其父级的受保护方法公开,则下划线就显得毫无意义。这是一个极端的情况,但是它确实发生了。API开发人员还可以选择将私有方法公开,这意味着除了更改访问修饰符之外,他们还必须重构方法名称。没什么大不了的,但是很讨厌。
约翰·弗雷德里克·瓦伦

约翰-重构很麻烦吗?我的编辑器具有一个称为“查找和替换”的功能。很棒!
DaveWalley

您可以使用C#约定为私有成员添加一个下划线作为前缀。因此,以相同的方式执行Zend Framework 1(2012)约定。
alpham8

73

我认为,目前这些PHP约定最权威的来源是PSR-2:编码样式指南,因为Zend框架是PSR的一部分:

属性名称不应以单个下划线作为前缀,以表示受保护的或私有的可见性。


9
我认为,使用命名约定不是爱一种语言的理由。
sepehr 2010年

4
当我第一次阅读有关内容时,我理解了原因,因此您可以查看一种方法,并确定它是公共的还是私有的。如果这是一项要求而不是一项约定,那将更有意义。因为如果团队中的一位程序员在不需要的地方添加了下划线,或者在下划线的情况下公开了下划线,那么您会感到非常困惑。事实证明,这来自Jeremy指出的PHP4,和#ZF基于PEAR约定建立了约定。PEAR已将其删除,并且我相信#ZF会效仿。
joedevon

这个答案是正确的。它遍布在Magento的该死的地方,并且正如下面的Sliq所指出的那样,该约定通常已被弃用。
Siliconrockstar

这是关于此的更新链接。framework.zend.com/manual/1.12/en/...
变形兽

仅供参考(和@joedevon)的Zend 2.4于几个月前发布,他们仍然对私人和受保护的framework.zend.com/manual/current/en/ref/…使用下划线。
2015年

40

现在,在2013年,根据PSR-2编码指南,这是“官方”不良样式

属性名称不应以单个下划线作为前缀,以表示受保护的或私有的可见性。

来源:https : //github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md


6
根据PSR-2->“ SHOULD NOT”的意思是不禁止“ NOT RECOMMEND”,这在某些情况下是可以接受的。PSR文件-> ietf.org/rfc/rfc2119.txt
艾哈迈德·哈米迪(Ahmed Hamdy)2015年

14

我强烈反对在私有/受保护的方法前加下划线,因为您可以为此使用私有/受保护的关键字,IDE会为您标记它。

我仍然是,但是,我找到了一个好的做法的原因之一。想象一下,您有公共方法,addFoo()并且在该方法内部您有一部分任务与其他方法通用addFooWhenBar()addFooWhenBaz()...现在,该通用方法的最佳名称是addFoo(),但它已经被使用,因此您必须提出一些建议。像addFooInternal()or或addFooCommon()or 这样的丑陋名称,但是_addFoo()私有方法看起来是最好的方法。


是的,同意。实际上,我来这里是为了查看其他人对下划线的看法,因为我很少使用下划线,并且总是觉得不对劲,但这是我的例子。我还在模板方法模式的某些情况下使用了它们,其中公共方法调用子级已被覆盖的抽象受保护方法,这是类似的想法。有时,它调用的公共方法和抽象保护方法如此相似或相关,以不同的方式命名它们似乎比仅在抽象方法前加上_怪异。
John Pancoast

12

前导下划线通常用于私有属性和方法。这不是我通常使用的技术,但在某些程序员中仍然很流行。


10

我在为私有方法编写的PHP 5类中使用领先的下划线。对于开发人员来说,特定类成员是私有的只是一个小的视觉提示。当使用可为您区分公共成员和私有成员的IDE时,这种类型的提示没有用。我从C#的日子里捡起它。旧习惯...


5

我相信您最初的假设是正确的,我发现某些语言在方法/成员等下加下划线是一种普遍的做法,这些方法/成员等应对“对象”保密。尽管可以,但只是一种视觉方式,您不应该这样称呼!


5

我一直在寻找相同的答案,我做了一些研究,但我发现php框架建议使用不同的样式:

代码点火器

官方手册的编码风格部分鼓励这种做法

私有方法和变量

仅在内部访问的方法和变量(例如,公用方法用于代码抽象的实用工具和帮助器函数)应带有下划线前缀。

public function convert_text()

private function _convert_text()

其他框架也一样,例如

Cakephp:

做同样的事情

成员可见度

将PHP5的private和protected关键字用于方法和变量。此外,非公共方法或变量名称以单个下划线(_)开头。例:

class A
{
    protected $_iAmAProtectedVariable;

    protected function _iAmAProtectedMethod()
    {
       /* ... */
    }

    private $_iAmAPrivateVariable;

    private function _iAmAPrivateMethod()
    {
        /* ... */
    }
}

并且

做同样的事情

私人班级成员前面带有单个下划线。例如:

$_status    _sort()     _initTree()

Drupal

代码风格对此特别警告

  1. 受保护的或私有的属性和方法不应使用下划线前缀。

交响乐

另一方面,声明

Symfony遵循PSR-0,PSR-1,PSR-2和PSR-4文档中定义的标准。


非常彻底的答案。
Colonelclick

4

我从python知道这一点,其中在变量前加上下划线会导致编译器在实际变量名之前翻译一些随机的字母和数字序列。这意味着从类外部访问变量的任何尝试都将导致“变量未定义”错误。

我不知道这是否仍然是在python中使用的约定


3

在Drupal(一个PHP CMS)中,下划线可以用来防止钩子被调用(https://api.drupal.org/api/drupal/includes!module.inc/group/hooks/7)。

如果我有一个名为“ my_module”的模块,并且想命名一个函数my_module_insert,它将在函数hook_insert上“钩”。为防止这种情况,我可以将函数重命名为_my_module_insert。

ps钩子在Drupal中的工作方式很可能会错误地实现钩子,这是非常糟糕的。


1
一段时间以来,我一直认为这是drupal的设计缺陷。显式地注册钩子会更有意义,以防止混乱和不稳定的操作。假设通常是一件坏事,干扰正常编程或劫持它们的构造通常是不良的体系结构。
mopsyd

3

Drupal,并使用下划线:

一般说来,下划线是为了简单标记一个函数可能仅由相关父函数调用的事实。

function mymodule_tool($sting="page title"){
    $out ='';
    //do stuff 
    $out  .= _mymodule_tool_decor($sting);
    return $out;
}

function _mymodule_tool_decor($sting){
    return '<h1>'.$string.'</h1>';
}

当然,只是一个简单的例子...


0

使用下划线只是为了记住目的,我们不会在类外“修改变量” /“调用函数”。

由于我们以所有大写形式声明const变量,因此在看到变量名称时可以猜测它是const变量。与我们不想在类外部修改的变量类似,我们为自己的约定在下划线处声明了该变量。


您所说的“常量变量”是什么意思?您如何定义一个可变常数?
Nico Haase

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.