Не используйте PHP фильтр!

Главные вкладки

fairrandir 7 июня 2017 в 13:11
10

Вольный и дополненный перевод https://drupal.stackexchange.com/questions/2509/what-are-the-downsides-o...

На форуме некоторые товарищи, иногда рекомендуют для решения задачи использовать встроенный в ядро PHP фильтр, или Views PHP. Никогда так не делайте! И вот почему:

  1. Данный код пишется в базу, поэтому его нельзя будет отследить через систему контроля версий, например git. (если вы не используете систему контроля версий в разработке - это тоже плохо).
  2. Поля с php-фильтром не кэшируются.
  3. Код в php-фильтре выполняется через eval(). Код через eval работает медленнее, не кэшируется opcache-м, а на некоторых хостингах eval может быть отключен из соображений безопасности.
  4. Не информативные сообщения об ошибках. Что-то типа error in eval() on line 4. Где этот кусок кода, что с ним делать?
  5. Проблемы с обновлением модулей. Обновление модуля - и у вас куча ошибок, которые сложно найти и исправить.
  6. Сложно писать и поддерживать такой код. В обычном textfield - нет форматирования как в IDE, да и шрифт не моноширинный. Копировать туда-обратно тоже заколебаться можно.
  7. Человеческий фактор. Всегда существует возможность ошибки в конфигурации, которая позволит не доверенным пользователям заюзать php-фильтр. ОЙ!
  8. Безопасность в целом. Любой сайт могут взломать, но присутствие на сайте php-фильтра может сделать последствия взлома гораздо тяжелее. XSS, SQL-инъекция - и вот вас уже shell прямо в базе. Smile
  9. Сложности деплоя. Нельзя просто обновить файлы на сервере. Надо лезть в админку, и копипастить код в нужные места. Хотя обычно в PHP-фильтр пишут прямо на продакте. Не стоит работать на продакте.
  10. Повышается цена ошибки. Одна небольшая опечатка в сквозном блоке - и всё пропало, шеф.
  11. Многие разработчики высказываются против использования php-фильтра. Например: пользователь Semantics в своей записи в блоге высказывался против PHP-фильтра ещё в 2013-м (!) году.

Хорошо, PHP-фильтр использовать не стоит. А что же тогда делать?

  1. Через template_preprocess хуки.
  2. Можно создать свой токен и вставлять его с помощью token_filter
  3. Можно создавать вычисляемые поля с помощью computed_field. Этот модуль даже сам подскажет вам, какое название функции использовать.
  4. Если используется Display Suite - можно написать своё Display Suite поле
  5. Ещё варианты, тысячи их! В зависимости от задачи.

Авторы

fairrandir Мимо крокодил

Комментарии

Аватар пользователя bsyomov bsyomov 10 июня 2017 в 11:23
2

У меня есть своя более короткая версия:
Есть только две причины использовать php filter - глупость и лень.
И в обоих случаях, заниматься разработкой вам не стоит.

Аватар пользователя xakd xakd 11 июня 2017 в 10:24

"5. Проблемы с обновлением модулей. Обновление модуля - и у вас куча ошибок, которые сложно найти и исправить." - голословный бред же, ну что за фигня то?

Аватар пользователя fairrandir fairrandir 11 июня 2017 в 11:02

Пример из жизни - обновилась мажорная версия модуля, потерялась обратная совместимость. Какие-то умельцы вставили PHP-код в панели, для встраивания Яндекс.карт на НЕКОТОРЫЕ страницы. При обновлении модуля - эти страницы больше не открываются. Вот было весело переписывать их все искать и переводить на нормальный код.

Аватар пользователя xakd xakd 11 июня 2017 в 11:10

Вот бы если в computed_field они бы это написали - проблем бы не было. Ой. Или бы ли бы. Ты же советуешь этот механизм, так ведь?

Аватар пользователя gun_dose gun_dose 11 июня 2017 в 11:14

В той ситуации надо было написать Ctools Custom Content Type - совершенно хрестоматийный случай их применения.

А что касается компьютэд филд, так по мне этот модуль та ещё галдэша. Лучше высчитать нужные поля в hook_entity_presave

Аватар пользователя xakd xakd 11 июня 2017 в 11:42

