Как стать автором
Обновить

Комментарии 46

У меня возникает некий диссонанс, когда на хабре в 2019 году я вижу статьи из серии «php для начинающих».

Куда больший диссонанс возникнет, если начнётся серия статей "php для заканчивающих".

НЛО прилетело и опубликовало эту надпись здесь
Еще лучше в 2019 видеть инструкцию по использованию require_once.
Почему нет? Если человек пишет на PHP он должен иметь представление об incude и require вне зависимости от того что он использует композер. Сам композер под капотом юзает: require_once __DIR__. '/composer/autoload_real.php'; не понимать это было бы странным чтоли)
Ну не знаю, не знаю: за последние 5 лет уже закопали целую кучу «революционных» JS-фреймворков вместе со спецами по ним, а PHP по-прежнему живее всех живых.
А чего это вы язык с фреймверками сравниваете? Сравнивайте с JS, который совершенно не испытывает тенденции к умиранию. В отличии от PHP, доля которого снижается, и уже сравнялась с JS.
image
Тенденции к росту JS я тоже не вижу, а PHP вымирает похоже вместе с C# в этот раз…
… пойду Python учить, вон как вверх полез.
Ну, по крайней мере, он держится на одном уровне — это явно не «закопали»
Мне казалось, холивары о языках хабр перерос, но я ошибался, и они ещё кому-то интересны…
Все как на бирже. Смотришь какие графики растут и в это вкладываешься.
А потом оказывается, что так делает еще пару миллионов человек и что это не так работает. :)

Проблема в том, что специалисты по JS никому не нужны — нужны специалисты по Angular, Vue, Amber и т.д.

Блин, что-то я фигню придумал: с такими графиками в пост про PHP приходить.
Вы всё ещё считаете, что проблема именно в PHP?
А я говорил, что проблема в PHP?
«Проблема» в сообществе(хотя это не проблема, а просто особенность человеческой психики), и в моем поведении — не подумал об этой особенности.
Не думаю, что это особенность PHP сообщества, это свойственно всем сообществам, ведь попытка «накидать камней» в чей либо огород влечёт вполне ожидаемую реакцию. Собственно, будь у меня возможность, я бы весь данный тред потёр, т.к. он не несёт никакой полезной информации, от слова совсем.
Не-не, не сообщества php ни в коем разе. Это черта любого сообщества.
Для начинающих путешественников во времени.

Это очень хорошо, что появляются статьи, и очень плохо, что диссонанс.
Из-за такого диссонанса до сих пор тостер весь завален кодом вида "while $row = mysqli_fetch_array...". потому что статьи для начинающих как были написаны в прошлом веке, так и тиражируются жадными авторами видеокурсов без учета новшеств, которые добавлялись в язык в течение 20 лет.
Не говоря уже о том, что обычно статьи для начинающих пишут сами начинающие. С предсказуемым результатом.
Поэтому грамотные статьи, которые показывают хорошие современные практики, необходимы как воздух.


РНР — это быстрый, удобный и современный язык программирования… который в представлении большинства остался набором скриптов Personal Home Page из прошлого века.
А всё из-за "диссонанса".

mysqli_fetch_array() это еще туда-сюда.

… а вот когда на полном серьезе рекомендуют писать var $a = mysql_connect()…
Еще важно указать что include подключает файл непосредственно при выполнении данной строки, а require в момент компиляции. То есть строка
if (true==false){include 'file.php';} // Данный файл даже не будет читаться с диска.
if (true==false){require 'file.php';} // Данный файл будет при старте читаться с диска.
Может оно и так, но глядя на код, я вижу лишь различие в сообщении об ошибке:
switch (type) {
	case ZEND_INCLUDE:
	case ZEND_REQUIRE:
		if (UNEXPECTED(strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename))) {
			zend_message_dispatcher(
				(type == ZEND_INCLUDE) ?
					ZMSG_FAILED_INCLUDE_FOPEN : ZMSG_FAILED_REQUIRE_FOPEN,
					Z_STRVAL_P(inc_filename));
			break;
	}
	new_op_array = compile_filename(type, inc_filename);
	break;
}
нет, откуда все это берут?) кто этот странный первоисточник?
поведение одинаковое, прям один в один, разница только в уровне ошибки.

Еще важно указать что include подключает файл непосредственно при выполнении данной строки, а require в момент компиляции. То есть строка
if (true==false){include 'file.php';} // Данный файл даже не будет читаться с диска.
if (true==false){require 'file.php';} // Данный файл будет при старте читаться с диска.

этот код прекрасно отработает и будет где-то жить своей жизнью, пока туда кто-то не войдет
Это не так.
Да, я оказался не прав.
Провел тест — при исполнении кода
if (true==false){include 'file.php';}
if (true==false){require 'file.php';}

Ни один файл не был прочитан с диска!
Тогда остается вопрос, преподаватель не прав или все-же может в старых версиях php или при использовании оптимизаторов\кешей опкода или других доп. компонентов такое поведение возможно?
Возможно преподавателя сбила с толку статья про require на php.su. Там действительно написано нечто такое.
Опробовал ваш код в windows в php 7.3, 5.5, 5.2, 4.4, старее не нашёл. В 5.5 пробовал с включенным opcache, так-же пробовал указывать ссылки на внешние файлы и включать параметры allow_url_fopen, allow_url_include. Файлы никогда не пытаются подключиться. Вероятно, кешируется тоже невыполняющийся кусок (если он вообще попадает в кеш?)
Преподаватель неправ. Единица компиляции в PHP — файл. Компилируется файл при его подключении в рантайме из другого кода, то есть компиляция в PHP «по требованию», если опустить всякие нюансы про кэширование опкода или, скажем, phar.

