Как обстоят дела с лидирующим подчеркиванием в методах класса PHP?

155

Просматривая различные библиотеки PHP, я заметил, что многие люди предпочитают префикс некоторых методов класса с одним подчеркиванием, например

public function _foo()

...вместо того...

public function foo()

Я понимаю, что в конечном итоге это сводится к личным предпочтениям, но мне было интересно, кто-нибудь имел некоторое представление о том, откуда эта привычка.

Я думаю, что это, вероятно, перенесено из PHP 4, прежде чем методы класса могут быть помечены как защищенные или частные, как способ "не вызывать этот метод извне класса". Тем не менее, мне также пришло в голову, что, возможно, это происходит где-то (язык), с которым я не знаком, или что за этим могут быть веские доводы, которые мне было бы полезно узнать.

Любые мысли, идеи и / или мнения будут оценены.

nocash
источник
9
Обновление 2014: официально устаревший синтаксис: github.com/php-fig/fig-standards/blob/master/accepted/…
Sliq,

Ответы:

155

Это из плохих старых времен объектно-ориентированного PHP (PHP 4). Эта реализация ОО была довольно плохой и не включала в себя такие вещи, как частные методы. Чтобы компенсировать это, разработчики PHP предвосхитили методы, которые должны были быть приватными, с подчеркиванием. В некоторых старших классах вы увидите, /**private*/ __foo() {чтобы придать дополнительный вес.

Я никогда не слышал о разработчиках, которые предварительно подчеркивали все свои методы подчеркиванием, поэтому я не могу объяснить, что вызывает это.

Джереми ДеГрут
источник
12
Я помещаю подчеркивание перед методами в моих контроллерах, которые являются частными для класса и не используются в маршрутизации. Поскольку я работаю со своей собственной платформой, это повышает безопасность, поскольку я применяю политику отсутствия начальных подчеркиваний для имен контроллеров внутри маршрутов. Но это редко превышает 1-2 метода на контроллер.
Роберт К
6
По соглашению, в perl метод, начинающийся с подчеркивания, является приватным. Но это всего лишь соглашение. Фактически, эти методы все еще доступны извне класса.
Люк М
Подчеркивание имеет еще меньший смысл, если расширяющий класс решает сделать защищенный метод своего родителя открытым. Это крайний случай, но это случается. Разработчики API также могут выбрать частный метод как общедоступный, что означает, что им придется реорганизовать имя метода в дополнение к изменению модификатора доступа. Не важная персона, но все же неприятность.
Йохан Фредрик Варен
Йохан - рефакторинг это неприятность? Мой редактор имеет функцию под названием «Найти и заменить». Прекрасно работает!
DaveWalley
Это соглашение C #, которое вы можете использовать для префикса частных членов с одним подчеркиванием. Поэтому это было соглашение Zend Framework 1 (2012), чтобы сделать это таким же образом.
alpham8
73

Я полагаю, что наиболее авторитетным источником таких соглашений для PHP сейчас является PSR-2: Руководство по стилю кодирования, поскольку Zend Framework является частью PSR :

Имена свойств НЕ ДОЛЖНЫ иметь префикс с одним подчеркиванием для обозначения защищенной или частной видимости.

joedevon
источник
9
Я думаю, что использование соглашения об именах - не повод любить язык.
Sepehr
4
Когда я впервые прочитал об этом, я понял причину, по которой вы можете посмотреть на метод и узнать, является ли он общедоступным или частным. Что имело бы гораздо больше смысла, если бы это было требование, а не соглашение. Потому что, если один программист в команде добавляет подчеркивание там, где это не нужно, или публикует подчеркивание с подчеркиванием, у вас возникает много путаницы. Как оказалось, это пришло из PHP4, как указывает Джереми, & #ZF основали свое соглашение на соглашении PEAR. Груша удалила его, и я верю, что #ZF последует его примеру.
Joedevon
Этот ответ правильный. Это чертовски популярное место в Magento, и, как отмечает Sliq ниже, это соглашение, как правило, устарело.
silicrockstar
Вот обновленная ссылка относительно этого. framework.zend.com/manual/1.12/en/…
Shapeshifter
К вашему сведению (и @joedevon) Zend 2.4 был выпущен несколько месяцев назад, и они до сих пор используют подчеркивание для частного и защищенного framework.zend.com/manual/current/en/ref/… .
Джеймс
40

Теперь, в 2013 году, это «официально» плохой стиль согласно руководству по кодированию PSR-2:

Имена свойств НЕ ДОЛЖНЫ иметь префикс с одним подчеркиванием для обозначения защищенной или частной видимости`

Источник: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md

SliQ
источник
6
в соответствии с PSR-2-> «НЕ ДОЛЖЕН» означает «НЕ РЕКОМЕНДУЕТСЯ» не запрещено. Это означает, что в некоторых случаях это может быть приемлемо. PSR Doc -> ietf.org/rfc/rfc2119.txt
Ахмед Хэмди
14

Я был категорически против префикса закрытых / защищенных методов с подчеркиванием, поскольку вы можете использовать ключевое слово private / protected для этого, и IDE пометит его для вас.

И я до сих пор, но я нашел одну причину, почему это может быть хорошей практикой. Представьте, что у вас есть публичный метод, addFoo()и внутри этого метода у вас есть некоторая часть задачи, которая является общей с другими методами addFooWhenBar(), addFooWhenBaz()... Теперь лучшее имя для этого общего метода будет addFoo(), но оно уже занято, поэтому вы должны придумать безобразное имя как addFooInternal()или addFooCommon()или ... но _addFoo()закрытый метод выглядит как лучший.

umpirsky
источник
Да, согласился. Я на самом деле пришел сюда, чтобы посмотреть, что другие думают о подчеркивании, потому что я их редко использую, и это всегда кажется неправильным, но этот пример один раз у меня есть. Я также использовал их для некоторых случаев шаблона шаблонного метода, где открытый метод вызывает абстрактные защищенные методы, которые переопределены дочерними элементами, что является аналогичной идеей. Иногда открытый метод и абстрактный защищенный метод, которые он вызывает, настолько похожи или связаны, что их именование по-разному кажется более странным, чем просто добавление префикса _ к абстрактному.
Джон
12

Основные подчеркивания обычно используются для частных свойств и методов . Не метод, который я обычно использую, но остается популярным среди некоторых программистов.

jonstjohn
источник
10

Я использую ведущие подчеркивания в классе PHP 5, который я пишу для частных методов. Это небольшая визуальная подсказка для разработчика, что конкретный член класса является частным. Этот тип подсказок не так полезен при использовании IDE, в которой для вас различаются открытые и закрытые члены. Я взял это из моих дней C #. Старые привычки ...

GloryFish
источник
5

Я полагаю, что ваше первоначальное предположение было верным, я обнаружил, что для некоторых языков обычной практикой является добавление подчеркивания к методам / элементам и т. Д., Которые должны быть приватными для «объекта». Просто визуальный способ сказать, хотя вы можете, вы не должны называть это!

Квинтин Робинсон
источник
5

Я искал тот же ответ, я провел небольшое исследование и обнаружил, что фреймворки php предлагают разные стили:

Кодовый Воспламенитель

Официальное руководство имеет раздел стиля кодирования, который поощряет эту практику :

Частные методы и переменные

Методы и переменные, доступ к которым осуществляется только изнутри, например, вспомогательные и вспомогательные функции, которые ваши публичные методы используют для абстракции кода, должны начинаться с подчеркивания.

public function convert_text()

private function _convert_text()

Другие рамки делают то же самое, как

CakePHP:

делает то же самое :

Видимость участников

Используйте закрытые и защищенные ключевые слова PHP5 для методов и переменных. Кроме того, непубличные имена методов или переменных начинаются с одного подчеркивания (_). Пример:

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.

m.ardito
источник
Очень подробный ответ.
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, можно реализовать ловушку по ошибке, что очень плохо.

Maho
источник
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>';
}

Конечно, просто простой пример ...

user3613677
источник
0

Используя подчеркивание просто для запоминания цели, мы не будем «модифицировать переменную» / «вызывать функцию» вне класса.

Мы объявляем переменные const заглавными буквами, чтобы, увидев имя переменной, можно было догадаться, что это переменная const. Подобно переменной, которую мы не хотим изменять вне класса, мы объявляем ее с подчеркиванием для нашего собственного соглашения.

Tassawer
источник
Что вы подразумеваете под "постоянными переменными"? Как вы можете определить постоянную, которая является переменной?
Нико Хаасе
-21

Их называют "магическими методами" .

Тристан
источник
39
_foo()с единственным начальным подчеркиванием не является магическим методом. Магические методы обозначаются двумя последовательными ведущими подчеркиваниями. Вопрос здесь говорит только об одном.
BoltClock