Да кто спорит, что есть разные варианты. Только бесит, что какое то фанатье упёртое считает, что один из вариантов неправилен, потому что слишком прост( а на деле других причин тут не просматривается).
Ведь если так все просто - вписать пару строк кода в php-фильтр в виде - то что ж я за профи, мне надо написать модуль для решения элементарной задачи, а php-фильтр я не могу использовать, потому что я такой крутой.
Вот такой подход вызывает рвоту.

Аватар пользователя xakd xakd 11 июня 2017 в 10:53

fairrandir wrote:

Код в php-фильтре выполняется через eval(). Код через eval работает медленнее, не кэшируется opcache-м, а на некоторых хостингах eval может быть отключен из соображений безопасности.

fairrandir wrote:

Хорошо, PHP-фильтр использовать не стоит. А что же тогда делать?

fairrandir wrote:

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

ОХРЕНЕТЬ!! А в computed_field чем исполняется код по-твоему? Святым духом? Да там eval ужасный выполняет код, аллё.
Нельзя использовать php-фильтр, потому что там ужасный eval - юзайте computed_field потому что там хороший eval? Тьфу блин, а выглядело так что ты изучил вопрос

Аватар пользователя fairrandir fairrandir 11 июня 2017 в 11:07
<?php
if (function_exists($compute_func)) {
  
$compute_func($entity_field$entity_type$entity$field$instance$langcode$items);
}
?>

В своем модуле, определяется функция, которая называется, например, computed_field_field_rating_current_compute. В данной функции и происходит собственно вычисление, без всякого eval.

Аватар пользователя xakd xakd 11 июня 2017 в 11:47

Ты дураками то всех не считай, а? А если я в php-фильтре вызову функцию из модуля, все ок? Ты тут про eval писал, так вот он

<?php    // Execute the display code.
    
$display_output NULL;
    if (
$display_in_code) {
      
$display_output $display_func($field$entity_field_item$entity_lang$langcode$entity);
    }
    else {
      eval(
$field['settings']['display_format']);
    }
?>

и вот

<?php  if (isset($settings['code'])) {
      eval(
$settings['code']);
    }
?>

То есть если я в php-фильтре вызову функцию, то все ок что ли? Что за бред?

Я вот проверил, в computed_field вызвал пару функций - user_load(1) а потом user_save - и все ок, другой теперь пароль у user#1.
Но это конечно же ерунда, можно юзать

Аватар пользователя Andruxa Andruxa 11 июня 2017 в 12:33

git там используется на этапе формирования-сборки того, что собираемся деплоить. Сам деплой - это уже не гит.
Выкатывать на прод командой git pull - тоже не хорошо.

Аватар пользователя gun_dose gun_dose 11 июня 2017 в 19:17

1. Нужно самому отслеживать и запоминать, какие файлы изменены.
2. Долго таскать их мышкой
3. Долгая передача файлов - на каждый файл создаётся новое соединение.
4. Не секьюрно.
5. Очень часто при бросании файлов мышкой туда-сюда они могут не переписаться.

Аватар пользователя xakd xakd 11 июня 2017 в 11:17

1.Данный код пишется в базу, поэтому его нельзя будет отследить через систему контроля версий, например git. (если вы не используете систему контроля версий в разработке - это тоже плохо).
3. Код в php-фильтре выполняется через eval(). Код через eval работает медленнее, не кэшируется opcache-м, а на некоторых хостингах eval может быть отключен из соображений безопасности.
Не информативные сообщения об ошибках. Что-то типа error in eval() on line 4. Где этот кусок кода, что с ним делать?
6. Сложно писать и поддерживать такой код. В обычном textfield - нет форматирования как в IDE, да и шрифт не моноширинный. Копировать туда-обратно тоже заколебаться можно.
7. Человеческий фактор. Всегда существует возможность ошибки в конфигурации, которая позволит не доверенным пользователям заюзать php-фильтр(или computed_field). ОЙ!
8. Безопасность в целом. Любой сайт могут взломать, но присутствие на сайте php-фильтра может сделать последствия взлома гораздо тяжелее. XSS, SQL-инъекция - и вот вас уже shell прямо в базе. Smile
9.Сложности деплоя. Нельзя просто обновить файлы на сервере. Надо лезть в админку, и копипастить код в нужные места. Хотя обычно в PHP-фильтр пишут прямо на продакте. Не стоит работать на продакте.
10.Повышается цена ошибки. Одна небольшая опечатка в сквозном блоке - и всё пропало, шеф.