Сейчас в новом коде редко где встретишь, все рулит композер и use

интересно, пойду задания выполнять
Вот про `return` не знал, спасибо!
Открою страшную тайну, но в обычном файле PHP всегда есть return, а если там написать return, то там их станет два подряд %)

Тривиальное объяснение этой особенности
Имеются ввиду опкоды. Каждый файл всегда заканчивается этим опкодом. Но самое интересное в том, что этот самый опкод генерируется всегда и при любых условиях. Даже если сам файл уже содержит return.

Это-то понятно. Лично мимо меня как-то пролетело, что можно из include возвращать осмысленные данные из любого места включаемого скрипта.
Интересно было бы узнать про функции после return — это фича или все же узаконенная бага?

Интересно было бы узнать про функции после return — это фича или все же узаконенная бага?


Немного теории: Вначале создаётся AST и параллельно выделяется место под так называемую «таблицу символов». Там вроде как хранятся только переменные с контекстом, но будем считать что ещё и всякие функции с классами. Так вот, в первом проходе обнаруживаются всякие function, class и прочее, чтобы на них можно было потом ссылаться. Сами ссылки на имена и типы называются «связыванием», время, когда это происходит — «ранним» (во время парсинга). Если это константа и вывод типа не требуется, то ещё и «статическим». Например, большинству PHP разработчиков становится теперь понятно когда именно всякие константы __DIR__, __CLASS__ и проч. заменяются на физические имена.

Потом, после этих всех действий врубается интерпретатор, который считывает опкоды и который может ссылаться на константы через FETCH_ххх или DO_ххх опкоды. А return — это как раз опкод и выполняется уже во время работы интерпретатора, на «поздней» стадии.

Получаем: Что в таблице символов уже зарегистрирована какая-то функция X. А понять до или после ретурна она задекларирована можно только начав выполнять код, да и лишнее это.

Так что отвечая на вопрос — это совершенно нормальное поведение, даже не бага и допускаю, что так работают абсолютное большинство ЯП с более чем одним проходом. Такие вот пироги.

В целом ясно, но не вполне логично(имхо) в контексте процедурного программирования.


Вот, например, такой код


f();
if(true){
    function f(){ echo 1; }
}

вполне очевидно выдаст фатальную ошибку.
По сути своей очень близко к ситуации с функциями после return'а во включаемом файле.
Т.е., с одной стороны, можно рассматривать include как функцию с побочными эффектами(кодогенерация), раз уж есть return, который прерывает поток исполнения этой кодогенерации. С другой стороны, функции все равно продолжают генериться, хотя по здравому размышлению, не должны бы.


Как-то сумбурно описал, но думаю идея понятна. Ну так — пустые философствования. :)

Как-то сумбурно описал, но думаю идея понятна. Ну так — пустые философствования. :)

Ща попробую декомпозировать эти тезисы.

Функции внутри AST нод (ast node имею ввиду), отличных от корневой — не выносятся в таблицу заранее. Декларируются в рантайме, а значит и «недобага» не будет воспроизводится.
Заголовок спойлера
// 2.php
<?php
return;

if (true) {
    function f()
    {
        echo 42;
    }
}

<?php
require __DIR__ . '/2.php';

f(); // fail


Кажется всё, вот оно решение всех проблем!

Но… По пунктам:
1) Если просто написать функцию, то будет структура с подпрограммой.
Заголовок спойлера
line     #* E I O op       | operands
---------------------------|-----------
   2     0  E >   EXT_STMT |
         1        NOP      |
   6     2      > RETURN   | 1


2) Если запилить это всё в if, то опкод будет генерировать эту функцию (почти что eval, только с кешированием опкода).
Заголовок спойлера
line     #* E I O op               | operands
-----------------------------------|-----------
   2     0  E >   EXT_STMT         |
         1      > JMPZ             | <true>, ->4 # Это вот ифчик
   3     2    >   EXT_STMT         |
         3        DECLARE_FUNCTION | 'f' # А вот это декларация функции
   8     4    > > RETURN           | 1


Так что получаем уже позднее связывание, а не раннее, как было до этого. Как следствие — вообще другой механизм и другой кусок кода, который отвечает за это объявление.

///

Но если в целом — философствование это очень годное. Вынести return на ранний уровень и поступать аналогично механизмам, используемым в function. Т.е. тупо игнорировать дальнейший код, написанный после return, если он объявлен в корневой ноде AST. Дима Стогов как раз занимался DCE в PHP, можно ему подкинуть идейку.
Только это поломает обратную совместимость, и голосование за такой RFC скорей всего будет провальным :(

P.S. Вот такие топики «для начинающих» я люблю :)
Функцию автолоад выпиливают из PHP8. Думаю стоит об этом упомянуть в статье.
Не выпилили, а сделали депрекейтед. Разные вещи.
Про deprecated я упомянул в статье, насчёт удаление в PHP8 — это да, но может и раньше, поэтому я не указал конкретную версию.
А вы видели сайт-файл на 10 000 строк? Аж слёзы на глазах (╥_╥)…

Да, была такая традиция для ускорения работы приложения склеивать всё вместе в один файл
Типа один раз распарсил, в опкэш сохранил и получил кучу свободного времени.
Это было в 2005-м году, и это была не оптимизация, просто заказчик учил PHP…
А разве у Хабра не было в правилах про уникальный контент и запрет репостов?
Спасибо, не знал
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.