关于编码风格:PHP类方法中领先的下划线有什么用?

What's the deal with a leading underscore in PHP class methods?

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

1
public function _foo()

…而不是…

1
public function foo()

我意识到这最终取决于个人喜好,但我想知道是否有人对这个习惯的来源有一些了解。

我的想法是,在类方法被标记为受保护或私有之前,它可能是从php 4继承的,作为一种暗示"不要从类外部调用此方法"的方法。然而,我也想到,它可能起源于我不熟悉的某个地方(一种语言),或者它背后可能有很好的推理,我会从中受益。

任何想法、见解和/或意见都会受到赞赏。


它来自于面向对象的PHP(php 4)过去的糟糕时期。OO的实现非常糟糕,没有包括私有方法等内容。为了弥补这个不足,PHP开发人员用下划线作为私有方法的序言。在一些老的课程中,你会看到/**private*/ __foo() {给它额外的重量。

我从未听说过开发人员在所有方法的开头都加了下划线,所以我无法解释是什么导致了这种情况。


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

Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility.


现在,在2013年,根据PSR-2编码准则,这是"官方"的坏样式:

Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility`

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


我强烈反对在private/protected方法前加下划线,因为您可以使用private/protected关键字,IDE会为您标记它。

我仍然是,但是,我发现了一个原因,为什么它可以成为一个好的实践。假设您有一个公共方法addFoo(),在这个方法中,您有一部分任务是与其他方法addFooWhenBar()addFooWhenBaz()相同的。现在,这个常用方法的最佳名称是addFoo(),但它已经被采用了,所以您必须想出一些难听的名称,如addFooInternal()addFooCommon()或…但_addFoo()私有方法看起来是最好的方法。


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


我在为私有方法编写的php 5类中使用了前导下划线。对于开发人员来说,这是一个很小的视觉提示,即特定的类成员是私有的。当使用为您区分公共和私有成员的IDE时,这种提示就没有那么有用了。我是从我的购物日里买的。旧习惯…


我相信你最初的假设是正确的,我发现有些语言在方法/成员等前面加上下划线是很常见的做法,这些方法/成员等都是对"对象"保密的。只是一种直观的表达方式,尽管你可以,但你不应该这么说!


我在寻找相同的答案,我做了一些研究,我刚刚发现PHP框架建议不同的风格:

编码点火器

官方手册有一个编码样式部分,鼓励这种做法:

Private Methods and Variables

Methods and variables that are only accessed internally, such as utility and helper functions that your public methods use for code abstraction, should be prefixed with an underscore.

1
2
3
public function convert_text()

private function _convert_text()

其他框架也一样,比如

Cakephp:

做同样的事情:

Member Visibility

Use PHP5’s private and protected keywords for methods and variables. Additionally, non-public method or variable names start with a single underscore (_). Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A
{
    protected $_iAmAProtectedVariable;

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

    private $_iAmAPrivateVariable;

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

而且

做同样的事情:

Private class members are preceded by a single underscore. For example:

1
$_status    _sort()     _initTree()

同时

猪跑

代码样式特别警告:

  • Protected or private properties and methods should not use an underscore prefix.
  • 交响曲

    另一方面,声明:

    Symfony follows the standards defined in the PSR-0, PSR-1, PSR-2 and PSR-4 documents.


    我从python了解它,在这里用下划线前缀变量会导致编译器在实际变量名前面转换一些随机的字母和数字序列。这意味着任何从类外部访问变量的尝试都会导致"变量未定义"错误。

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


    Drupal,并使用下划线:

    一般来说,下划线只是简单地标记一个事实,即一个函数可能只由相关的父函数调用…

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function mymodule_tool($sting="page title"){
        $out ='';
        //do stuff
        $out  .= _mymodule_tool_decor($sting);
        return $out;
    }

    function _mymodule_tool_decor($sting){
        return ''.$string.'';
    }

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


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

    如果我有一个称为"我的模块"的模块,并且想要命名一个函数,我的模块插入它会"钩住"在函数钩子插入上。为了防止这种情况发生,我可以将函数重命名为"插入我的模块"。

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


    在中使用下划线只是为了记住我们不会在类外部"修改变量"/"调用函数"。

    就像我们用大写字母声明常量变量那样,当看到变量名时,可以猜测它是常量变量。类似于我们不想在类外部修改的变量,我们为自己的约定用下划线声明它。


    它们被称为"魔法方法"。