Все вышеуказанные пункты вычеркивай или вычеркивай computed_field и пиши статью, почему этот модуль нельзя использовать - и все эти пункты туда пойдут отлично.

Аватар пользователя fairrandir fairrandir 11 июня 2017 в 11:10

xakd wrote:

Все вышеуказанные пункты вычеркивай или вычеркивай computed_filed

А давайте вы лучше напишите статью, почему стоит использовать PHP-фильтр. С аргументами, пожалуйста.

Аватар пользователя xakd xakd 11 июня 2017 в 11:16

Я выше написал уже - это удобно и работает. Какие вам ещё причины нужны? Может написать ещё почему можно использовать computed_field? Может написать, почему я не верблюд, а, сразу уж?

Аватар пользователя gun_dose gun_dose 11 июня 2017 в 11:20

Офигеть удобно. Вот надо тебе этот код в пхп-фильтре поправить
- идёшь на сайт
- логинишься,
- ищешь в админке нужный блок, вьюс или что-то ещё
- правишь всё в неудобном поле без подсветки кода и форматирования
- сохраняешь

А если всё в коде, то правка происходит так
- поправил код в иде-шке
- гит пуш
- гит пулл

Аватар пользователя xakd xakd 11 июня 2017 в 11:24

Нет, не так. Есть сайт безо всяких гитов. Идешь и создаешь к примеру поле Views php - пишешь там три строчки.
Или же - ставишь гит, если ещё хостинг позволяет, потом пишешь модуль, потом через гит его закачиваешь и потом удаляешь? Это типа быстрее что ли?

Аватар пользователя gun_dose gun_dose 11 июня 2017 в 11:35

Если на сайте нет гита, то нефиг работать с такими заказчиками. Даже на самых бомжацких шаред-хостингах гит есть из коробки, а на впс гит ставится одной командой за 5 сек.

Аватар пользователя gun_dose gun_dose 11 июня 2017 в 12:08
2

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

Аватар пользователя xakd xakd 11 июня 2017 в 11:17

Я наверное напишу статью, почему нельзя использовать computed_field - и вон у меня уже и аргументы есть. Ну что бы дурь этих доводов была нагляднее видна

Аватар пользователя xakd xakd 11 июня 2017 в 11:26

Про rules тоже надо такую статью - почему нельзя его использовать. Там тоже без проблем можно код выполнять
И про devel тоже

Аватар пользователя Andruxa Andruxa 11 июня 2017 в 18:59

Rules как раз и нужен вместо кода.

Приведу пример с расчетом итоговой цены и типа скидки для пользователя.
У нас в магазине скидка может быть трёх типов:
- распродажа: розничная цена + цена со скидкой, значения загружаются извне
- акция: скидка от розничной цены, действующая непродолжительный период времени, "товар дня" условно говоря
- накопительная скидка пользователя
Обычная практика - из трёх возможных скидок выбирается максимальная, и берётся её тип.

Как быть, если скидка по распродаже и скидка по акции - одинаковы (бывает, когда менеджер магазина напутал)?
Какой тип выбрать? Распродажа - смотри, у нас тут распродажи-распродажи?
Или акцию? Смотри - у нас тут акции-акции, хотя ты и так бы мог купить по той же цене на распродаже?
А если у пользователя - такая же накопительная скидка как и по распродаже-акции? Какой тип показать?
Правильный ответ - A/B/C тесты. Как будет лучше продаваться - так и надо делать.

Так вот, чтобы не хардкодить логику в модуле, её вынесли в отдельный рул - в аргументах вся инфа по товару, пользователю, акциям. Результат - итоговая цена и тип получившейся скидки. И поменять эту логику в случае необходимости - теперь задача администратора сайта, а не программиста.
Бонусом - возможность добавления какой угодно дополнительной логики: а если сегодня четверг и нечётный месяц, то...
Вот для этого и нужен рул - вынести бизнес-логику из кода.
И php-фильтр тут не причем.

