【问题标题】:What's the deal with a leading underscore in PHP class methods?PHP 类方法中的前导下划线是怎么回事?
【发布时间】:2010-10-14 09:11:33
【问题描述】:

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

public function _foo()

...而不是...

public function foo()

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

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

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

【问题讨论】:

标签: php coding-style


【解决方案1】:

它源于面向对象 PHP (PHP 4) 的糟糕旧时代。 OO 的实现非常糟糕,并且不包括私有方法之类的东西。作为补偿,PHP 开发人员在原本是私有的方法前面加上了下划线。在一些较早的课程中,您会看到 /**private*/ __foo() { 以增加其重要性。

我从来没有听说过开发人员在他们的所有方法前都使用下划线,所以我无法开始解释是什么原因造成的。

【讨论】:

  • 我在控制器中的方法前放置了一个下划线,这些方法是类私有的,并且在路由中未使用。因为我使用自己的框架,所以这增加了安全性,因为我在路由中对控制器名称执行不带前导下划线的策略。但这很少超过每个控制器 1-2 个方法。
  • 按照惯例,对于 perl,以下划线开头的方法是私有的。但这只是一个约定。事实上,这些方法仍然可以从类外部访问。
  • 如果扩展类决定公开其父类的受保护方法,则下划线的意义就更小了。这是一个边缘案例,但它发生了。 API 开发人员还可以选择将私有方法公开为公共方法,这意味着除了更改访问修饰符之外,他们还必须重构方法名称。没什么大不了的,但仍然令人讨厌。
  • Johan - 重构很麻烦?我的编辑器有一个名为“查找和替换”的功能。效果很好!
  • 这是一种您可以使用的 C# 约定,为私有成员加上一个下划线前缀。因此,Zend Framework 1 (2012) 约定以同样的方式进行。
【解决方案2】:

我相信目前此类 PHP 约定最权威的来源是 PSR-2: Coding Style Guide,因为 Zend 框架是 PSR 的一部分:

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

【讨论】:

  • 当我第一次读到这个时,我理解了这样做的原因,以便您可以查看一个方法并知道它是公共的还是私有的。如果这是一项要求而不是约定,那将更有意义。因为如果团队中的 1 位程序员在不需要的地方添加了下划线,或者用下划线公开了一个下划线,那么您最终会遇到很多混乱。事实证明,正如 Jeremy 指出的那样,这来自 PHP4,并且 #ZF 基于 PEAR 约定的约定。 PEAR 已将其删除,我相信#ZF 会效仿。
  • 这个答案是正确的。它在 Magento 中无处不在,正如下面 Sliq 所指出的,这是一个通常已被弃用的约定。
  • 这里是关于这个的更新链接。 framework.zend.com/manual/1.12/en/…
  • 仅供参考(和@joedevon)Zend 2.4 几个月前发布了,他们仍然使用下划线表示私有和受保护的framework.zend.com/manual/current/en/ref/…
  • 但是现在 Zend 框架版本 2.4 不使用带有前缀的单下划线 protectedprivate 变量或方法声明到他们的代码中。例如:AbstractActionController 类 -> github.com/zendframework/zend-mvc/blob/master/src/Controller/…AbstractController 类 -> github.com/zendframework/zend-mvc/blob/master/src/Controller/…
【解决方案3】:

现在,在 2013 年,这是 PSR-2 编码指南“正式”地“糟糕”的风格

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

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

【讨论】:

  • 根据PSR-2 -> “不应该”意味着“不推荐”不被禁止 这意味着在某些情况下可能是可以接受的。 PSR 文档 -> ietf.org/rfc/rfc2119.txt
【解决方案4】:

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

我仍然是,但是,我找到了一个可以成为一种好习惯的原因。想象一下,您有公共方法addFoo(),并且在该方法中,您有一些与其他方法共有的任务addFooWhenBar()addFooWhenBaz()...现在,该常用方法的最佳名称是addFoo(),但是它已经被占用了,所以你必须想出一些丑陋的名字,比如 addFooInternal()addFooCommon() 或 ... 但 _addFoo() 私有方法看起来是最好的。

【讨论】:

  • 是的,同意。其实我来这里是想看看其他人对下划线的看法,因为我很少使用它们,而且总是感觉不对,但这个例子是我有过的一次。我还将它们用于模板方法模式的某些情况,其中公共方法调用子级已覆盖的抽象受保护方法,这是一个类似的想法。 有时公共方法和它调用的抽象受保护方法是如此相似或相关,以至于以不同的方式命名它们似乎比在抽象方法前加一个 _ 更奇怪。
【解决方案5】:

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

【讨论】:

    【解决方案6】:

    我在为私有方法编写的 PHP 5 类中使用前导下划线。对于开发人员来说,一个特定的类成员是私有的,这是一个小的视觉提示。在使用为您区分公共和私有成员的 IDE 时,这种类型的提示没有那么有用。我从我的 C# 时代开始学习它。旧习惯...

    【讨论】:

      【解决方案7】:

      我一直在寻找相同的答案,我做了一些研究,我刚刚发现 php 框架提出了不同的风格:

      代码点火器

      官方手册有coding style section that encourages this practice

      私有方法和变量

      只能在内部访问的方法和变量,例如公共方法用于代码抽象的实用程序和辅助函数,应使用下划线作为前缀。

      public function convert_text()
      
      private function _convert_text()
      

      其他框架也这样做,比如

      Cakephp:

      does the same:

      会员可见性

      对方法和变量使用 PHP5 的私有和受保护关键字。此外,非公共方法或变量名称以单个下划线 (_) 开头。示例:

      class A
      {
          protected $_iAmAProtectedVariable;
      
          protected function _iAmAProtectedMethod()
          {
             /* ... */
          }
      
          private $_iAmAPrivateVariable;
      
          private function _iAmAPrivateMethod()
          {
              /* ... */
          }
      }
      

      还有

      does the same:

      私有类成员前面有一个下划线。例如:

      $_status    _sort()     _initTree()
      

      虽然

      Drupal

      代码风格特别是warns against this:

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

      交响乐

      另一方面,declares:

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

      【讨论】:

      • 非常彻底的答案。
      【解决方案8】:

      我相信您最初的假设是正确的,我发现某些语言在方法/成员等前加下划线前缀是一种常见的做法,这些方法/成员等旨在对“对象”保持私有。只是一种直观的说法,虽然你可以,但你不应该这样称呼它!

      【讨论】:

        【解决方案9】:

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

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

        【讨论】:

          【解决方案10】:

          在 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 中的工作方式可能会错误地实现钩子,这是非常糟糕的。

          【讨论】:

          • 我一直认为这是drupal的设计缺陷。显式注册您的钩子以防止混淆和不稳定的操作会更有意义。假设通常是一件坏事,干扰正常编程或劫持它们的构造通常是糟糕的架构。
          【解决方案11】:

          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>';
          }
          

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

          【讨论】:

            【解决方案12】:

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

            由于我们将 const 变量全部声明为大写,因此在看到变量名称时可以猜测它是 const 变量。类似于我们不想在类外修改的变量,我们用下划线声明它以符合我们自己的约定。

            【讨论】:

            • “常量变量”是什么意思?你怎么能定义一个可变的常量?
            【解决方案13】:

            他们被称为"magic methods"

            【讨论】:

            • _foo() 带有单个前导下划线并不是一种神奇的方法。魔术方法由 两个 连续的前导下划线表示。这里的问题只讲一个。
            猜你喜欢
            • 2016-07-16
            • 1970-01-01
            • 1970-01-01
            • 2012-10-05
            • 1970-01-01
            • 2011-09-03
            • 1970-01-01
            • 2014-02-08
            相关资源
            最近更新 更多