За devel, включенный на проде - надо наказывать материально.

Аватар пользователя multpix multpix 11 июня 2017 в 19:01
1

Делая сайты на базе drupal, мы сталкиваемся с тем,
что возникшую задачу можно решить несколькими различными способами.

Помимо прочих сопутствующих задаче условий, важнейшим является компетенция разработчика.
Косвенно о ней можно судить по методу решения поставленной задачи))

Но спор не о наших скилах а о принципах разработки.

Так, откинув несущественное мы придем к простому принципу:
база данных - для данных.

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

Однако, это не повод сей принцип не принимать в расчет.
Хорошей практикой будет учитывать его в своей работе.
Тем паче, это же мы видим и в развитии самого drupal от версии к версии.

Те же настройки сайта, это не данные но они в бд, но в 8-ке у нас уже есть конфиги,
читай - возможность хранить свои настройки в файловой системе,
(где им в принципе самое и место).

Из тех-же шаблонов уезжает логика и вызовы в БД.

Исполняемый код в БД - не лучшее решение.
Да есть такая возможность, но так-же есть возможность этого не делать для своего функционала.

Все упирается в компетенцию исполнителя работ.
Тут самое простое и быстрое на первый взгляд решение - не всегда оптимальное и безопасное.

Это жизнь - костыли были есть и будут.
Но это не повод постоянно с ними жить и защищать такой метод.

Вывод по сабжу темы:
с php_filter возможно решать локальные задачки,
но получив работающий функ-л, важно знать - это первейший кандидат на рефакторинг.
Так зачем делать двойную работу?
Имеет смысл делать правильно изначально))

Аватар пользователя vbard vbard 22 августа 2017 в 14:31

Согласен с ТС полностью: использовать php фильтр не стОит. Лучшее что можно с ним сделать - отключить.
Действительно, бывают моменты, когда он может выручить, но следует всеми силами этого избегать.
Для хейтеров ТС - ребята, это не секта, это опыт. Надеюсь вы к этому тоже придёте. А не придёте - у нас работы прибавится, что тоже не может не радовать Smile Как раз сейчас такой экземпляр на поддержке.
Когда видишь в логах
Strict warning: Only variables should be passed by reference в функции eval() (строка 19 в файле /home/webmaster/domains/domain.com/html/modules/php/php.module(80) : eval()'d code).
а в боди ноды

<?php<div id="catalog">
<?php print create_jplayer_from_vocabulary('playlist2');?>
</div>
<?php if (block_get_blocks_by_region('triptych_middle')): ?>
<?php  
print render(block_get_blocks_by_region('triptych_middle')); ?>
<?php 
endif; ?>

чувствуется уверенность в завтрашнем дне Smile

Аватар пользователя Никки Никки 15 декабря 2020 в 12:30

От половины этих пунктов можно запросто избавиться, если в поле php-фильтра писать не код, а инклуд файла, в котором код. А сам файл хранить в файловой структуре сайта. У меня для этого отдельная папочка создана. И в комментариях к каждому файлу даю ссыль на представление, куда этот файл инклудится.
Не спорю с тем, что код в БД (даже если это одна строчка инклуда) всё равно не фонтан. И eval() не фонтан. Вообще, решение не фонтан. Но бывает нужно такую ерунду сделать, из-за которой городить огород, используя предложенные альтернативы, кажется потерей времени. Жаль, что такой фичи уже нет в Д8 и дальше.

Аватар пользователя sudo sudo 15 января 2021 в 18:16

Все здорово и понятно, но как быть, если через php include() в Body подгружается контент? Причем аж 22 с лишним тыщи единиц?

Аватар пользователя sudo sudo 15 января 2021 в 23:31

gun_dose wrote:
На дворе 2021 год. Если тебе приходится использовать include, значит ты решаешь задачу неправильно.

В каждую ноду надо подгружать чистенький html, формируемый в источнике, не связанном с друпалом. Причем периодически приходится обновлять по несколько тысяч нод.
Теоретически можно и вручную копипастить, а можно инклудом всасывать html в поле. Из двух зол выбрал меньшее. За 10 лет проблем с сайтом на семерке не было, поскольку доступ только админский.
Если есть какие толковые соображения, буду рад выслушать.